diff --git a/make_post_sell/request_methods.py b/make_post_sell/request_methods.py
index c80c96e..f75293b 100644
--- a/make_post_sell/request_methods.py
+++ b/make_post_sell/request_methods.py
@@ -181,8 +181,8 @@ def includeme(config):
"""
root_domain = request.app.get("make_post_sell.root_domain")
- # For development, always treat localhost as SaaS domain for convenience
- if request.domain == "localhost":
+ # For development, always treat localhost/127.0.0.1 as SaaS domain for convenience
+ if request.domain in ("localhost", "127.0.0.1"):
return True
# Standard SaaS domain check
diff --git a/make_post_sell/static/css/common.css b/make_post_sell/static/css/common.css
index 3b1bfc2..26be9b5 100644
--- a/make_post_sell/static/css/common.css
+++ b/make_post_sell/static/css/common.css
@@ -299,6 +299,164 @@ section.join-form {
text-align: center;
}
+/* ============================================
+ LOGIN CARD
+ ============================================ */
+
+.login-card {
+ max-width: 440px;
+ margin: var(--space-12) auto;
+ padding: var(--space-10) var(--space-8);
+ text-align: center;
+ background-color: var(--surface-base);
+}
+
+.login-card-title {
+ margin-bottom: var(--space-2);
+}
+
+.login-card-subtitle {
+ margin-bottom: var(--space-8);
+ color: var(--text-secondary);
+}
+
+.login-form {
+ display: grid;
+ gap: var(--space-4);
+ text-align: left;
+}
+
+.login-form-label {
+ margin-bottom: calc(-1 * var(--space-2));
+}
+
+.login-form-input {
+ width: 100%;
+ padding: var(--space-3) var(--space-4);
+ font-size: var(--text-md);
+ border: 2px solid var(--border-default);
+ border-radius: var(--radius-md);
+ background-color: var(--input-bg);
+ color: var(--input-text);
+ transition: border-color var(--duration-fast) var(--ease-standard);
+}
+
+.login-form-input:focus {
+ border-color: var(--border-focus);
+ outline: none;
+}
+
+.login-form-submit {
+ width: 100%;
+ font-size: var(--text-base);
+ padding: var(--space-3) var(--space-6);
+ cursor: pointer;
+}
+
+.login-card-hint {
+ margin-top: var(--space-6);
+ padding: var(--space-4);
+ background-color: var(--surface-dim);
+ border-radius: var(--radius-md);
+ text-align: left;
+}
+
+/* ============================================
+ LANDING PAGE (SaaS homepage, not logged in)
+ ============================================ */
+
+.landing-hero {
+ max-width: var(--content-width);
+ margin: var(--space-16) auto var(--space-12);
+ text-align: center;
+ padding: 0 var(--space-6);
+}
+
+.landing-hero-sub {
+ max-width: 540px;
+ margin: var(--space-4) auto var(--space-8);
+ color: var(--text-secondary);
+}
+
+.landing-hero-ctas {
+ display: grid;
+ grid-template-columns: auto auto;
+ gap: var(--space-4);
+ justify-content: center;
+}
+
+.landing-features {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: var(--space-6);
+ max-width: var(--content-wide);
+ margin: 0 auto var(--space-12);
+ padding: 0 var(--space-6);
+}
+
+.landing-feature-card {
+ text-align: center;
+ padding: var(--space-8) var(--space-6);
+}
+
+.landing-feature-icon {
+ font-size: var(--text-4xl);
+ margin-bottom: var(--space-4);
+}
+
+.landing-feature-card h3 {
+ margin-bottom: var(--space-2);
+}
+
+.landing-cta-bottom {
+ max-width: var(--content-width);
+ margin: 0 auto var(--space-16);
+ padding: 0 var(--space-6);
+}
+
+.landing-cta-card {
+ text-align: center;
+ padding: var(--space-12) var(--space-8);
+}
+
+.landing-cta-card h2 {
+ margin-bottom: var(--space-3);
+}
+
+.landing-cta-card p {
+ margin-bottom: var(--space-6);
+ color: var(--text-secondary);
+}
+
+@media (max-width: 800px) {
+ .landing-hero {
+ margin: var(--space-10) auto var(--space-8);
+ }
+
+ .landing-hero-ctas {
+ grid-template-columns: 1fr;
+ }
+
+ .landing-hero-ctas .mps-button {
+ width: 100%;
+ }
+
+ .landing-features {
+ grid-template-columns: 1fr;
+ }
+
+ .login-card {
+ margin: var(--space-6) auto;
+ padding: var(--space-6) var(--space-5);
+ }
+}
+
+@media (min-width: 801px) and (max-width: 1000px) {
+ .landing-features {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
input.mps-product-title,
input.mps-product-price,
input.mps-content-title {
diff --git a/make_post_sell/templates/home.j2 b/make_post_sell/templates/home.j2
index bd77159..ce116c0 100644
--- a/make_post_sell/templates/home.j2
+++ b/make_post_sell/templates/home.j2
@@ -4,10 +4,9 @@
{% if not request.shop %}
- Create your own shop and start selling digital products in minutes. Commission-free digital downloads & physical product sales. Open source. Public domain. SPA media channel. Visitors browse your catalog without page reloads. Stripe, PayPal, Monero, Dogecoin, and free coupons. Your money, your choice. Email updates, RSS, and Atom feeds. Keep your audience in the loop. Sandbox filters, karaoke vocal isolation, and more. Built for creators. Views, sales, and traffic. Know what works without third-party trackers. Run multiple shops from one account. Custom domains included. What's next? check your email to log in!
-
+
+ New Shop
{% endif %}
+ Make. Post. Sell.
- Make it. Post it. Sell it.
+ Watch Mode
+ Five Payment Options
+ Subscriptions & Feeds
+ Creative Tools
+ Analytics Dashboard
+ Multi-tenant
+ Log in
- New and Existing Users
-
-
-
-
-
The SaaS homepage for unauthenticated visitors. Uses design tokens throughout. Grid-based feature cards. Responsive: 3 columns → 2 → 1.
+ +The unified login/signup form. Centered card with elevation, styled input, and hint block.
+Patterns that are thoughtfully designed and worth preserving. If something is a class act, it earned its place here through deliberate UX decisions, not accident.
+ +The sign-up and login flow is the same flow. There is no separate registration page. Every entry point — "Create a Shop," "Log In," "My Account" — routes to /join-or-log-in, which asks for one thing: your email.
New and existing users — one step to get in.
+