Autosave: 20260224-132008

This commit is contained in:
Flatlogic Bot 2026-02-24 13:20:09 +00:00
parent d9aee95dfc
commit 97eb5bd10b
14 changed files with 796 additions and 242 deletions

View File

@ -11,6 +11,6 @@ class ValueTagAdmin(admin.ModelAdmin):
@admin.register(Profile) @admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin): class ProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'professional_headline', 'transition_status', 'location_city') list_display = ('user', 'gamer_tag', 'primary_game', 'rank', 'location_city')
filter_horizontal = ('intents', 'value_tags') filter_horizontal = ('intents', 'value_tags')

View File

@ -0,0 +1,27 @@
# Generated by Django 5.2.7 on 2026-02-17 19:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0013_alter_profile_gamer_tag_alter_profile_platform_and_more'),
]
operations = [
migrations.RenameField(
model_name='profile',
old_name='accountability_streak',
new_name='win_streak',
),
migrations.RemoveField(
model_name='profile',
name='transition_status',
),
migrations.AlterField(
model_name='post',
name='post_type',
field=models.CharField(choices=[('lfg', 'Looking for Group'), ('highlight', 'Match Highlight'), ('strategy', 'Strategy/Meta'), ('climb_update', 'Rank Progress'), ('hardware', 'Setup/Hardware'), ('vibe_check', 'Vibe Check')], default='lfg', max_length=20),
),
]

View File

@ -45,17 +45,9 @@ class Profile(models.Model):
('nintendo', 'Nintendo Switch'), ('nintendo', 'Nintendo Switch'),
('mobile', 'Mobile'), ('mobile', 'Mobile'),
] ]
TRANSITION_CHOICES = [
('none', 'Stable'),
('post-divorce', 'Post-Divorce'),
('relocating', 'Relocating'),
('career-change', 'Career Change'),
('new-in-town', 'New in Town'),
]
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
professional_headline = models.CharField(max_length=255, blank=True) professional_headline = models.CharField(max_length=255, blank=True)
transition_status = models.CharField(max_length=50, choices=TRANSITION_CHOICES, default='none')
bio = models.TextField(blank=True) bio = models.TextField(blank=True)
location_city = models.CharField(max_length=100, blank=True) location_city = models.CharField(max_length=100, blank=True)
intents = models.ManyToManyField(Intent, blank=True) intents = models.ManyToManyField(Intent, blank=True)
@ -71,7 +63,7 @@ class Profile(models.Model):
preferred_role = models.CharField(max_length=100, blank=True) preferred_role = models.CharField(max_length=100, blank=True)
# Momentum & Engagement # Momentum & Engagement
accountability_streak = models.IntegerField(default=0) win_streak = models.IntegerField(default=0)
# Auth & Security # Auth & Security
is_email_verified = models.BooleanField(default=False) is_email_verified = models.BooleanField(default=False)
@ -304,17 +296,17 @@ class Block(models.Model):
class Post(models.Model): class Post(models.Model):
POST_TYPE_CHOICES = [ POST_TYPE_CHOICES = [
('reflection', 'Reflection'), ('lfg', 'Looking for Group'),
('looking_for', 'Looking For'), ('highlight', 'Match Highlight'),
('offering', 'Offering'), ('strategy', 'Strategy/Meta'),
('event_invite', 'Event Invite'), ('climb_update', 'Rank Progress'),
('progress_update', 'Progress Update'), ('hardware', 'Setup/Hardware'),
('skill_share', 'Skill Share'), ('vibe_check', 'Vibe Check'),
] ]
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts') author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
content = models.TextField() content = models.TextField()
image = models.ImageField(upload_to='posts/', blank=True, null=True) image = models.ImageField(upload_to='posts/', blank=True, null=True)
post_type = models.CharField(max_length=20, choices=POST_TYPE_CHOICES, default='reflection') post_type = models.CharField(max_length=20, choices=POST_TYPE_CHOICES, default='lfg')
timestamp = models.DateTimeField(auto_now_add=True) timestamp = models.DateTimeField(auto_now_add=True)
class Meta: class Meta:

View File

@ -14,7 +14,7 @@
<!-- Bootstrap Icons --> <!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css">
<!-- Custom CSS --> <!-- Custom CSS -->
<link rel="stylesheet" href="{% static 'css/custom.css' %}"> <link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
{% block head %}{% endblock %} {% block head %}{% endblock %}
</head> </head>
@ -22,7 +22,7 @@
<nav class="navbar navbar-expand-lg sticky-top py-2"> <nav class="navbar navbar-expand-lg sticky-top py-2">
<div class="container-fluid px-lg-5"> <div class="container-fluid px-lg-5">
<a class="navbar-brand brand-font d-flex align-items-center" href="/"> <a class="navbar-brand brand-font d-flex align-items-center" href="/">
<img src="{% static 'core/images/logo.png' %}?v={{ deployment_timestamp }}" alt="Roster Logo" style="height: 48px; filter: drop-shadow(0 0 10px rgba(0, 180, 219, 0.3));"> <img src="{% static 'core/images/logo.png' %}?v={{ deployment_timestamp }}" alt="Roster Logo" style="height: 48px; filter: drop-shadow(0 0 15px rgba(0, 210, 255, 0.5));">
</a> </a>
<button class="navbar-toggler border-0 text-white" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> <button class="navbar-toggler border-0 text-white" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<i class="bi bi-list fs-1"></i> <i class="bi bi-list fs-1"></i>

View File

@ -7,9 +7,9 @@
<div class="container"> <div class="container">
<div class="row justify-content-center text-center"> <div class="row justify-content-center text-center">
<div class="col-lg-8"> <div class="col-lg-8">
<h1 class="brand-font display-4 mb-4">Our Mission</h1> <h1 class="brand-font display-4 mb-4">The Mission</h1>
<p class="lead text-slate fs-4">Roster is a platform for intentional beauty connections, ritual sharing, and community growth.</p> <p class="lead text-slate fs-4">Roster is built for the squad-less, the solo-queuers, and the players tired of random teammate roulette.</p>
<p class="text-muted">Not a dating app — a high-trust social connection ecosystem centered on shared values, life goals, activities, and authentic engagement.</p> <p class="text-muted">We believe gaming is at its best when you're playing with a team that matches your rank, shares your schedule, and fits your vibe. No more toxic lobbies, no more silent comms — just better games.</p>
</div> </div>
</div> </div>
</div> </div>
@ -20,20 +20,20 @@
<div class="row g-4"> <div class="row g-4">
<div class="col-md-4"> <div class="col-md-4">
<div class="card h-100 border-0 shadow-sm p-4"> <div class="card h-100 border-0 shadow-sm p-4">
<h3 class="brand-font h4">High Trust</h3> <h3 class="brand-font h4">Skill Sync</h3>
<p>Verified members and moderated communities ensure a safe and respectful environment.</p> <p>We match you based on actual rank and role data, ensuring you're never the odd one out in your own squad.</p>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="card h-100 border-0 shadow-sm p-4"> <div class="card h-100 border-0 shadow-sm p-4">
<h3 class="brand-font h4">Value Centered</h3> <h3 class="brand-font h4">Schedule Overlap</h3>
<p>Match based on shared values like growth, community, and adventure.</p> <p>Stop waiting for friends to come online. Find players who play when you do, whether it's 3 PM or 3 AM.</p>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="card h-100 border-0 shadow-sm p-4"> <div class="card h-100 border-0 shadow-sm p-4">
<h3 class="brand-font h4">Intent Driven</h3> <h3 class="brand-font h4">Vibe Check</h3>
<p>Clearly state what you're looking for: networking, friendship, or activity partners.</p> <p>Competitive, casual, or somewhere in between? Filter by playstyle and personality to find your perfect team.</p>
</div> </div>
</div> </div>
</div> </div>
@ -42,7 +42,7 @@
<section class="py-5 bg-sand"> <section class="py-5 bg-sand">
<div class="container text-center"> <div class="container text-center">
<h2 class="brand-font mb-4">Ready to find your community?</h2> <h2 class="brand-font mb-4">Ready to find your squad?</h2>
<a href="{% url 'signup' %}" class="btn btn-primary-cg btn-lg">Join Roster</a> <a href="{% url 'signup' %}" class="btn btn-primary-cg btn-lg">Join Roster</a>
</div> </div>
</section> </section>

View File

@ -45,8 +45,8 @@
<div class="d-flex gap-4 mb-4"> <div class="d-flex gap-4 mb-4">
<img src="{{ user.profile.get_avatar_url }}" class="rounded-circle" width="48" height="48" style="object-fit: cover; opacity: 0.9; border: 2px solid var(--r-cyan);"> <img src="{{ user.profile.get_avatar_url }}" class="rounded-circle" width="48" height="48" style="object-fit: cover; opacity: 0.9; border: 2px solid var(--r-cyan);">
<div class="flex-grow-1"> <div class="flex-grow-1">
<label class="small fw-bold text-muted mb-2">Share your latest beauty breakthrough or find your ritual squad</label> <label class="small fw-bold text-muted mb-2">Share a highlight, a new strat, or look for a group</label>
<textarea name="content" class="form-control border-0 bg-transparent" placeholder="What's your ritual today? Sharing a discovery or looking for advice..." rows="2" style="resize: none;"></textarea> <textarea name="content" class="form-control border-0 bg-transparent" placeholder="What's on your mind? LFG, highlight, or meta discussion..." rows="2" style="resize: none;"></textarea>
</div> </div>
</div> </div>
<div class="d-flex justify-content-between align-items-center pt-2"> <div class="d-flex justify-content-between align-items-center pt-2">
@ -81,7 +81,7 @@
<a href="{% url 'profile_detail' profile.user.username %}" class="text-decoration-none"> <a href="{% url 'profile_detail' profile.user.username %}" class="text-decoration-none">
<img src="{{ profile.get_avatar_url }}" class="rounded-circle mb-3" width="56" height="56" style="object-fit: cover; border: 2px solid var(--r-cyan);"> <img src="{{ profile.get_avatar_url }}" class="rounded-circle mb-3" width="56" height="56" style="object-fit: cover; border: 2px solid var(--r-cyan);">
<h6 class="mb-1 small fw-bold text-truncate text-white">{{ profile.user.first_name }} {{ profile.user.last_name|slice:":1" }}.</h6> <h6 class="mb-1 small fw-bold text-truncate text-white">{{ profile.user.first_name }} {{ profile.user.last_name|slice:":1" }}.</h6>
<p class="small text-muted mb-3 text-truncate">{{ profile.primary_game.name|default:"Beauty Enthusiast" }}</p> <p class="small text-muted mb-3 text-truncate">{{ profile.primary_game.name|default:"Player" }}</p>
</a> </a>
<div class="d-grid"> <div class="d-grid">
{% if profile.user.id in following_ids %} {% if profile.user.id in following_ids %}
@ -172,7 +172,7 @@
<span class="badge bg-light text-dark rounded-pill small">{{ stats.unread_messages }}</span> <span class="badge bg-light text-dark rounded-pill small">{{ stats.unread_messages }}</span>
</div> </div>
<div class="stat-item border-0 mb-2 d-flex justify-content-between"> <div class="stat-item border-0 mb-2 d-flex justify-content-between">
<span class="small text-muted">Accountability Streak</span> <span class="small text-muted">Win Streak</span>
<span class="fw-bold text-sage small">{{ stats.streak }} 🔥</span> <span class="fw-bold text-sage small">{{ stats.streak }} 🔥</span>
</div> </div>
<div class="stat-item border-0 mb-3 d-flex justify-content-between"> <div class="stat-item border-0 mb-3 d-flex justify-content-between">
@ -223,70 +223,158 @@
</div> </div>
{% else %} {% else %}
<!-- Anonymous Landing Page --> <!-- 1) HERO SECTION -->
<section class="hero-section py-5"> <section class="hero-gaming py-5">
<div class="container py-5"> <div class="container py-5 text-center position-relative" style="z-index: 2;">
<div class="row justify-content-center"> <div class="row justify-content-center py-5">
<div class="col-lg-10 text-center"> <div class="col-lg-10">
<h1 class="hero-title">Build your ultimate Roster.</h1> <h1 class="hero-title mb-3">Stop Solo Queueing.<br>Build Your Squad.</h1>
<p class="lead text-muted mb-5 px-lg-5" style="font-size: 1.5rem;">Connect with the best in personalized beauty. Find your ritual, share your journey, and build your squad.</p> <p class="lead text-silver-dim mb-5 px-lg-5 mx-auto" style="max-width: 800px; font-size: 1.25rem;">Roster matches you with teammates based on game, rank, role, schedule, and vibe — so you never drop into a match alone again.</p>
<div class="d-flex justify-content-center gap-4"> <div class="d-flex justify-content-center gap-3 flex-wrap">
<a href="{% url 'signup' %}" class="btn btn-neon">Join Roster</a> <a href="{% url 'signup' %}" class="btn btn-neon px-5">Find My Squad</a>
<a href="{% url 'about' %}" class="btn btn-outline-cg">Learn More</a> <a href="#how-it-works" class="btn btn-outline-cg px-5">See How It Works</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="py-5"> <!-- 2) PAIN SECTION -->
<section class="pain-section py-5">
<div class="container py-5"> <div class="container py-5">
<div class="d-flex justify-content-between align-items-end mb-5 flex-wrap gap-4"> <div class="row align-items-center g-5">
<div> <div class="col-lg-5">
<h2 class="text-metallic h1 mb-2">Discover Experts & Enthusiasts</h2> <h2 class="text-metallic h1 mb-4">Random teammates ruin ranked.</h2>
<p class="text-muted mb-0">Personalities aligned with your beauty goals and interests.</p> <p class="text-muted lead mb-0">The solo queue experience is broken. We've all been there:</p>
</div> </div>
<div class="d-flex overflow-auto pb-2 gap-3"> <div class="col-lg-7">
<a href="{% url 'home' %}" class="btn btn-sm {% if not current_intent %}btn-neon{% else %}btn-outline-cg border-0{% endif %} rounded-pill px-4">All Profiles</a> <div class="row g-4">
{% for intent in intents %} <div class="col-md-6">
<a href="?intent={{ intent.name }}" class="btn btn-sm {% if current_intent == intent.name %}btn-neon{% else %}btn-outline-cg border-0{% endif %} rounded-pill px-4">{{ intent.name }}</a> <div class="pain-point h-100">
{% endfor %} <h5 class="text-white mb-2">No comms</h5>
</div> <p class="small text-muted mb-0">Silence in the lobby leads to chaos in the match.</p>
</div>
<div class="row g-5">
{% for profile in profiles %}
<div class="col-md-6 col-lg-4">
<div class="card p-5 h-100 d-flex flex-column border-0">
<div class="d-flex align-items-start mb-4">
<img src="{{ profile.get_avatar_url }}" alt="{{ profile.user.get_full_name }}" class="profile-avatar me-4" style="width: 64px; height: 64px; border: 2px solid var(--r-cyan);">
<div class="pt-1">
{% if profile.primary_game %}
<span class="intent-badge mb-2 d-inline-block">{{ profile.primary_game.name }}</span>
{% endif %}
<h3 class="h5 mb-1 fw-bold text-white">{{ profile.user.first_name }} {{ profile.user.last_name|slice:":1" }}.</h3>
<p class="text-muted small mb-0"><i class="bi bi-geo-alt me-2"></i> {{ profile.location_city }}</p>
</div> </div>
</div> </div>
<p class="fw-bold text-cyan mb-3">{{ profile.platform|upper|default:"BEAUTY" }} • {{ profile.rank|default:"Enthusiast" }}</p> <div class="col-md-6">
<p class="text-muted small mb-4 line-clamp-3">{{ profile.bio }}</p> <div class="pain-point h-100">
<h5 class="text-white mb-2">Role chaos</h5>
<div class="mb-5 d-flex flex-wrap gap-2 mt-auto"> <p class="small text-muted mb-0">Three main DPS and no support? Every single time.</p>
{% for intent in profile.intents.all %} </div>
<span class="intent-badge">{{ intent.name }}</span>
{% endfor %}
</div> </div>
<div class="col-md-6">
<div class="d-grid mt-2"> <div class="pain-point h-100">
<a href="{% url 'signup' %}" class="btn btn-outline-cg">View Full Roster</a> <h5 class="text-white mb-2">Rank mismatch</h5>
<p class="small text-muted mb-0">Getting paired with players who aren't on your level.</p>
</div>
</div>
<div class="col-md-6">
<div class="pain-point h-100">
<h5 class="text-white mb-2">Toxic lobbies</h5>
<p class="small text-muted mb-0">Dealing with griefers and throwers instead of playing.</p>
</div>
</div> </div>
</div> </div>
<div class="mt-5 text-center text-lg-start">
<h3 class="text-neon-green h4 mb-0">Roster fixes that.</h3>
</div>
</div> </div>
{% empty %} </div>
<div class="col-12 text-center py-5"> </div>
<p class="text-muted">No profiles found yet.</p> </section>
<!-- 3) HOW IT WORKS -->
<section id="how-it-works" class="py-5">
<div class="container py-5">
<div class="text-center mb-5">
<h2 class="text-metallic h1 mb-3">How it works</h2>
<p class="text-muted">Simple, automated, and effective.</p>
</div>
<div class="row g-4">
<div class="col-lg-4">
<div class="step-card">
<div class="step-number">01</div>
<h4 class="text-white mb-3">Build your player profile</h4>
<p class="text-muted mb-0">Tell us your game, rank, role, schedule, and playstyle. It takes 2 minutes.</p>
</div>
</div> </div>
{% endfor %} <div class="col-lg-4">
<div class="step-card">
<div class="step-number">02</div>
<h4 class="text-white mb-3">Get matched intelligently</h4>
<p class="text-muted mb-0">Our algorithm finds players with overlapping schedules and compatible skill levels.</p>
</div>
</div>
<div class="col-lg-4">
<div class="step-card">
<div class="step-number">03</div>
<h4 class="text-white mb-3">Lock in your squad</h4>
<p class="text-muted mb-0">Message your matches, schedule sessions, and start climbing the ranks together.</p>
</div>
</div>
</div>
</div>
</section>
<!-- 4) DIFFERENTIATION GRID -->
<section class="py-5 bg-glass border-glass border-start-0 border-end-0">
<div class="container py-5">
<div class="text-center mb-5">
<h2 class="text-metallic h1 mb-3">The Roster Edge</h2>
<p class="text-muted">Why settling for standard matchmaking is losing you Elo.</p>
</div>
<div class="diff-grid mx-auto" style="max-width: 900px;">
<div class="diff-header d-none d-md-grid" style="grid-template-columns: 2fr 1fr 1fr 1.2fr; align-items: center;">
<div>Feature</div>
<div class="text-center">Discord</div>
<div class="text-center">In-Game</div>
<div class="text-center text-neon-green">Roster</div>
</div>
<div class="diff-row">
<div class="diff-label">Compatibility Matching</div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value diff-roster"><i class="bi bi-check2"></i></div>
</div>
<div class="diff-row">
<div class="diff-label">Role Balancing</div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value text-danger small">Limited</div>
<div class="diff-value diff-roster"><i class="bi bi-check2"></i></div>
</div>
<div class="diff-row">
<div class="diff-label">Schedule Overlap</div>
<div class="diff-value text-muted small">Manual</div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value diff-roster"><i class="bi bi-check2"></i></div>
</div>
<div class="diff-row">
<div class="diff-label">Squad Building</div>
<div class="diff-value text-muted small">Chaotic</div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value diff-roster"><i class="bi bi-check2"></i></div>
</div>
<div class="diff-row">
<div class="diff-label">Structured Sessions</div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value text-muted"><i class="bi bi-dash"></i></div>
<div class="diff-value diff-roster"><i class="bi bi-check2"></i></div>
</div>
</div>
</div>
</section>
<!-- 5) FINAL CTA SECTION -->
<section class="cta-final text-center">
<div class="container">
<h2 class="hero-title mb-4" style="font-size: 4rem;">Your next win starts with<br>the right squad.</h2>
<div class="mt-5">
<a href="{% url 'signup' %}" class="btn btn-neon btn-lg px-5 py-3 shadow-lg" style="font-size: 1.5rem;">Find My Squad</a>
</div> </div>
</div> </div>
</section> </section>

View File

@ -86,14 +86,14 @@
</div> </div>
</div> </div>
<div class="col-md-4 border-end border-light"> <div class="col-md-4 border-end border-light">
<h6 class="text-muted text-uppercase extra-small fw-bold mb-3 ls-1">Values</h6> <h6 class="text-muted text-uppercase extra-small fw-bold mb-3 ls-1">Traits</h6>
<div class="d-flex flex-wrap justify-content-center gap-2"> <div class="d-flex flex-wrap justify-content-center gap-2">
{% for tag in target_user.profile.value_tags.all %} {% for tag in target_user.profile.value_tags.all %}
<span class="intent-badge border-0" style="background: var(--cg-sand-secondary);"> <span class="intent-badge border-0" style="background: var(--cg-sand-secondary);">
#{{ tag.name }} #{{ tag.name }}
</span> </span>
{% empty %} {% empty %}
<small class="text-muted small">No values shared</small> <small class="text-muted small">No traits shared</small>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
@ -111,7 +111,7 @@
</span> </span>
{% endif %} {% endif %}
<span class="intent-badge border-0 text-sage" style="background: var(--cg-sand-primary);"> <span class="intent-badge border-0 text-sage" style="background: var(--cg-sand-primary);">
{{ target_user.profile.accountability_streak }} 🔥 Streak {{ target_user.profile.win_streak }} 🔥 Win Streak
</span> </span>
</div> </div>
</div> </div>

View File

@ -29,7 +29,7 @@ def get_dashboard_context(request):
'pending_connections': ConnectionRequest.objects.filter(to_user=request.user, status='pending').count(), 'pending_connections': ConnectionRequest.objects.filter(to_user=request.user, status='pending').count(),
'upcoming_events_count': request.user.rsvps.filter(status='going', event__start_datetime__gt=timezone.now()).count(), 'upcoming_events_count': request.user.rsvps.filter(status='going', event__start_datetime__gt=timezone.now()).count(),
'completion_percentage': request.user.profile.profile_completion_percentage, 'completion_percentage': request.user.profile.profile_completion_percentage,
'streak': request.user.profile.accountability_streak, 'streak': request.user.profile.win_streak,
'followers_count': request.user.profile.followers_count, 'followers_count': request.user.profile.followers_count,
'following_count': request.user.profile.following_count, 'following_count': request.user.profile.following_count,
} }
@ -53,6 +53,7 @@ def get_dashboard_context(request):
"following_ids": following_ids, "following_ids": following_ids,
"post_types": Post.POST_TYPE_CHOICES, "post_types": Post.POST_TYPE_CHOICES,
"current_time": timezone.now(), "current_time": timezone.now(),
"deployment_timestamp": int(timezone.now().timestamp()),
"project_name": "Roster", "project_name": "Roster",
} }
@ -62,10 +63,10 @@ def home(request):
# Simple logic to seed data for the first run # Simple logic to seed data for the first run
if not Intent.objects.exists(): if not Intent.objects.exists():
intents_data = [ intents_data = [
('Friendship', 'bi-people'), ('Competitive', 'bi-trophy'),
('Networking', 'bi-briefcase'), ('Casual/Social', 'bi-controller'),
('Activity Partner', 'bi-bicycle'), ('Ranked Climb', 'bi-graph-up-arrow'),
('Accountability', 'bi-check-circle') ('Co-op/Story', 'bi-people-fill')
] ]
for name, icon in intents_data: for name, icon in intents_data:
Intent.objects.create(name=name, icon=icon) Intent.objects.create(name=name, icon=icon)
@ -76,8 +77,7 @@ def home(request):
p = Profile.objects.create( p = Profile.objects.create(
user=demo_user, user=demo_user,
professional_headline='Architect & Urban Planner', professional_headline='Architect & Urban Planner',
transition_status='new-in-town', bio='Passionate about competitive FPS. Recently moved here and looking for a long-term squad.',
bio='Passionate about sustainable cities. Recently moved here from Chicago and looking for local communities.',
location_city='Austin, TX', location_city='Austin, TX',
) )
p.intents.add(Intent.objects.get(name='Networking')) p.intents.add(Intent.objects.get(name='Networking'))
@ -86,8 +86,7 @@ def home(request):
p2 = Profile.objects.create( p2 = Profile.objects.create(
user=demo_user2, user=demo_user2,
professional_headline='UX Researcher | Growth Mindset', professional_headline='UX Researcher | Growth Mindset',
transition_status='post-divorce', bio='Rediscovering my love for MOBAs. Seeking competitive matches and team coordination.',
bio='Rediscovering my love for hiking and photography. Seeking authentic connections and shared growth.',
location_city='Austin, TX', location_city='Austin, TX',
) )
p2.intents.add(Intent.objects.get(name='Friendship')) p2.intents.add(Intent.objects.get(name='Friendship'))
@ -122,7 +121,7 @@ def create_post(request):
if request.method == 'POST': if request.method == 'POST':
content = request.POST.get('content') content = request.POST.get('content')
image = request.FILES.get('image') image = request.FILES.get('image')
post_type = request.POST.get('post_type', 'reflection') post_type = request.POST.get('post_type', 'lfg')
if content or image: if content or image:
Post.objects.create(author=request.user, content=content, image=image, post_type=post_type) Post.objects.create(author=request.user, content=content, image=image, post_type=post_type)
return redirect('home') return redirect('home')
@ -354,7 +353,7 @@ def matches(request, tab=None):
if sort_by == 'newest': if sort_by == 'newest':
queryset = queryset.order_by('-date_joined') queryset = queryset.order_by('-date_joined')
elif sort_by == 'aligned': elif sort_by == 'aligned':
queryset = queryset.order_by('-profile__accountability_streak') queryset = queryset.order_by('-profile__win_streak')
queryset = queryset.select_related('profile').prefetch_related('profile__intents').distinct() queryset = queryset.select_related('profile').prefetch_related('profile__intents').distinct()

View File

@ -1,21 +1,21 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap');
:root { :root {
--r-navy-deep: #050A18; --r-navy-deep: #020b1a;
--r-navy-soft: #0C162D; --r-navy-soft: #0a192f;
--r-cyan: #00B4DB; --r-cyan: #00d2ff;
--r-cyan-glow: rgba(0, 180, 219, 0.4); --r-cyan-glow: rgba(0, 210, 255, 0.45);
--r-neon-green: #39FF14; --r-neon-green: #14ff00;
--r-neon-glow: rgba(57, 255, 20, 0.4); --r-neon-glow: rgba(20, 255, 0, 0.4);
--r-silver: #E0E0E0; --r-silver: #e6e7e8;
--r-silver-dim: #A0A0A0; --r-silver-dim: #9ca3af;
--r-glass-bg: rgba(255, 255, 255, 0.03); --r-glass-bg: rgba(255, 255, 255, 0.04);
--r-glass-border: rgba(224, 224, 224, 0.2); --r-glass-border: rgba(224, 224, 224, 0.15);
--r-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); --r-transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
} }
body { body {
background: radial-gradient(circle at top center, #101B38 0%, var(--r-navy-deep) 100%); background: radial-gradient(circle at 50% 0%, #0d2137 0%, var(--r-navy-deep) 100%);
background-attachment: fixed; background-attachment: fixed;
color: var(--r-silver); color: var(--r-silver);
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
@ -27,144 +27,368 @@ body {
h1, h2, h3, h4, .brand-font { h1, h2, h3, h4, .brand-font {
font-family: 'Playfair Display', serif; font-family: 'Playfair Display', serif;
letter-spacing: -0.01em; letter-spacing: -0.02em;
} }
/* Metallic Text Effect */ /* Metallic Text Effect */
.text-metallic { .text-metallic {
background: linear-gradient(135deg, #FFFFFF 0%, var(--r-silver) 50%, var(--r-silver-dim) 100%); background: linear-gradient(to bottom, #ffffff 0%, var(--r-silver) 50%, #888888 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
} }
/* Glassmorphism Navbar */ /* Glassmorphism Navbar */
.navbar { .navbar {
background: rgba(5, 10, 24, 0.85) !important; background: rgba(2, 11, 26, 0.8) !important;
backdrop-filter: blur(20px); backdrop-filter: blur(24px) saturate(180%);
-webkit-backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(24px) saturate(180%);
border-bottom: 1px solid var(--r-glass-border); border-bottom: 1px solid var(--r-glass-border);
padding: 1rem 0; padding: 0.75rem 0;
} }
.nav-link { .nav-link {
color: var(--r-silver-dim) !important; color: var(--r-silver-dim) !important;
font-weight: 500; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
font-size: 0.85rem; font-size: 0.75rem;
letter-spacing: 1px; letter-spacing: 1.5px;
transition: var(--r-transition); transition: var(--r-transition);
opacity: 0.8;
} }
.nav-link:hover, .nav-link.active { .nav-link:hover, .nav-link.active {
color: var(--r-cyan) !important; color: var(--r-cyan) !important;
text-shadow: 0 0 15px var(--r-cyan-glow); opacity: 1;
text-shadow: 0 0 20px var(--r-cyan-glow);
} }
/* Custom Buttons */ /* Custom Buttons */
.btn-neon { .btn-neon {
background: linear-gradient(135deg, var(--r-cyan) 0%, #0083B0 100%); background: linear-gradient(135deg, var(--r-cyan) 0%, #0076ad 100%);
color: white !important; color: #020b1a !important;
border: none; border: none;
font-weight: 700; font-weight: 800;
padding: 0.9rem 2.2rem; padding: 0.9rem 2.4rem;
border-radius: 12px; border-radius: 10px;
transition: var(--r-transition); transition: var(--r-transition);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 1px; letter-spacing: 1.5px;
box-shadow: 0 8px 20px var(--r-cyan-glow); box-shadow: 0 0 20px var(--r-cyan-glow);
position: relative;
overflow: hidden;
}
.btn-neon::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255,255,255,0.2), transparent);
transform: rotate(45deg);
transition: 0.8s;
}
.btn-neon:hover::after {
left: 120%;
} }
.btn-neon:hover { .btn-neon:hover {
transform: translateY(-3px); transform: translateY(-4px) scale(1.02);
box-shadow: 0 12px 30px var(--r-cyan-glow); box-shadow: 0 0 35px var(--r-cyan-glow);
color: white !important;
} }
.btn-outline-cg { .btn-outline-cg {
border: 2px solid var(--r-silver-dim); border: 1.5px solid var(--r-glass-border);
color: var(--r-silver); color: var(--r-silver);
font-weight: 600; font-weight: 700;
padding: 0.8rem 2rem; padding: 0.8rem 2.2rem;
border-radius: 12px; border-radius: 10px;
transition: var(--r-transition); transition: var(--r-transition);
background: var(--r-glass-bg);
} }
.btn-outline-cg:hover { .btn-outline-cg:hover {
border-color: var(--r-neon-green); border-color: var(--r-neon-green);
color: var(--r-neon-green); color: var(--r-neon-green) !important;
box-shadow: 0 0 20px var(--r-neon-glow); box-shadow: 0 0 25px var(--r-neon-glow);
background: transparent; background: rgba(20, 255, 0, 0.05);
transform: translateY(-2px);
}
/* Primary CG Button (Follow/Post) */
.btn-primary-cg {
background: var(--r-cyan);
color: #020b1a !important;
font-weight: 800;
border: none;
border-radius: 8px;
padding: 0.5rem 1.5rem;
transition: var(--r-transition);
}
.btn-primary-cg:hover {
box-shadow: 0 0 15px var(--r-cyan-glow);
transform: scale(1.05);
} }
/* Cards & Panels */ /* Cards & Panels */
.card, .profile-card, .glass-panel { .card, .profile-card, .glass-panel, .stat-widget {
background: rgba(255, 255, 255, 0.02) !important; background: rgba(10, 25, 47, 0.4) !important;
backdrop-filter: blur(15px); backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(16px);
border: 1px solid var(--r-glass-border) !important; border: 1px solid var(--r-glass-border) !important;
border-radius: 28px; border-radius: 20px;
transition: var(--r-transition); transition: var(--r-transition);
color: var(--r-silver) !important; color: var(--r-silver) !important;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
} }
.card:hover { .card:hover {
border-color: var(--r-cyan) !important; border-color: rgba(0, 210, 255, 0.3) !important;
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5); background: rgba(10, 25, 47, 0.6) !important;
background: rgba(255, 255, 255, 0.04) !important; transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0,0,0,0.4);
}
/* Badges */
.intent-badge, .post-badge {
background: rgba(20, 255, 0, 0.1);
color: var(--r-neon-green);
border: 1px solid rgba(20, 255, 0, 0.3);
padding: 0.25rem 0.75rem;
border-radius: 6px;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
} }
/* Hero Title */ /* Hero Title */
.hero-title { .hero-title {
font-size: 5rem; font-size: 6rem;
font-weight: 800; font-weight: 900;
line-height: 1.1; line-height: 1;
margin-bottom: 2rem; margin-bottom: 2.5rem;
background: linear-gradient(135deg, #FFFFFF 0%, var(--r-silver) 40%, var(--r-cyan) 100%); background: linear-gradient(135deg, #ffffff 0%, var(--r-silver) 30%, var(--r-cyan) 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
filter: drop-shadow(0 10px 20px rgba(0,0,0,0.4));
} }
@media (max-width: 991px) {
.hero-title { font-size: 3.5rem; }
}
/* Sidebar Nav */
.sidebar-nav .nav-link {
display: flex;
align-items: center;
gap: 12px;
padding: 0.8rem 1rem;
border-radius: 10px;
margin-bottom: 0.5rem;
text-transform: none;
font-size: 0.9rem;
letter-spacing: 0;
}
.sidebar-nav .nav-link i {
font-size: 1.2rem;
}
.sidebar-nav .nav-link:hover, .sidebar-nav .nav-link.active {
background: rgba(0, 210, 255, 0.1);
color: var(--r-cyan) !important;
border-left: 3px solid var(--r-cyan);
}
/* Horizontal Scroll for Suggestions */
.horizontal-scroll {
display: flex;
gap: 1.5rem;
overflow-x: auto;
padding: 1rem 0 2rem;
scrollbar-width: none;
}
.horizontal-scroll::-webkit-scrollbar { display: none; }
.suggestion-card {
min-width: 160px;
background: rgba(255,255,255,0.02);
padding: 1.5rem;
border-radius: 20px;
border: 1px solid var(--r-glass-border);
transition: var(--r-transition);
}
.suggestion-card:hover {
background: rgba(0, 210, 255, 0.05);
border-color: var(--r-cyan);
}
/* Profile Avatars */
.profile-avatar {
border: 2px solid var(--r-cyan);
box-shadow: 0 0 15px var(--r-cyan-glow);
border-radius: 12px;
}
/* Global Overrides */
.bg-light, .bg-white { background-color: transparent !important; }
.text-muted { color: var(--r-silver-dim) !important; }
.text-cyan { color: var(--r-cyan) !important; }
/* Form Styling */ /* Form Styling */
.form-control, .form-select { .form-control, .form-select {
background: rgba(255, 255, 255, 0.05) !important; background: rgba(255, 255, 255, 0.03) !important;
border: 1px solid var(--r-glass-border) !important; border: 1px solid var(--r-glass-border) !important;
border-radius: 14px; border-radius: 10px;
color: white !important; color: white !important;
padding: 0.9rem 1.4rem;
} }
.form-control:focus { .form-control:focus {
border-color: var(--r-cyan) !important; border-color: var(--r-cyan) !important;
box-shadow: 0 0 15px var(--r-cyan-glow); box-shadow: 0 0 20px var(--r-cyan-glow);
background: rgba(255, 255, 255, 0.08) !important;
} }
/* Mobile Nav Enhancement */ /* Gaming Native Landing Page Styles */
.bottom-nav { .hero-gaming {
background: rgba(5, 10, 24, 0.95); position: relative;
backdrop-filter: blur(25px); background: radial-gradient(circle at 50% 50%, #0a2e38 0%, #021a24 100%);
border-top: 1px solid var(--r-glass-border); overflow: hidden;
height: 80px;
} }
.bottom-nav-item { .hero-gaming::before {
color: var(--r-silver-dim) !important; content: "";
transition: var(--r-transition); position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
linear-gradient(to right, rgba(0, 210, 255, 0.05) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0, 210, 255, 0.05) 1px, transparent 1px);
background-size: 50px 50px;
mask-image: radial-gradient(circle at 50% 50%, black 30%, transparent 80%);
pointer-events: none;
} }
.bottom-nav-item.active { .pain-section {
color: var(--r-cyan) !important; background: #010c12;
text-shadow: 0 0 10px var(--r-cyan-glow); border-top: 1px solid rgba(20, 255, 0, 0.1);
border-bottom: 1px solid rgba(20, 255, 0, 0.1);
} }
/* Global Overrides */ .pain-point {
.bg-light, .bg-white { background: rgba(255, 255, 255, 0.02);
background-color: transparent !important; border-left: 3px solid #ff4d4d;
padding: 1.5rem;
transition: transform 0.3s ease;
} }
.text-muted { .pain-point:hover {
color: var(--r-silver-dim) !important; transform: translateX(10px);
background: rgba(255, 77, 77, 0.05);
} }
.step-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 1rem;
padding: 2.5rem;
height: 100%;
transition: all 0.3s ease;
}
.step-card:hover {
border-color: var(--r-cyan);
box-shadow: 0 0 30px rgba(0, 210, 255, 0.1);
}
.step-number {
font-size: 3rem;
font-weight: 900;
color: rgba(255, 255, 255, 0.05);
line-height: 1;
margin-bottom: 1rem;
}
.diff-grid {
background: rgba(2, 26, 36, 0.5);
border-radius: 1.5rem;
overflow: hidden;
border: 1px solid rgba(230, 231, 232, 0.1);
}
.diff-header {
background: rgba(230, 231, 232, 0.05);
padding: 1.5rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
}
.diff-row {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1.2fr;
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
align-items: center;
}
.diff-row:last-child {
border-bottom: none;
}
.diff-label {
color: #e6e7e8;
font-weight: 500;
}
.diff-value {
text-align: center;
font-size: 1.2rem;
}
.diff-roster {
color: var(--r-green);
font-weight: bold;
text-shadow: 0 0 10px rgba(20, 255, 0, 0.3);
}
.cta-final {
background: linear-gradient(180deg, #021a24 0%, #00d2ff 400%);
padding: 8rem 0;
}
@media (max-width: 768px) {
.diff-row {
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.diff-label {
grid-column: span 2;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
padding-bottom: 0.5rem;
}
}
.text-neon-green { color: var(--r-neon-green) !important; }
.text-cyan { color: var(--r-cyan) !important; }
.text-silver { color: var(--r-silver) !important; }
.bg-glass { background: var(--r-glass-bg) !important; backdrop-filter: blur(10px); }
.border-glass { border: 1px solid var(--r-glass-border) !important; }
/* Existing Sage/Sand Overrides */
.text-sage { color: var(--r-neon-green) !important; }
.bg-sage { background-color: var(--r-neon-green) !important; color: #020b1a !important; }
.text-slate, .text-dark { color: var(--r-silver) !important; }
/* Scrollbar */ /* Scrollbar */
::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--r-navy-deep); } ::-webkit-scrollbar-track { background: var(--r-navy-deep); }

View File

@ -1,21 +1,21 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap');
:root { :root {
--r-navy-deep: #050A18; --r-navy-deep: #020b1a;
--r-navy-soft: #0C162D; --r-navy-soft: #0a192f;
--r-cyan: #00B4DB; --r-cyan: #00d2ff;
--r-cyan-glow: rgba(0, 180, 219, 0.4); --r-cyan-glow: rgba(0, 210, 255, 0.45);
--r-neon-green: #39FF14; --r-neon-green: #14ff00;
--r-neon-glow: rgba(57, 255, 20, 0.4); --r-neon-glow: rgba(20, 255, 0, 0.4);
--r-silver: #E0E0E0; --r-silver: #e6e7e8;
--r-silver-dim: #A0A0A0; --r-silver-dim: #9ca3af;
--r-glass-bg: rgba(255, 255, 255, 0.03); --r-glass-bg: rgba(255, 255, 255, 0.04);
--r-glass-border: rgba(224, 224, 224, 0.2); --r-glass-border: rgba(224, 224, 224, 0.15);
--r-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); --r-transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
} }
body { body {
background: radial-gradient(circle at top center, #101B38 0%, var(--r-navy-deep) 100%); background: radial-gradient(circle at 50% 0%, #0d2137 0%, var(--r-navy-deep) 100%);
background-attachment: fixed; background-attachment: fixed;
color: var(--r-silver); color: var(--r-silver);
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
@ -27,144 +27,368 @@ body {
h1, h2, h3, h4, .brand-font { h1, h2, h3, h4, .brand-font {
font-family: 'Playfair Display', serif; font-family: 'Playfair Display', serif;
letter-spacing: -0.01em; letter-spacing: -0.02em;
} }
/* Metallic Text Effect */ /* Metallic Text Effect */
.text-metallic { .text-metallic {
background: linear-gradient(135deg, #FFFFFF 0%, var(--r-silver) 50%, var(--r-silver-dim) 100%); background: linear-gradient(to bottom, #ffffff 0%, var(--r-silver) 50%, #888888 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
} }
/* Glassmorphism Navbar */ /* Glassmorphism Navbar */
.navbar { .navbar {
background: rgba(5, 10, 24, 0.85) !important; background: rgba(2, 11, 26, 0.8) !important;
backdrop-filter: blur(20px); backdrop-filter: blur(24px) saturate(180%);
-webkit-backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(24px) saturate(180%);
border-bottom: 1px solid var(--r-glass-border); border-bottom: 1px solid var(--r-glass-border);
padding: 1rem 0; padding: 0.75rem 0;
} }
.nav-link { .nav-link {
color: var(--r-silver-dim) !important; color: var(--r-silver-dim) !important;
font-weight: 500; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
font-size: 0.85rem; font-size: 0.75rem;
letter-spacing: 1px; letter-spacing: 1.5px;
transition: var(--r-transition); transition: var(--r-transition);
opacity: 0.8;
} }
.nav-link:hover, .nav-link.active { .nav-link:hover, .nav-link.active {
color: var(--r-cyan) !important; color: var(--r-cyan) !important;
text-shadow: 0 0 15px var(--r-cyan-glow); opacity: 1;
text-shadow: 0 0 20px var(--r-cyan-glow);
} }
/* Custom Buttons */ /* Custom Buttons */
.btn-neon { .btn-neon {
background: linear-gradient(135deg, var(--r-cyan) 0%, #0083B0 100%); background: linear-gradient(135deg, var(--r-cyan) 0%, #0076ad 100%);
color: white !important; color: #020b1a !important;
border: none; border: none;
font-weight: 700; font-weight: 800;
padding: 0.9rem 2.2rem; padding: 0.9rem 2.4rem;
border-radius: 12px; border-radius: 10px;
transition: var(--r-transition); transition: var(--r-transition);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 1px; letter-spacing: 1.5px;
box-shadow: 0 8px 20px var(--r-cyan-glow); box-shadow: 0 0 20px var(--r-cyan-glow);
position: relative;
overflow: hidden;
}
.btn-neon::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255,255,255,0.2), transparent);
transform: rotate(45deg);
transition: 0.8s;
}
.btn-neon:hover::after {
left: 120%;
} }
.btn-neon:hover { .btn-neon:hover {
transform: translateY(-3px); transform: translateY(-4px) scale(1.02);
box-shadow: 0 12px 30px var(--r-cyan-glow); box-shadow: 0 0 35px var(--r-cyan-glow);
color: white !important;
} }
.btn-outline-cg { .btn-outline-cg {
border: 2px solid var(--r-silver-dim); border: 1.5px solid var(--r-glass-border);
color: var(--r-silver); color: var(--r-silver);
font-weight: 600; font-weight: 700;
padding: 0.8rem 2rem; padding: 0.8rem 2.2rem;
border-radius: 12px; border-radius: 10px;
transition: var(--r-transition); transition: var(--r-transition);
background: var(--r-glass-bg);
} }
.btn-outline-cg:hover { .btn-outline-cg:hover {
border-color: var(--r-neon-green); border-color: var(--r-neon-green);
color: var(--r-neon-green); color: var(--r-neon-green) !important;
box-shadow: 0 0 20px var(--r-neon-glow); box-shadow: 0 0 25px var(--r-neon-glow);
background: transparent; background: rgba(20, 255, 0, 0.05);
transform: translateY(-2px);
}
/* Primary CG Button (Follow/Post) */
.btn-primary-cg {
background: var(--r-cyan);
color: #020b1a !important;
font-weight: 800;
border: none;
border-radius: 8px;
padding: 0.5rem 1.5rem;
transition: var(--r-transition);
}
.btn-primary-cg:hover {
box-shadow: 0 0 15px var(--r-cyan-glow);
transform: scale(1.05);
} }
/* Cards & Panels */ /* Cards & Panels */
.card, .profile-card, .glass-panel { .card, .profile-card, .glass-panel, .stat-widget {
background: rgba(255, 255, 255, 0.02) !important; background: rgba(10, 25, 47, 0.4) !important;
backdrop-filter: blur(15px); backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(16px);
border: 1px solid var(--r-glass-border) !important; border: 1px solid var(--r-glass-border) !important;
border-radius: 28px; border-radius: 20px;
transition: var(--r-transition); transition: var(--r-transition);
color: var(--r-silver) !important; color: var(--r-silver) !important;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
} }
.card:hover { .card:hover {
border-color: var(--r-cyan) !important; border-color: rgba(0, 210, 255, 0.3) !important;
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5); background: rgba(10, 25, 47, 0.6) !important;
background: rgba(255, 255, 255, 0.04) !important; transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0,0,0,0.4);
}
/* Badges */
.intent-badge, .post-badge {
background: rgba(20, 255, 0, 0.1);
color: var(--r-neon-green);
border: 1px solid rgba(20, 255, 0, 0.3);
padding: 0.25rem 0.75rem;
border-radius: 6px;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
} }
/* Hero Title */ /* Hero Title */
.hero-title { .hero-title {
font-size: 5rem; font-size: 6rem;
font-weight: 800; font-weight: 900;
line-height: 1.1; line-height: 1;
margin-bottom: 2rem; margin-bottom: 2.5rem;
background: linear-gradient(135deg, #FFFFFF 0%, var(--r-silver) 40%, var(--r-cyan) 100%); background: linear-gradient(135deg, #ffffff 0%, var(--r-silver) 30%, var(--r-cyan) 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
filter: drop-shadow(0 10px 20px rgba(0,0,0,0.4));
} }
@media (max-width: 991px) {
.hero-title { font-size: 3.5rem; }
}
/* Sidebar Nav */
.sidebar-nav .nav-link {
display: flex;
align-items: center;
gap: 12px;
padding: 0.8rem 1rem;
border-radius: 10px;
margin-bottom: 0.5rem;
text-transform: none;
font-size: 0.9rem;
letter-spacing: 0;
}
.sidebar-nav .nav-link i {
font-size: 1.2rem;
}
.sidebar-nav .nav-link:hover, .sidebar-nav .nav-link.active {
background: rgba(0, 210, 255, 0.1);
color: var(--r-cyan) !important;
border-left: 3px solid var(--r-cyan);
}
/* Horizontal Scroll for Suggestions */
.horizontal-scroll {
display: flex;
gap: 1.5rem;
overflow-x: auto;
padding: 1rem 0 2rem;
scrollbar-width: none;
}
.horizontal-scroll::-webkit-scrollbar { display: none; }
.suggestion-card {
min-width: 160px;
background: rgba(255,255,255,0.02);
padding: 1.5rem;
border-radius: 20px;
border: 1px solid var(--r-glass-border);
transition: var(--r-transition);
}
.suggestion-card:hover {
background: rgba(0, 210, 255, 0.05);
border-color: var(--r-cyan);
}
/* Profile Avatars */
.profile-avatar {
border: 2px solid var(--r-cyan);
box-shadow: 0 0 15px var(--r-cyan-glow);
border-radius: 12px;
}
/* Global Overrides */
.bg-light, .bg-white { background-color: transparent !important; }
.text-muted { color: var(--r-silver-dim) !important; }
.text-cyan { color: var(--r-cyan) !important; }
/* Form Styling */ /* Form Styling */
.form-control, .form-select { .form-control, .form-select {
background: rgba(255, 255, 255, 0.05) !important; background: rgba(255, 255, 255, 0.03) !important;
border: 1px solid var(--r-glass-border) !important; border: 1px solid var(--r-glass-border) !important;
border-radius: 14px; border-radius: 10px;
color: white !important; color: white !important;
padding: 0.9rem 1.4rem;
} }
.form-control:focus { .form-control:focus {
border-color: var(--r-cyan) !important; border-color: var(--r-cyan) !important;
box-shadow: 0 0 15px var(--r-cyan-glow); box-shadow: 0 0 20px var(--r-cyan-glow);
background: rgba(255, 255, 255, 0.08) !important;
} }
/* Mobile Nav Enhancement */ /* Gaming Native Landing Page Styles */
.bottom-nav { .hero-gaming {
background: rgba(5, 10, 24, 0.95); position: relative;
backdrop-filter: blur(25px); background: radial-gradient(circle at 50% 50%, #0a2e38 0%, #021a24 100%);
border-top: 1px solid var(--r-glass-border); overflow: hidden;
height: 80px;
} }
.bottom-nav-item { .hero-gaming::before {
color: var(--r-silver-dim) !important; content: "";
transition: var(--r-transition); position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
linear-gradient(to right, rgba(0, 210, 255, 0.05) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0, 210, 255, 0.05) 1px, transparent 1px);
background-size: 50px 50px;
mask-image: radial-gradient(circle at 50% 50%, black 30%, transparent 80%);
pointer-events: none;
} }
.bottom-nav-item.active { .pain-section {
color: var(--r-cyan) !important; background: #010c12;
text-shadow: 0 0 10px var(--r-cyan-glow); border-top: 1px solid rgba(20, 255, 0, 0.1);
border-bottom: 1px solid rgba(20, 255, 0, 0.1);
} }
/* Global Overrides */ .pain-point {
.bg-light, .bg-white { background: rgba(255, 255, 255, 0.02);
background-color: transparent !important; border-left: 3px solid #ff4d4d;
padding: 1.5rem;
transition: transform 0.3s ease;
} }
.text-muted { .pain-point:hover {
color: var(--r-silver-dim) !important; transform: translateX(10px);
background: rgba(255, 77, 77, 0.05);
} }
.step-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 1rem;
padding: 2.5rem;
height: 100%;
transition: all 0.3s ease;
}
.step-card:hover {
border-color: var(--r-cyan);
box-shadow: 0 0 30px rgba(0, 210, 255, 0.1);
}
.step-number {
font-size: 3rem;
font-weight: 900;
color: rgba(255, 255, 255, 0.05);
line-height: 1;
margin-bottom: 1rem;
}
.diff-grid {
background: rgba(2, 26, 36, 0.5);
border-radius: 1.5rem;
overflow: hidden;
border: 1px solid rgba(230, 231, 232, 0.1);
}
.diff-header {
background: rgba(230, 231, 232, 0.05);
padding: 1.5rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
}
.diff-row {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1.2fr;
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
align-items: center;
}
.diff-row:last-child {
border-bottom: none;
}
.diff-label {
color: #e6e7e8;
font-weight: 500;
}
.diff-value {
text-align: center;
font-size: 1.2rem;
}
.diff-roster {
color: var(--r-green);
font-weight: bold;
text-shadow: 0 0 10px rgba(20, 255, 0, 0.3);
}
.cta-final {
background: linear-gradient(180deg, #021a24 0%, #00d2ff 400%);
padding: 8rem 0;
}
@media (max-width: 768px) {
.diff-row {
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.diff-label {
grid-column: span 2;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
padding-bottom: 0.5rem;
}
}
.text-neon-green { color: var(--r-neon-green) !important; }
.text-cyan { color: var(--r-cyan) !important; }
.text-silver { color: var(--r-silver) !important; }
.bg-glass { background: var(--r-glass-bg) !important; backdrop-filter: blur(10px); }
.border-glass { border: 1px solid var(--r-glass-border) !important; }
/* Existing Sage/Sand Overrides */
.text-sage { color: var(--r-neon-green) !important; }
.bg-sage { background-color: var(--r-neon-green) !important; color: #020b1a !important; }
.text-slate, .text-dark { color: var(--r-silver) !important; }
/* Scrollbar */ /* Scrollbar */
::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--r-navy-deep); } ::-webkit-scrollbar-track { background: var(--r-navy-deep); }