From fc8bd63b3411ea1a8713bc42cecd8de361991905 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 28 Feb 2026 12:23:20 +0000 Subject: [PATCH] V2 --- core/__pycache__/forms.cpython-311.pyc | Bin 0 -> 2057 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 6828 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 2168 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 12329 bytes core/forms.py | 22 ++ .../__pycache__/seed_data.cpython-311.pyc | Bin 0 -> 3638 bytes core/management/commands/seed_data.py | 58 +++++ core/migrations/0001_initial.py | 85 +++++++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 5403 bytes core/models.py | 91 ++++++- core/templates/base.html | 129 +++++++++- core/templates/core/chat_detail.html | 141 +++++++++++ core/templates/core/create_startup.html | 33 +++ core/templates/core/discover.html | 57 +++++ core/templates/core/index.html | 228 +++++++----------- core/templates/core/invest.html | 31 +++ core/templates/core/login.html | 38 +++ core/templates/core/messages.html | 41 ++++ core/templates/core/onboarding/investor.html | 32 +++ .../core/onboarding/partner_matching.html | 99 ++++++++ core/templates/core/onboarding/role.html | 59 +++++ core/templates/core/partners.html | 62 +++++ core/templates/core/portfolio.html | 102 ++++++++ core/templates/core/signup.html | 38 +++ core/templates/core/startup_detail.html | 84 +++++++ core/templates/core/verify.html | 28 +++ core/urls.py | 24 +- core/views.py | 214 ++++++++++++++-- static/css/custom.css | 101 +++++++- 29 files changed, 1621 insertions(+), 176 deletions(-) create mode 100644 core/__pycache__/forms.cpython-311.pyc create mode 100644 core/forms.py create mode 100644 core/management/commands/__pycache__/seed_data.cpython-311.pyc create mode 100644 core/management/commands/seed_data.py create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/templates/core/chat_detail.html create mode 100644 core/templates/core/create_startup.html create mode 100644 core/templates/core/discover.html create mode 100644 core/templates/core/invest.html create mode 100644 core/templates/core/login.html create mode 100644 core/templates/core/messages.html create mode 100644 core/templates/core/onboarding/investor.html create mode 100644 core/templates/core/onboarding/partner_matching.html create mode 100644 core/templates/core/onboarding/role.html create mode 100644 core/templates/core/partners.html create mode 100644 core/templates/core/portfolio.html create mode 100644 core/templates/core/signup.html create mode 100644 core/templates/core/startup_detail.html create mode 100644 core/templates/core/verify.html diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c967f7fccd00744695916ac4c6590e95f9be9316 GIT binary patch literal 2057 zcmb7EO>7%Q6yEjz*p8i&rfFg@7FJ714aBC0-b$g7DB@5Tk)lX@z-&AdXVYD;ncY=l z6D$rKa`Yima>%Jjfv6n9EoV*~*OCv`2q7d+xj9NsIq}}EP3ky7Vm$kKcINH(-n_q` z#>dA582A2oVWee2_#0maL+LM07%a90A`sCOEKw6hfkcR8Ml4B_ELoE+MN>o}B77(CK5r51o}nLAK8n5W$=VUlZXU5WuEBM zKL(vcgt5Nl$)B(|C!~@lSHLwdL`{hZR9%hso&XO3rxw2h#nQb;^2oHvpamc4e2nDoSNT`?7a``!N@YHxhw`4u$-2i@79^ zl}dQeQi+e1N|sGL6W7U7=^IZs!xM(3!4){9CRdjYY7&QGlJod8y6%2ft$8kw;S!A0 zd7|i9OO%D%>O!E2N7oDj{&Mz(6ZlX#n=7o?7A<&7;61NE*J;^vZB|&b*>k4`-YJxA zMhihDG`Uje@V_t%}6*;KmMpZdYvRR5Z~-TGwf=|Rz7(EWFpa88xm zQ{~Q7xtp5ZQFdQDyyh=H_wy#sl+{jIos`v0=XUPzK0M6(Uo7}!!~ftroatse-Rz{B z-AsPx%T6YL*z~_@`1ilXnb~M(HaeM&?)0q|-7G@tly)o7k z05+reV{e1i>>YsOzRX_77YrCn54PEDTm@2haD{0efD8-g0l@j4dy%*TROiTz<9|1femfdz9D{~%@)%f$8wU|9&^CxT(h?*h69tN09c~?lsKrPW3N&^$ z@rt^jKzS6aj6$JZ2R%oaj*Xj(%y5G;VOcBemic_1&A=I(0x0I<7yXW%o4tvUK|mVz z7Q!ur3jx8{vG)K_rSmbsc|gJ>oJ_aUkbudXt!B&HY93U7*Zr^8{P)*!&eYp8_0CMa zCq*vF2{sFS7d7T^4`BkHkrYrc1xDc*_f9W42vY#*z!O|0t9rF!hn1`b)$IhO&H|@k z9C`c+7Cpu|%*Mc;VXvIU9)xY+xpPnD4RFoZsP!{%2FF6c+@DGxo?|=XR literal 0 HcmV?d00001 diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 18a063c85a879cc83d00a9a0383835944a371483..9529ab8d2ab453183b5febabb79d5a435203f288 100644 GIT binary patch literal 6828 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 Ku%RM0pb7wG3pAVn diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index ebb8c6ea5957e01e2e132c7f2744cb84e6f77cdc..9f3827ad2bc430862b46e2cdea0c88048b214d1f 100644 GIT binary patch literal 2168 zcmZ{k&rjQC7{?v*gv5mKE8#aS?O4{PWms%N+JJ$e+qA;8RRW5{P%RU`B&LZS*$yo} z_1MD>+{O`2Q@3dxIQCE2@pbh|Mb=K+sW+tFDoxt+#<2<1dt=9szwhV$KCfRtuYb*C zIs|Nw{`y(Fn-GM5_)XCIo59<^+XUe!K^4?kMX1KMVlf`KRobfYExa_WD)5+_|(yt*U3dT{RPW;#Lbjb!?e=?s}{B$GoX6Egjg%m6Z7Au|}s3?b7U zGQ*L~2r@k(GaAW^A=4W&*CLtg$n=HGcqDTJnQX}1jATAQCKoajk<5q41T`qA`AFs? zWClW?TanCdWClZ~aFr?bZVjn-)`Y^{HykR&Jg6yl8Lx?bjXbg5@Y?bO56VWB@LpZ1 z5+`YCCB0sgymmiu+ABs$(f)qo>j#zmU(`!r>2;;PE0wF98uM*qJeXjyi^c6ViU7a z3__=)W|;P_QPB*^6T{f)wQTgn6`j{~d$#s?LGrqqlB^P2(JIc+dx-x$xJZ8BWCEgQ zShnPK@{8Qm9I;9)3)h&>CJ3FbVp*|Ua;EuxGvRlIVK1%jDSFA6s+$$d1?H5Qx_rz~`l|00{@{)?>YaOWJD{qKt|7|xq zOung2zH3dsExpl}*K>9Kz20EagU7YJ%&w-ZSXGTTWqF;|136r7lW!W6?+SB>duM_L z@iUKbEsf8NJHaNVZv8I2MM-!!De+w()pzQ;U6;sHQmpeLdt#W6t(sCKQlt9$VolW! z-lgWNhFY(X1#=Py^L=Ffi~r~GSS)rXjM2--neZvSe4GhcdigkS7ZT#LFQ4~4-}rIs zXqQ6Xg*=1&8Kh7hKKzR1^1ppUVaA0S1~a}qbU4ehw_azZS6PWJd{48In|;8t59sD2 z3bG3_1355QVY$NV-1Mv5^vkblZraV=W4U{O-lnkT!Wx6MfQw2*#nGb;cI^}T`3i+q z7giapHh3zIANRAHvvlbpg-sVW8EiH?t{*4ZjnC-f8ijQi))}m~j##Gmf1t4K!Zw3# zKlSJ#VFMqZVunQ*78xwI$c57m3Ue;ZF_`n^vBNqWES#n(%)2npV7}=-c0|~9oalWD zD=w@sSZQ`l9B=%x{W3*i$%Q2bOTNwcQJ#%Vo-R;Wc43*pvM)F0@?KIZ4j;|1(aF;< TLYMQ2zV5bXY5p_sU>W=e0;XD9 delta 264 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 WRxM!}&uxJbP(ZA@B7<-Vj{gs^itA?p literal 1364 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 PFTQj~UjM|ntL*;(dD+GY literal 0 HcmV?d00001 diff --git a/core/management/commands/seed_data.py b/core/management/commands/seed_data.py new file mode 100644 index 0000000..c68b3c7 --- /dev/null +++ b/core/management/commands/seed_data.py @@ -0,0 +1,58 @@ +from django.core.management.base import BaseCommand +from django.contrib.auth.models import User +from core.models import Profile, Tag, Startup, Investment + +class Command(BaseCommand): + help = 'Seed the database with initial mock data' + + def handle(self, *args, **kwargs): + self.stdout.write('Seeding initial data...') + + # Create Tags + tags = ['Fintech', 'Healthtech', 'Edtech', 'Sustainability', 'Consumer', 'Social Impact', 'AI', 'SaaS'] + tag_objs = [] + for tag in tags: + obj, created = Tag.objects.get_or_create(name=tag) + tag_objs.append(obj) + + # Create Founders + founders = [ + {'username': 'alex_founder', 'uni': 'Oxford', 'grad': 2025, 'bio': 'Building the future of finance for Gen Z.'}, + {'username': 'sarah_tech', 'uni': 'Imperial', 'grad': 2024, 'bio': 'Tech enthusiast and full-stack developer.'}, + {'username': 'michael_green', 'uni': 'UCL', 'grad': 2023, 'bio': 'Sustainability expert looking to change the world.'} + ] + + founder_profiles = [] + for f in founders: + user, created = User.objects.get_or_create(username=f['username'], email=f'{f["username"]}@uni.ac.uk') + if created: + user.set_password('password123') + user.save() + + profile = user.profile + profile.role = 'FOUNDER' + profile.university = f['uni'] + profile.graduation_year = f['grad'] + profile.bio = f['bio'] + profile.is_verified = True + profile.save() + founder_profiles.append(profile) + + # Create Startups + startups = [ + {'name': 'Stashify', 'headline': 'Micro-investing for students', 'amount': 5000, 'founder': founder_profiles[0]}, + {'name': 'HealthPulse', 'headline': 'AI-driven wellness tracker', 'amount': 10000, 'founder': founder_profiles[1]}, + {'name': 'EcoCart', 'headline': 'Track your carbon footprint while shopping', 'amount': 7500, 'founder': founder_profiles[2]} + ] + + for s in startups: + Startup.objects.get_or_create( + founder=s['founder'], + name=s['name'], + headline=s['headline'], + description="This is a detailed description of the startup " + s['name'] + ". We are building an MVP and looking for early-stage investors from the university community.", + target_amount=s['amount'], + status='FUNDING' + ) + + self.stdout.write(self.style.SUCCESS('Successfully seeded data!')) diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..68093f4 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,85 @@ +# Generated by Django 5.2.7 on 2026-02-28 12:06 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ], + ), + migrations.CreateModel( + name='Profile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('role', models.CharField(choices=[('FOUNDER', 'Founder'), ('INVESTOR', 'Investor'), ('PENDING', 'Pending')], default='PENDING', max_length=10)), + ('university', models.CharField(blank=True, max_length=255)), + ('graduation_year', models.IntegerField(blank=True, null=True)), + ('bio', models.CharField(blank=True, max_length=150)), + ('investment_appetite', models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True)), + ('investment_frequency', models.CharField(blank=True, max_length=100)), + ('matching_answers', models.JSONField(blank=True, null=True)), + ('is_verified', models.BooleanField(default=False)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)), + ('interests', models.ManyToManyField(blank=True, to='core.tag')), + ], + ), + migrations.CreateModel( + name='Notification', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField()), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('is_read', models.BooleanField(default=False)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to='core.profile')), + ], + ), + migrations.CreateModel( + name='Message', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField()), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('is_read', models.BooleanField(default=False)), + ('receiver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='received_messages', to='core.profile')), + ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_messages', to='core.profile')), + ], + ), + migrations.CreateModel( + name='Startup', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('headline', models.CharField(max_length=255)), + ('description', models.TextField()), + ('target_amount', models.DecimalField(decimal_places=2, max_digits=12)), + ('raised_amount', models.DecimalField(decimal_places=2, default=0, max_digits=12)), + ('status', models.CharField(choices=[('DRAFT', 'Draft'), ('FUNDING', 'Funding'), ('FUNDED', 'Funded')], default='DRAFT', max_length=10)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('founder', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='startups', to='core.profile')), + ], + ), + migrations.CreateModel( + name='Investment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('amount', models.DecimalField(decimal_places=2, max_digits=12)), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('investor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='investments', to='core.profile')), + ('startup', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='investments', to='core.startup')), + ], + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..468ae307ea691ba5ff339376748c52a4660c0bf8 GIT binary patch literal 5403 zcmd5=Jy07-7M>YNqaVOXHU?xsU<@|Gw&Vq~HtV&$fFz6!;vd^o-Odh7BL+(&JTt<^ z=h|{`!G#;$61q0<`DzIqY(TI9p~F^H2h>Dcb;*&*Wui^)UiV1+7f- zam~6i;;hJX0yoGh&cASq3%QouB}1SY0VrG_s!44{P43s zDSp<&biJh(MNsHy-%`bH3$O5sQ*o_}ubeOze)eZUP~1$jvecq@6n@?NN&qeRm9$dA zy6<4y2QyY2W5&vZGp0DD>L*?~p;WK?4|*0>7dWU3C{C`QI=B+hs$p7HrS*aqzkd3V zR_!5Mb!BYTGp!T*Yz37wV6Wkj=Nb>$Ybs+e#I&mS*()w?<*T2?b3R zR;8RXv(mhdWD_Y?#j>tuWPMe7gjOxDfpk?)tIv>Cxq|e$tbrs=&LGQ4<#reBbL`R~ zKb6u*OPPz7nA6n9ITRLjdIVYGf{N0LVY$cj?1GwxfqFKL!VVbaPK-_`WAOK3Q==15(pHdRW@)Q?ES`)FB?qB^GzD%t`WdjjP0ygP!*b6rX4QEFb0}y* z&ZSMA9$A(T76MB)RC9Iv-&9kuTytqzdt`T4!!=3Cv73^#ie#8ZKTC%>wOl%FIp);t z_TOmzl*-nTL7FMa%ge}AO|(sKD%&)n!%lnD2?foA*V58*TBb|!Wxykfno>@%~VBk+(mzq+l^E`LTg=NAE$Bx}YKSg}>18WJpB1>Y%QUJp?%XAVMPxtDD>0&H(q zli+%XObCsR(lmB=)N%xkr#;$SGubbTp4>0IWc< zq)1?z_QB26fH*=|6+F$oX7{8i>t+t-wqxX3g!$5{hO7z&8S}cjOfR-p6=5b2#1R+TQR1~|g*(rKK+4!fUv(N+=xpqVom30<*?zQmN}is|wKm;x>WCmGce zz)1)Sw28DW9)l;PsiG(7Ouk~iNU~|U7iKOi>M@7K1qVhd@hZkTq#M9b8?y{Ak^HdrkaqVI=y3CHO3PlsXPaY z3R<5BeAueo)leZM6$32)N9ZeqPTvBo%6>J~2RlQ8 zX0YWQSd?|USUCh_Nug3LW>deYc6V|#Syb!KLaNJ}U8@?^&{P(LT@{rjSxaRtL7B5W zjK(yw?t#9^fxcMWsveQG)u}9%MY~hzsadoX1Fla2PwlEN0sK}|+CA8=eA#7GeEaza z_Z~oSzu%57W-}<7n**xkqUb4_2S|GKNmhSkEJLnFDSe}RZ%xrFSFU^^6`dMcUe)Pa z7!w{S7;PfQz1aQx?Zn9!g9VZEcKp>xJQrSjNXIvMPapC06&ym1_+q%=Ay6Pr#PjOT-K5{zSi zqTq7WoG7?NukRfPVuy;ti9O?Ij$<5mJ-5FFjvExl1bF;Okm%#gcfva+cbJ5hfGlhU zns9S;ZG|*P-zb{~ZoZdqzDJtxVgK+}pcS`Wdzm0@*EW>5HMlLAZ%dN4B=(O2U|ip^ zCX)J&*XE`J*T?epF;XAH{`gklJnp#hS|lAeHrw$12NSCHOd}x$}MzMdaP*+LAQcc4GVuy-C%U)QTj}VqKxbf0jf;3*r zH%3Tf1pA|G!Y(>t7oZQt^PxBiQ5I|kKsid4qZ=;Vcq`v{i!|QC{@V;+C&kzKX6BcN zq$f^#lB8z_BNJlyjK9Oc4KZ*-4BQZH3EUM56(U98r3gUmP*JGaLvR#g{cjL7;HJph z3~7pN)czVIy+fpTg7nT}^*JoG-)3oOoFV`T;Q>hzOh9;oxZ%>;m!#p+o0VTy$+bap zZH!!dfKw}=@SF#X9M^b{jsyuKLDG@KLZQk{vHK`?5Ia;9YLAC~FJmWhus0vXue^TG|*K0gQWNvbN0nQ#NrQ_&9%3d~uil>6y~85%yR?`>=~Ba}oPra*@)B zr_+DV!R>|}h7q`hE!c;(cXtFk*V%z=pG0YDml@Zf^tucZTXWxfS*gy+QqS6=?$BmTB`taIlhDr|lK0seDpZvX%Q literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 71a8362..65a65c7 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,92 @@ from django.db import models +from django.contrib.auth.models import User +from django.db.models.signals import post_save +from django.dispatch import receiver -# Create your models here. +class Tag(models.Model): + name = models.CharField(max_length=50, unique=True) + + def __str__(self): + return self.name + +class Profile(models.Model): + ROLE_CHOICES = [ + ('FOUNDER', 'Founder'), + ('INVESTOR', 'Investor'), + ('PENDING', 'Pending'), + ] + + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') + role = models.CharField(max_length=10, choices=ROLE_CHOICES, default='PENDING') + university = models.CharField(max_length=255, blank=True) + graduation_year = models.IntegerField(null=True, blank=True) + bio = models.CharField(max_length=150, blank=True) + interests = models.ManyToManyField(Tag, blank=True) + + # Investor specific + investment_appetite = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True) + investment_frequency = models.CharField(max_length=100, blank=True) + + # Founder specific (for partner matching) + matching_answers = models.JSONField(null=True, blank=True) # To store questionnaire responses + + is_verified = models.BooleanField(default=False) + + def __str__(self): + return self.user.username + +@receiver(post_save, sender=User) +def create_user_profile(sender, instance, created, **kwargs): + if created: + Profile.objects.create(user=instance) + +@receiver(post_save, sender=User) +def save_user_profile(sender, instance, **kwargs): + instance.profile.save() + +class Startup(models.Model): + STATUS_CHOICES = [ + ('DRAFT', 'Draft'), + ('FUNDING', 'Funding'), + ('FUNDED', 'Funded'), + ] + + founder = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='startups') + name = models.CharField(max_length=255) + headline = models.CharField(max_length=255) + description = models.TextField() + target_amount = models.DecimalField(max_digits=12, decimal_places=2) + raised_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0) + status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='DRAFT') + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.name + +class Investment(models.Model): + investor = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='investments') + startup = models.ForeignKey(Startup, on_delete=models.CASCADE, related_name='investments') + amount = models.DecimalField(max_digits=12, decimal_places=2) + timestamp = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.investor.user.username} invested in {self.startup.name}" + +class Message(models.Model): + sender = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='sent_messages') + receiver = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='received_messages') + content = models.TextField() + timestamp = models.DateTimeField(auto_now_add=True) + is_read = models.BooleanField(default=False) + + def __str__(self): + return f"From {self.sender.user.username} to {self.receiver.user.username}" + +class Notification(models.Model): + user = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='notifications') + content = models.TextField() + timestamp = models.DateTimeField(auto_now_add=True) + is_read = models.BooleanField(default=False) + + def __str__(self): + return f"Notification for {self.user.user.username}" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..5ced4ff 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,9 +1,9 @@ - - {% block title %}Knowledge Base{% endblock %} + + {% block title %}Gatsby{% endblock %} {% if project_description %} @@ -14,12 +14,129 @@ {% endif %} {% load static %} + + + - {% block head %}{% endblock %} + + + + {% block extra_css %}{% endblock %} + - - {% block content %}{% endblock %} - + + +
+ {% block content %}{% endblock %} +
+ + + + + diff --git a/core/templates/core/chat_detail.html b/core/templates/core/chat_detail.html new file mode 100644 index 0000000..9dd385a --- /dev/null +++ b/core/templates/core/chat_detail.html @@ -0,0 +1,141 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}Chat with {{ chat_partner.user.username }} - Gatsby{% endblock %} + +{% block extra_css %} + +{% endblock %} + +{% block content %} +
+
+
+ +
+ + + +
+ {{ chat_partner.user.username|first|upper }} +
+
+
{{ chat_partner.user.username }}
+

{{ chat_partner.university }} · {{ chat_partner.role|title }}

+
+
+ + +
+ {% for message in messages %} +
+ {{ message.content }} + + {% if message.sender == user.profile %}You{% else %}{{ message.sender.user.username }}{% endif %} · {{ message.timestamp|date:"H:i" }} + +
+ {% empty %} +
+

This is the beginning of your conversation with {{ chat_partner.user.username }}.

+
+ {% endfor %} +
+ + + +
+
+
+ + +{% endblock %} diff --git a/core/templates/core/create_startup.html b/core/templates/core/create_startup.html new file mode 100644 index 0000000..33cf6e3 --- /dev/null +++ b/core/templates/core/create_startup.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}Post Startup - Gatsby{% endblock %} + +{% block content %} +
+
+
+

Post New Startup

+

Ready to build the future? Share your vision with the university ecosystem.

+ +
+ {% csrf_token %} + {% for field in form %} +
+ + {{ field }} + {% if field.errors %} +
{{ field.errors }}
+ {% endif %} +
+ {% endfor %} + +
+ + Cancel +
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/discover.html b/core/templates/core/discover.html new file mode 100644 index 0000000..ebedc76 --- /dev/null +++ b/core/templates/core/discover.html @@ -0,0 +1,57 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+

Discover Peer-Led Startups

+

Browse through the latest student and graduate startups looking for investment and partners.

+
+ +
+ +
+ {% for startup in startups %} +
+
+
+
+ Fintech + 12 days left +
+

{{ startup.name }}

+

{{ startup.headline }}

+ +
+
+ £{{ startup.raised_amount|floatformat:0 }} raised + {{ startup.raised_amount|divisibleby:startup.target_amount|default:0 }}% of £{{ startup.target_amount|floatformat:0 }} +
+
+
+
+
+ + +
+
+
+ {% empty %} +
+
+
+ +
+

No startups found yet

+

Be the first to post your vision and start raising capital from your peers.

+ Post Your Startup +
+
+ {% endfor %} +
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..cccd7b5 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,93 @@ {% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% load static %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+
+
+ + Exclusive for Students & Grads +
+

Build and Fund the Future Together.

+

The only university networking and micro-investment platform where verified students and recent graduates support each other's startups.

+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
-{% endblock %} \ No newline at end of file + + +
+
+
+
+
+ +
+

Verify

+

Exclusively for students and graduates within the last 5 years. Use your university email to join the network.

+
+
+
+
+
+ +
+

Connect

+

Find the perfect co-founder or team member using our AI-driven matching questionnaire based on skills and vision.

+
+
+
+
+
+ +
+

Fund

+

Start raising capital from your peers or discover student-led startups to invest in, starting from as little as £50.

+
+
+
+
+ +
+
+

How it Works

+

Three simple steps to launch your vision or grow your portfolio.

+
+
+
+
+
+
+ 1 +
+
+
Create Your Verified Profile
+

Sign up with your .edu or university email. We verify your status as a current student or recent graduate instantly.

+
+
+
+
+ 2 +
+
+
Define Your Role
+

Choose to be a Founder looking for investment and partners, or an Investor looking to support peer-led innovation.

+
+
+
+
+ 3 +
+
+
Start Networking & Investing
+

Browse listings, connect with founders, or set up your startup profile and start your first funding round.

+
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/invest.html b/core/templates/core/invest.html new file mode 100644 index 0000000..0a50b56 --- /dev/null +++ b/core/templates/core/invest.html @@ -0,0 +1,31 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

Invest in {{ startup.name }}

+

Be part of the next big university startup. Minimum investment is £50.

+ +
+ {% csrf_token %} +
+ + +
Enter the amount you wish to invest in this project.
+
+ +
+ +
+
+ +
+

By clicking "Confirm Investment", you agree to our Terms of Use and acknowledge the risks involved.

+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/login.html b/core/templates/core/login.html new file mode 100644 index 0000000..e15ffe3 --- /dev/null +++ b/core/templates/core/login.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

Welcome Back to GATSBY

+

Sign in to your account and explore the peer-to-peer startup ecosystem.

+ +
+ {% csrf_token %} + {% if form.non_field_errors %} +
{{ form.non_field_errors.0 }}
+ {% endif %} + +
+ + +
+
+ + +
+ +
+ +
+
+ +
+

Don't have an account? Sign Up

+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/messages.html b/core/templates/core/messages.html new file mode 100644 index 0000000..8560d26 --- /dev/null +++ b/core/templates/core/messages.html @@ -0,0 +1,41 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}Messages - Gatsby{% endblock %} + +{% block content %} +
+
+

Your Chats

+ +
+
+ {% for partner in chat_partners %} + +
+
+ {{ partner.user.username|first|upper }} +
+
+
{{ partner.user.username }}
+

{{ partner.university }} · {{ partner.role|title }}

+
+
+ +
+
+
+ {% empty %} +
+
+ +
+
No messages yet
+

Start a conversation with a founder or partner from the Discover page.

+
+ {% endfor %} +
+
+
+
+{% endblock %} diff --git a/core/templates/core/onboarding/investor.html b/core/templates/core/onboarding/investor.html new file mode 100644 index 0000000..0e4b846 --- /dev/null +++ b/core/templates/core/onboarding/investor.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

Complete Your Investor Profile

+

Sharing your background and goals helps us match you with the right startups.

+ +
+ {% csrf_token %} +
+ + +
+ +
+ + +
What's the total amount you're comfortable investing across the platform?
+
+ +
+ +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/onboarding/partner_matching.html b/core/templates/core/onboarding/partner_matching.html new file mode 100644 index 0000000..8e06f44 --- /dev/null +++ b/core/templates/core/onboarding/partner_matching.html @@ -0,0 +1,99 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

Partner Matching Questionnaire

+

Tell us more about your vision to find the perfect co-founder or team members.

+ +
+ {% csrf_token %} +
+
1. Which area best describes your startup or project?
+ +
+ +
+
2. What role are you currently fulfilling?
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
3. What kind of partner are you looking for?
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
4. What's your primary goal for the next 3 months?
+ +
+ +
+ +
+
+
+
+
+
+ + +{% endblock %} diff --git a/core/templates/core/onboarding/role.html b/core/templates/core/onboarding/role.html new file mode 100644 index 0000000..784b7a7 --- /dev/null +++ b/core/templates/core/onboarding/role.html @@ -0,0 +1,59 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

Choose Your Role

+

How do you plan to use Gatsby? You can change this later.

+ +
+ {% csrf_token %} +
+
+ +
+
+ +
+
+ +
+ +
+
+
+
+
+
+ + +{% endblock %} diff --git a/core/templates/core/partners.html b/core/templates/core/partners.html new file mode 100644 index 0000000..28ed40b --- /dev/null +++ b/core/templates/core/partners.html @@ -0,0 +1,62 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+

Find Your Next Co-Founder

+

Discover and connect with talented student and graduate founders looking for partners.

+
+ +
+ +
+ {% for partner in partners %} +
+
+
+
+
+ +
+
+
{{ partner.user.username }}
+ {{ partner.university }} · '{{ partner.graduation_year }} +
+
+ +

{{ partner.bio|default:"No bio available yet. I'm excited to build something new!" }}

+ +
+
Primary Focus
+
+ Fintech + Tech +
+
+ + +
+
+
+ {% empty %} +
+
+
+ +
+

No partners found yet

+

Be the first to create your founder profile and find your perfect co-founder.

+ Create Profile +
+
+ {% endfor %} +
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/portfolio.html b/core/templates/core/portfolio.html new file mode 100644 index 0000000..d93f2e3 --- /dev/null +++ b/core/templates/core/portfolio.html @@ -0,0 +1,102 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+

Your Portfolio

+

Manage your investments and track your startup's progress.

+
+
+
+ Total Invested: + £{{ total_invested|floatformat:0 }} +
+
+
+ +
+ +
+
+

My Investments

+ + New Investment + +
+ + {% for investment in investments %} +
+
+
+
{{ investment.startup.name }}
+ {{ investment.timestamp|date:"d M Y" }} +
+
+ £{{ investment.amount|floatformat:0 }} +
Invested
+
+
+ £{{ investment.startup.raised_amount|floatformat:0 }} +
Total Raised
+
+ +
+
+ {% empty %} +
+
+ +
+

No investments found yet. Browse startups and start supporting your peers.

+ Explore Startups +
+ {% endfor %} +
+ + +
+
+

My Startups

+ {% if user.profile.role == 'FOUNDER' %} + + Post New Startup + + {% endif %} +
+ + {% for startup in my_startups %} +
+
+
+
{{ startup.name }}
+ {{ startup.status }} +
+
+ £{{ startup.raised_amount|floatformat:0 }} +
Raised
+
+
+ £{{ startup.target_amount|floatformat:0 }} +
Target
+
+
+ Manage +
+
+
+ {% empty %} +
+
+ +
+

You haven't posted any startups yet. Ready to build the future?

+ Post Your Startup +
+ {% endfor %} +
+
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/signup.html b/core/templates/core/signup.html new file mode 100644 index 0000000..2f198b8 --- /dev/null +++ b/core/templates/core/signup.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

Create Your Profile

+

Join Gatsby and connect with the next generation of student-led startups. Only university or graduate emails from the last 5 years are accepted.

+ +
+ {% csrf_token %} + {% for field in form %} +
+ + + {% if field.help_text %} +
{{ field.help_text }}
+ {% endif %} + {% if field.errors %} +
{{ field.errors.0 }}
+ {% endif %} +
+ {% endfor %} + +
+ +
+
+ +
+

Already have an account? Sign In

+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/startup_detail.html b/core/templates/core/startup_detail.html new file mode 100644 index 0000000..71a4995 --- /dev/null +++ b/core/templates/core/startup_detail.html @@ -0,0 +1,84 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+
+ Fintech + 12 days left +
+

{{ startup.name }}

+

{{ startup.headline }}

+ +
+

About the Project

+

{{ startup.description }}

+
+ +
+

The Vision

+

Gatsby is built by the community. This project aims to revolutionize its sector by leveraging the unique insights of university talent. Our goal is to scale beyond campus while maintaining our core community values.

+
+ +
+
Founder
+
+
+ {{ startup.founder.user.username|first|upper }} +
+
+

{{ startup.founder.user.username }}

+

{{ startup.founder.university }} · Class of {{ startup.founder.graduation_year }}

+
+
+
+
+
+ +
+
+

Investment

+ +
+
+ £{{ startup.raised_amount|floatformat:0 }} raised + Target: £{{ startup.target_amount|floatformat:0 }} +
+
+ {% widthratio startup.raised_amount startup.target_amount 100 as percentage %} +
+
+
+ +
+
+ Minimum + £50 +
+
+ Backers + {{ startup.investments.count }} +
+
+ Valuation + £25k - £100k +
+
+ + + +
+

Join the network of alumni and students supporting this vision.

+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/verify.html b/core/templates/core/verify.html new file mode 100644 index 0000000..cb460a5 --- /dev/null +++ b/core/templates/core/verify.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+
+ +
+

Verify Your Email

+

We've sent a verification link to your university or graduate email address. Please click the link to confirm your status and access Gatsby.

+ +
+ {% csrf_token %} +
+ +
+
+ +
+

Didn't receive the email? Resend Link

+
+
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..e1c9b0e 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,23 @@ from django.urls import path - -from .views import home +from django.contrib.auth import views as auth_views +from . import views urlpatterns = [ - path("", home, name="home"), -] + path('', views.home, name='home'), + path('signup/', views.signup_view, name='signup'), + path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'), + path('logout/', auth_views.LogoutView.as_view(next_page='home'), name='logout'), + path('verify/', views.verify_view, name='verify'), + path('onboarding/role/', views.onboarding_role, name='onboarding_role'), + path('onboarding/investor/', views.onboarding_investor, name='onboarding_investor'), + path('onboarding/founder/', views.onboarding_founder, name='onboarding_founder'), + path('onboarding/matching/', views.onboarding_partner_matching, name='partner_matching'), + path('discover/', views.discover_startups, name='discover'), + path('partners/', views.find_partners, name='partners'), + path('portfolio/', views.my_portfolio, name='portfolio'), + path('startup//', views.startup_detail, name='startup_detail'), + path('startup//invest/', views.invest, name='invest'), + path('startup/post/', views.post_startup, name='post_startup'), + path('messages/', views.messages_view, name='messages'), + path('chat//', views.chat_detail, name='chat_detail'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..f90ff4c 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,195 @@ -import os -import platform - -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone - +from django.shortcuts import render, redirect, get_object_or_404 +from django.contrib.auth import login, authenticate +from django.contrib.auth.models import User +from django.contrib.auth.decorators import login_required +from .models import Profile, Tag, Startup, Investment, Message, Notification +from .forms import StartupForm, MessageForm +from django.contrib.auth.forms import UserCreationForm +from django import forms +from django.db.models import Sum, Q def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + return render(request, "core/index.html") - context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), - } - return render(request, "core/index.html", context) +class SignupForm(UserCreationForm): + university_email = forms.EmailField(required=True, label="University or Graduate Email") + full_name = forms.CharField(required=True) + university_name = forms.CharField(required=True) + graduation_year = forms.IntegerField(required=True) + + class Meta(UserCreationForm.Meta): + fields = UserCreationForm.Meta.fields + ('university_email',) + +def signup_view(request): + if request.method == "POST": + form = SignupForm(request.POST) + if form.is_valid(): + user = form.save() + profile = user.profile + profile.university = form.cleaned_data.get('university_name') + profile.graduation_year = form.cleaned_data.get('graduation_year') + profile.save() + # login(request, user) # Don't login yet, show verification screen + request.session['pending_verification_user_id'] = user.id + return redirect('verify') + else: + form = SignupForm() + return render(request, "core/signup.html", {"form": form}) + +def verify_view(request): + user_id = request.session.get('pending_verification_user_id') + if not user_id: + return redirect('signup') + + if request.method == "POST": + user = get_object_or_404(User, id=user_id) + user.profile.is_verified = True + user.profile.save() + login(request, user) + return redirect('onboarding_role') + + return render(request, "core/verify.html") + +@login_required +def onboarding_role(request): + if request.method == "POST": + role = request.POST.get('role') + request.user.profile.role = role + request.user.profile.save() + if role == 'INVESTOR': + return redirect('onboarding_investor') + else: + return redirect('onboarding_founder') + return render(request, "core/onboarding/role.html") + +@login_required +def onboarding_investor(request): + if request.method == "POST": + bio = request.POST.get('bio') + appetite = request.POST.get('appetite') + request.user.profile.bio = bio + request.user.profile.investment_appetite = appetite + request.user.profile.save() + return redirect('discover') + return render(request, "core/onboarding/investor.html") + +@login_required +def onboarding_founder(request): + # This leads to partner matching questionnaire + return redirect('partner_matching') + +@login_required +def onboarding_partner_matching(request): + if request.method == "POST": + # Save questionnaire answers in JSON format + request.user.profile.matching_answers = request.POST.dict() + request.user.profile.save() + return redirect('partners') + return render(request, "core/onboarding/partner_matching.html") + +@login_required +def discover_startups(request): + startups = Startup.objects.filter(status='FUNDING').order_by('-created_at') + return render(request, "core/discover.html", {"startups": startups}) + +@login_required +def find_partners(request): + current_profile = request.user.profile + # Basic partner matching logic: + # 1. Same university + # 2. Shared interests (Tags) - if we had tags set up properly + # For now, let's just prioritize same university and then others. + + partners = Profile.objects.filter(role='FOUNDER').exclude(user=request.user) + + # Sort by same university + partners = sorted(partners, key=lambda p: p.university == current_profile.university, reverse=True) + + return render(request, "core/partners.html", {"partners": partners}) + +@login_required +def my_portfolio(request): + profile = request.user.profile + investments = Investment.objects.filter(investor=profile) + total_invested = investments.aggregate(Sum('amount'))['amount__sum'] or 0 + my_startups = Startup.objects.filter(founder=profile) + return render(request, "core/portfolio.html", { + "investments": investments, + "total_invested": total_invested, + "my_startups": my_startups + }) + +@login_required +def startup_detail(request, pk): + startup = get_object_or_404(Startup, pk=pk) + return render(request, "core/startup_detail.html", {"startup": startup}) + +@login_required +def invest(request, pk): + startup = get_object_or_404(Startup, pk=pk) + if request.method == "POST": + amount = request.POST.get('amount') + Investment.objects.create( + investor=request.user.profile, + startup=startup, + amount=amount + ) + startup.raised_amount += float(amount) + startup.save() + return redirect('portfolio') + return render(request, "core/invest.html", {"startup": startup}) + +@login_required +def post_startup(request): + if request.method == "POST": + form = StartupForm(request.POST) + if form.is_valid(): + startup = form.save(commit=False) + startup.founder = request.user.profile + startup.save() + return redirect('portfolio') + else: + form = StartupForm() + return render(request, "core/create_startup.html", {"form": form}) + +@login_required +def messages_view(request): + profile = request.user.profile + # Get all unique profiles the current user has chatted with + sent_to = Message.objects.filter(sender=profile).values_list('receiver', flat=True) + received_from = Message.objects.filter(receiver=profile).values_list('sender', flat=True) + + chat_partner_ids = set(list(sent_to) + list(received_from)) + chat_partners = Profile.objects.filter(id__in=chat_partner_ids) + + return render(request, "core/messages.html", {"chat_partners": chat_partners}) + +@login_required +def chat_detail(request, pk): + sender_profile = request.user.profile + receiver_profile = get_object_or_404(Profile, pk=pk) + + messages = Message.objects.filter( + (Q(sender=sender_profile) & Q(receiver=receiver_profile)) | + (Q(sender=receiver_profile) & Q(receiver=sender_profile)) + ).order_by('timestamp') + + # Mark messages as read + Message.objects.filter(sender=receiver_profile, receiver=sender_profile, is_read=False).update(is_read=True) + + if request.method == "POST": + form = MessageForm(request.POST) + if form.is_valid(): + message = form.save(commit=False) + message.sender = sender_profile + message.receiver = receiver_profile + message.save() + return redirect('chat_detail', pk=pk) + else: + form = MessageForm() + + return render(request, "core/chat_detail.html", { + "chat_partner": receiver_profile, + "messages": messages, + "form": form + }) diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..2f5cb6e 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,99 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --bg-dark: #0a0a0f; + --surface-dark: #14141a; + --surface-glass: rgba(20, 20, 26, 0.7); + --accent-blue: #21d4fd; + --accent-violet: #7b2ff7; + --accent-gradient: linear-gradient(45deg, #7b2ff7, #21d4fd); + --text-primary: #ffffff; + --text-secondary: #b0b0b5; + --border-glass: rgba(255, 255, 255, 0.1); } + +body { + background-color: var(--bg-dark); + color: var(--text-primary); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + margin: 0; + overflow-x: hidden; +} + +.glass-card { + background: var(--surface-glass); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid var(--border-glass); + border-radius: 24px; + padding: 24px; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.glass-card:hover { + transform: translateY(-4px); + box-shadow: 0 12px 24px rgba(0, 0, 0, 0.4); +} + +.btn-primary { + background: var(--accent-gradient); + border: none; + border-radius: 100px; + color: white; + font-weight: 700; + padding: 12px 32px; + transition: opacity 0.2s ease; +} + +.btn-primary:hover { + opacity: 0.9; + color: white; +} + +.text-gradient { + background: var(--accent-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.navbar { + background-color: rgba(10, 10, 15, 0.8); + backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border-glass); +} + +.hero-section { + padding: 120px 0 80px; + text-align: center; +} + +.hero-title { + font-size: 4rem; + font-weight: 800; + margin-bottom: 24px; +} + +.hero-subtitle { + color: var(--text-secondary); + font-size: 1.25rem; + max-width: 600px; + margin: 0 auto 40px; +} + +.feature-pill { + background: var(--surface-dark); + border: 1px solid var(--border-glass); + border-radius: 100px; + display: inline-flex; + align-items: center; + padding: 8px 16px; + font-size: 0.9rem; + margin-bottom: 24px; +} + +.feature-dot { + width: 8px; + height: 8px; + background: var(--accent-blue); + border-radius: 50%; + margin-right: 8px; + box-shadow: 0 0 10px var(--accent-blue); +} \ No newline at end of file