Align ExposedGays theme with Pink Pulse colors, typography, and pill buttons
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
"description": "Free gay cruising map, chat & shop",
|
"description": "Free gay cruising map, chat & shop",
|
||||||
"start_url": "/",
|
"start_url": "/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"background_color": "#0d0a0f",
|
"background_color": "#08001C",
|
||||||
"theme_color": "#ff2d6b",
|
"theme_color": "#F92B9B",
|
||||||
"orientation": "any",
|
"orientation": "any",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,25 +4,25 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 280 30% 6%;
|
--background: 265 100% 5%;
|
||||||
--foreground: 0 0% 98%;
|
--foreground: 228 100% 97%;
|
||||||
--card: 280 25% 10%;
|
--card: 268 100% 11%;
|
||||||
--card-foreground: 0 0% 98%;
|
--card-foreground: 228 100% 97%;
|
||||||
--popover: 280 25% 10%;
|
--popover: 268 100% 11%;
|
||||||
--popover-foreground: 0 0% 98%;
|
--popover-foreground: 228 100% 97%;
|
||||||
--primary: 340 100% 59%;
|
--primary: 330 94% 57%;
|
||||||
--primary-foreground: 0 0% 100%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--secondary: 280 40% 18%;
|
--secondary: 268 55% 16%;
|
||||||
--secondary-foreground: 0 0% 98%;
|
--secondary-foreground: 228 100% 97%;
|
||||||
--muted: 280 20% 16%;
|
--muted: 268 35% 14%;
|
||||||
--muted-foreground: 280 10% 65%;
|
--muted-foreground: 228 12% 60%;
|
||||||
--accent: 280 60% 45%;
|
--accent: 280 72% 47%;
|
||||||
--accent-foreground: 0 0% 100%;
|
--accent-foreground: 0 0% 100%;
|
||||||
--destructive: 0 84% 60%;
|
--destructive: 0 84% 60%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 280 20% 20%;
|
--border: 220 38% 20%;
|
||||||
--input: 280 20% 20%;
|
--input: 220 38% 20%;
|
||||||
--ring: 340 100% 59%;
|
--ring: 330 94% 57%;
|
||||||
--radius: 0.75rem;
|
--radius: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,17 +37,59 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Leaflet dark theme overrides */
|
@layer components {
|
||||||
|
.gradient-text {
|
||||||
|
@apply bg-pulse-gradient bg-clip-text text-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-card {
|
||||||
|
@apply rounded-xl border border-white/[0.06] bg-pulse-midnight/70 backdrop-blur-md;
|
||||||
|
transition: background 0.2s, border-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-card:hover {
|
||||||
|
@apply border-primary/25 bg-pulse-glow/40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-pill {
|
||||||
|
@apply inline-flex items-center justify-center rounded-full px-4 py-2 text-sm font-bold transition-all touch-manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-pill-active {
|
||||||
|
@apply text-white shadow-pulse-glow;
|
||||||
|
background: linear-gradient(135deg, #ff2d9b, #9b30ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-pill-inactive {
|
||||||
|
color: #8b92a8;
|
||||||
|
background: rgba(30, 45, 74, 0.4);
|
||||||
|
border: 1px solid rgba(155, 48, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-pill-inactive:hover {
|
||||||
|
color: #ff6ec7;
|
||||||
|
border-color: rgba(255, 45, 155, 0.35);
|
||||||
|
background: rgba(255, 45, 155, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-pill-tag {
|
||||||
|
@apply text-xs font-bold px-3 py-1 rounded-full;
|
||||||
|
color: #ff6ec7;
|
||||||
|
background: rgba(255, 45, 155, 0.15);
|
||||||
|
border: 1px solid rgba(255, 45, 155, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Leaflet — Pink Pulse dark palette */
|
||||||
.leaflet-container {
|
.leaflet-container {
|
||||||
background: #0a1628 !important;
|
background: #08001c !important;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sniffies-map .leaflet-tile-pane {
|
.sniffies-map .leaflet-tile-pane {
|
||||||
filter: saturate(0.85) brightness(0.95);
|
filter: saturate(0.9) brightness(0.92) hue-rotate(-8deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sniffies-style photo markers */
|
|
||||||
.sniffies-marker-wrap,
|
.sniffies-marker-wrap,
|
||||||
.sniffies-you-wrap,
|
.sniffies-you-wrap,
|
||||||
.sniffies-spot-wrap {
|
.sniffies-spot-wrap {
|
||||||
@@ -68,15 +110,15 @@
|
|||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 2px solid #3b82f6;
|
border: 2px solid #f92b9b;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
background: #0a1628;
|
background: #08001c;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.6);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sniffies-avatar-ring.sniffies-online {
|
.sniffies-avatar-ring.sniffies-online {
|
||||||
border-color: #3b82f6;
|
border-color: #f92b9b;
|
||||||
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.35);
|
box-shadow: 0 0 0 2px rgba(249, 43, 155, 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sniffies-avatar {
|
.sniffies-avatar {
|
||||||
@@ -93,7 +135,7 @@
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #f97316;
|
background: linear-gradient(135deg, #ff2d9b, #c084fc);
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -113,9 +155,9 @@
|
|||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #ef4444;
|
background: #f92b9b;
|
||||||
border: 3px solid white;
|
border: 3px solid white;
|
||||||
box-shadow: 0 2px 12px rgba(239, 68, 68, 0.6);
|
box-shadow: 0 2px 12px rgba(249, 43, 155, 0.6);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -133,7 +175,7 @@
|
|||||||
.sniffies-you-label {
|
.sniffies-you-label {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #3b82f6;
|
color: #ff6ec7;
|
||||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,8 +184,8 @@
|
|||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: rgba(10, 22, 40, 0.9);
|
background: rgba(26, 0, 58, 0.95);
|
||||||
border: 2px solid #3b82f6;
|
border: 2px solid #8b22cc;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -158,7 +200,7 @@
|
|||||||
min-width: 16px;
|
min-width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #3b82f6;
|
background: linear-gradient(135deg, #ff2d9b, #8b22cc);
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -166,91 +208,114 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-popup-content-wrapper {
|
.leaflet-popup-content-wrapper {
|
||||||
background: hsl(280 25% 10%);
|
background: hsl(268 100% 11%);
|
||||||
color: hsl(0 0% 98%);
|
color: hsl(228 100% 97%);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
border: 1px solid hsl(280 20% 20%);
|
border: 1px solid hsl(220 38% 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-popup-tip {
|
.leaflet-popup-tip {
|
||||||
background: hsl(280 25% 10%);
|
background: hsl(268 100% 11%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.marker-cluster-small,
|
.marker-cluster-small,
|
||||||
.marker-cluster-medium,
|
.marker-cluster-medium,
|
||||||
.marker-cluster-large {
|
.marker-cluster-large {
|
||||||
background-color: rgba(255, 45, 107, 0.3) !important;
|
background-color: rgba(249, 43, 155, 0.3) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marker-cluster-small div,
|
.marker-cluster-small div,
|
||||||
.marker-cluster-medium div,
|
.marker-cluster-medium div,
|
||||||
.marker-cluster-large div {
|
.marker-cluster-large div {
|
||||||
background-color: rgba(255, 45, 107, 0.8) !important;
|
background-color: rgba(249, 43, 155, 0.85) !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Vanilla mode blur */
|
|
||||||
.vanilla-blur img,
|
.vanilla-blur img,
|
||||||
.vanilla-blur video,
|
.vanilla-blur video,
|
||||||
.vanilla-blur .explicit-content {
|
.vanilla-blur .explicit-content {
|
||||||
filter: blur(24px);
|
filter: blur(24px);
|
||||||
transition: filter 0.3s ease;
|
transition: filter 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vanilla-blur:hover img,
|
.vanilla-blur:hover img,
|
||||||
.vanilla-blur:hover video,
|
.vanilla-blur:hover video,
|
||||||
.vanilla-blur:hover .explicit-content {
|
.vanilla-blur:hover .explicit-content {
|
||||||
filter: blur(8px);
|
filter: blur(8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar */
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: hsl(280 30% 6%);
|
background: hsl(265 100% 5%);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: hsl(340 100% 59% / 0.5);
|
background: rgba(249, 43, 155, 0.45);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PWA safe areas */
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(249, 43, 155, 0.65);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-none {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-none::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.safe-bottom {
|
.safe-bottom {
|
||||||
padding-bottom: max(env(safe-area-inset-bottom, 0px), 4px);
|
padding-bottom: max(env(safe-area-inset-bottom, 0px), 4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.safe-top {
|
.safe-top {
|
||||||
padding-top: env(safe-area-inset-top, 0);
|
padding-top: env(safe-area-inset-top, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ID verification blur — nude photos in restricted states */
|
|
||||||
.id-blur img,
|
.id-blur img,
|
||||||
.id-blur .explicit-content {
|
.id-blur .explicit-content {
|
||||||
filter: blur(28px) !important;
|
filter: blur(28px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.id-blur:hover img,
|
.id-blur:hover img,
|
||||||
.id-blur:hover .explicit-content {
|
.id-blur:hover .explicit-content {
|
||||||
filter: blur(20px) !important;
|
filter: blur(20px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile touch targets & scroll */
|
|
||||||
.touch-manipulation {
|
.touch-manipulation {
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (height: 100dvh) {
|
@supports (height: 100dvh) {
|
||||||
.min-h-screen {
|
.min-h-screen {
|
||||||
min-height: 100dvh;
|
min-height: 100dvh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent iOS zoom on input focus */
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
input, select, textarea {
|
input,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overscroll containment for chat */
|
|
||||||
.overscroll-contain {
|
.overscroll-contain {
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus-visible {
|
||||||
|
outline: 2px solid rgba(249, 43, 155, 0.6);
|
||||||
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import type { Metadata, Viewport } from "next";
|
import type { Metadata, Viewport } from "next";
|
||||||
import { Inter } from "next/font/google";
|
import { Manrope } from "next/font/google";
|
||||||
import { Providers } from "@/components/Providers";
|
import { Providers } from "@/components/Providers";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
const manrope = Manrope({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-manrope",
|
||||||
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "ExposedGays — Free Gay Cruising & Shop",
|
title: "ExposedGays — Free Gay Cruising & Shop",
|
||||||
@@ -22,7 +25,7 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const viewport: Viewport = {
|
export const viewport: Viewport = {
|
||||||
themeColor: "#ff2d6b",
|
themeColor: "#F92B9B",
|
||||||
width: "device-width",
|
width: "device-width",
|
||||||
initialScale: 1,
|
initialScale: 1,
|
||||||
viewportFit: "cover",
|
viewportFit: "cover",
|
||||||
@@ -35,7 +38,7 @@ export default function RootLayout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className="dark">
|
<html lang="en" className="dark">
|
||||||
<body className={inter.className}>
|
<body className={`${manrope.variable} font-sans`}>
|
||||||
<Providers>{children}</Providers>
|
<Providers>{children}</Providers>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
|||||||
<div className="mx-auto mb-4 flex justify-center">
|
<div className="mx-auto mb-4 flex justify-center">
|
||||||
<Logo size="lg" showText={false} />
|
<Logo size="lg" showText={false} />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold bg-horny-gradient bg-clip-text text-transparent">
|
<h1 className="text-2xl font-bold gradient-text">
|
||||||
ExposedGays
|
ExposedGays
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mt-2 text-sm text-muted-foreground">
|
<p className="mt-2 text-sm text-muted-foreground">
|
||||||
@@ -149,9 +149,9 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-lg border border-blue-500/25 bg-blue-500/10 p-3">
|
<div className="rounded-xl border border-primary/25 bg-primary/10 p-3">
|
||||||
<p className="text-xs text-blue-100/90 leading-relaxed">
|
<p className="text-xs text-foreground/90 leading-relaxed">
|
||||||
<strong className="text-blue-200">No account needed.</strong> Verify your age
|
<strong className="text-pulse-pink-light">No account needed.</strong> Verify your age
|
||||||
with date of birth only — browse the map, spots, and profiles free. Explicit
|
with date of birth only — browse the map, spots, and profiles free. Explicit
|
||||||
photos and chat require a free signup. Government ID is only needed for nude
|
photos and chat require a free signup. Government ID is only needed for nude
|
||||||
content in certain states.
|
content in certain states.
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export function CannedMessagesPanel({ compact, onSelect }: CannedMessagesPanelPr
|
|||||||
key={msg.id}
|
key={msg.id}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => onSelect?.(msg.content)}
|
onClick={() => onSelect?.(msg.content)}
|
||||||
className="text-xs px-2.5 py-1.5 rounded-full border border-border hover:border-horny-pink/50 hover:bg-horny-pink/10 transition-colors truncate max-w-[140px]"
|
className="text-xs px-2.5 py-1.5 rounded-full pulse-pill-inactive truncate max-w-[140px]"
|
||||||
title={msg.content}
|
title={msg.content}
|
||||||
>
|
>
|
||||||
{msg.title}
|
{msg.title}
|
||||||
|
|||||||
@@ -111,14 +111,14 @@ export function CruiserProfileView({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-[2000] bg-black flex flex-col md:items-center md:justify-center md:p-4">
|
<div className="fixed inset-0 z-[2000] bg-black flex flex-col md:items-center md:justify-center md:p-4">
|
||||||
<div className="w-full h-full md:max-w-lg md:max-h-[92vh] md:rounded-2xl md:overflow-hidden flex flex-col bg-[#0a1628]">
|
<div className="w-full h-full md:max-w-lg md:max-h-[92vh] md:rounded-2xl md:overflow-hidden flex flex-col bg-pulse-deep-space">
|
||||||
{/* Header — Sniffies style */}
|
{/* Header — Sniffies style */}
|
||||||
<div className="shrink-0 bg-black px-3 py-2 safe-top">
|
<div className="shrink-0 bg-black px-3 py-2 safe-top">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="p-2 text-blue-400 touch-manipulation"
|
className="p-2 text-pulse-pink-light touch-manipulation"
|
||||||
aria-label="Back"
|
aria-label="Back"
|
||||||
>
|
>
|
||||||
<ArrowLeft className="h-5 w-5" />
|
<ArrowLeft className="h-5 w-5" />
|
||||||
@@ -126,7 +126,7 @@ export function CruiserProfileView({
|
|||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
{profile.is_verified && (
|
{profile.is_verified && (
|
||||||
<ShieldCheck className="h-4 w-4 text-blue-400 shrink-0" />
|
<ShieldCheck className="h-4 w-4 text-pulse-pink-light shrink-0" />
|
||||||
)}
|
)}
|
||||||
<span className="font-bold text-white truncate">{name}</span>
|
<span className="font-bold text-white truncate">{name}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -188,7 +188,7 @@ export function CruiserProfileView({
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => setActivePhoto(i + 1)}
|
onClick={() => setActivePhoto(i + 1)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative w-14 h-14 rounded-full overflow-hidden border-2 border-blue-400",
|
"relative w-14 h-14 rounded-full overflow-hidden border-2 border-primary",
|
||||||
shouldBlurPhoto(ph.is_explicit) && "id-blur"
|
shouldBlurPhoto(ph.is_explicit) && "id-blur"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -200,7 +200,7 @@ export function CruiserProfileView({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats + headline */}
|
{/* Stats + headline */}
|
||||||
<div className="px-4 py-3 space-y-2 bg-[#0a1628]">
|
<div className="px-4 py-3 space-y-2 bg-pulse-deep-space">
|
||||||
{stats && (
|
{stats && (
|
||||||
<p className="flex items-center gap-2 text-sm text-white/90">
|
<p className="flex items-center gap-2 text-sm text-white/90">
|
||||||
<Ruler className="h-4 w-4 text-white/50" />
|
<Ruler className="h-4 w-4 text-white/50" />
|
||||||
@@ -233,7 +233,7 @@ export function CruiserProfileView({
|
|||||||
onClick={() => setTab(t)}
|
onClick={() => setTab(t)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex-1 py-2.5 text-xs font-semibold uppercase tracking-wide touch-manipulation",
|
"flex-1 py-2.5 text-xs font-semibold uppercase tracking-wide touch-manipulation",
|
||||||
tab === t ? "text-blue-400 border-b-2 border-blue-400" : "text-white/50"
|
tab === t ? "text-pulse-pink-light border-b-2 border-primary" : "text-white/50"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{t}
|
{t}
|
||||||
@@ -391,7 +391,7 @@ export function CruiserProfileView({
|
|||||||
<div className="flex items-center gap-3 text-xs text-white/70">
|
<div className="flex items-center gap-3 text-xs text-white/70">
|
||||||
<span>{timeAgo(profile.last_active)}</span>
|
<span>{timeAgo(profile.last_active)}</span>
|
||||||
{profile.distance_miles != null && (
|
{profile.distance_miles != null && (
|
||||||
<span className="flex items-center gap-1 text-blue-400">
|
<span className="flex items-center gap-1 text-pulse-pink-light">
|
||||||
<MapPin className="h-3 w-3" />
|
<MapPin className="h-3 w-3" />
|
||||||
{formatDistance(profile.distance_miles)}
|
{formatDistance(profile.distance_miles)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function GuestUpgradeBanner({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="rounded-xl border border-amber-500/25 bg-[#0a1628]/90 p-4 relative">
|
<div className="rounded-xl border border-primary/25 bg-pulse-midnight/90 p-4 relative">
|
||||||
{onDismiss && (
|
{onDismiss && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -68,11 +68,11 @@ export function GuestUpgradeBanner({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-blue-500/20">
|
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary/20">
|
||||||
<ShieldCheck className="h-5 w-5 text-blue-400" />
|
<ShieldCheck className="h-5 w-5 text-pulse-pink-light" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0 pr-6">
|
<div className="flex-1 min-w-0 pr-6">
|
||||||
<p className="text-sm font-semibold text-blue-100">{msg.title}</p>
|
<p className="text-sm font-semibold text-foreground">{msg.title}</p>
|
||||||
<p className="text-xs text-muted-foreground mt-1 leading-relaxed">{msg.body}</p>
|
<p className="text-xs text-muted-foreground mt-1 leading-relaxed">{msg.body}</p>
|
||||||
<Button
|
<Button
|
||||||
variant="horny"
|
variant="horny"
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export function LocalGuidePanel({
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"pointer-events-auto border border-white/10 bg-[#0a1628]/96 backdrop-blur-md shadow-2xl overflow-hidden",
|
"pointer-events-auto border border-primary/15 bg-pulse-midnight/96 backdrop-blur-md shadow-pulse-card overflow-hidden",
|
||||||
isDock ? "rounded-t-2xl md:rounded-2xl" : "rounded-xl"
|
isDock ? "rounded-t-2xl md:rounded-2xl" : "rounded-xl"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -126,7 +126,7 @@ export function LocalGuidePanel({
|
|||||||
className="w-full flex items-center gap-2 px-3 py-2.5 sm:py-3 touch-manipulation active:bg-white/5 transition-colors"
|
className="w-full flex items-center gap-2 px-3 py-2.5 sm:py-3 touch-manipulation active:bg-white/5 transition-colors"
|
||||||
aria-expanded={expanded}
|
aria-expanded={expanded}
|
||||||
>
|
>
|
||||||
<span className="shrink-0 text-[10px] font-semibold uppercase tracking-wider text-blue-300/90">
|
<span className="shrink-0 pulse-pill-tag text-[10px] py-0.5 px-2">
|
||||||
Local
|
Local
|
||||||
</span>
|
</span>
|
||||||
<div className="flex-1 min-w-0 overflow-x-auto scrollbar-none">
|
<div className="flex-1 min-w-0 overflow-x-auto scrollbar-none">
|
||||||
@@ -139,7 +139,7 @@ export function LocalGuidePanel({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
openSection(section.key);
|
openSection(section.key);
|
||||||
}}
|
}}
|
||||||
className="shrink-0 text-[11px] sm:text-xs px-2.5 py-1 rounded-full bg-white/5 border border-white/10 text-foreground/90 hover:bg-white/10 hover:border-blue-400/30 transition-colors"
|
className="shrink-0 text-[11px] sm:text-xs px-2.5 py-1 rounded-full pulse-pill-inactive"
|
||||||
>
|
>
|
||||||
{section.localLabel.replace("Local ", "")}
|
{section.localLabel.replace("Local ", "")}
|
||||||
</span>
|
</span>
|
||||||
@@ -169,7 +169,7 @@ export function LocalGuidePanel({
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleOutboundClick("banner", partnerHomeHref(placement))
|
handleOutboundClick("banner", partnerHomeHref(placement))
|
||||||
}
|
}
|
||||||
className="block relative w-full overflow-hidden rounded-lg border border-white/10 bg-[#1a003a]/30"
|
className="block relative w-full overflow-hidden rounded-xl border border-primary/20 bg-pulse-midnight/50"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={PULSE_ATTRIBUTION.bannerRect}
|
src={PULSE_ATTRIBUTION.bannerRect}
|
||||||
@@ -200,12 +200,12 @@ export function LocalGuidePanel({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"rounded-lg border px-2.5 py-2.5 transition-colors group touch-manipulation min-h-[52px]",
|
"rounded-lg border px-2.5 py-2.5 transition-colors group touch-manipulation min-h-[52px]",
|
||||||
active
|
active
|
||||||
? "border-[#f92b9b]/40 bg-[#f92b9b]/10"
|
? "border-primary/40 bg-primary/10 shadow-pulse-glow"
|
||||||
: "border-white/10 hover:border-[#f92b9b]/25 hover:bg-[#f92b9b]/5"
|
: "border-pulse-border/50 hover:border-primary/30 hover:bg-primary/5"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1.5 mb-0.5">
|
<div className="flex items-center gap-1.5 mb-0.5">
|
||||||
<Icon className="h-3 w-3 text-blue-300/80 group-hover:text-[#f92b9b]" />
|
<Icon className="h-3 w-3 text-pulse-lavender/80 group-hover:text-primary" />
|
||||||
<p className="text-xs font-medium leading-tight">
|
<p className="text-xs font-medium leading-tight">
|
||||||
{section.localLabel}
|
{section.localLabel}
|
||||||
</p>
|
</p>
|
||||||
@@ -238,7 +238,7 @@ export function LocalGuidePanel({
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleOutboundClick("visit_tpp", partnerHomeHref(placement))
|
handleOutboundClick("visit_tpp", partnerHomeHref(placement))
|
||||||
}
|
}
|
||||||
className="shrink-0 inline-flex items-center gap-1 text-[11px] font-medium text-[#f92b9b] hover:underline touch-manipulation py-1"
|
className="shrink-0 inline-flex items-center gap-1 text-[11px] font-medium text-primary hover:underline touch-manipulation py-1"
|
||||||
>
|
>
|
||||||
thepinkpulse.com
|
thepinkpulse.com
|
||||||
<ExternalLink className="h-3 w-3 opacity-70" />
|
<ExternalLink className="h-3 w-3 opacity-70" />
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function Logo({ size = "md", showText = true, className }: LogoProps) {
|
|||||||
{showText && (
|
{showText && (
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
"font-bold bg-horny-gradient bg-clip-text text-transparent",
|
"font-bold gradient-text",
|
||||||
size === "sm" && "text-base",
|
size === "sm" && "text-base",
|
||||||
size === "md" && "text-xl",
|
size === "md" && "text-xl",
|
||||||
size === "lg" && "text-2xl"
|
size === "lg" && "text-2xl"
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export function CruisingMap({ vanillaMode, onActiveCountChange }: MapProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-full w-full bg-[#0a1628]">
|
<div className="relative h-full w-full bg-pulse-deep-space">
|
||||||
{/* Minimal top controls — Sniffies style */}
|
{/* Minimal top controls — Sniffies style */}
|
||||||
<div className="absolute top-2 left-2 right-2 z-[1000] flex gap-2 items-start pointer-events-none">
|
<div className="absolute top-2 left-2 right-2 z-[1000] flex gap-2 items-start pointer-events-none">
|
||||||
<div className="pointer-events-auto flex gap-2 flex-wrap">
|
<div className="pointer-events-auto flex gap-2 flex-wrap">
|
||||||
@@ -183,13 +183,13 @@ export function CruisingMap({ vanillaMode, onActiveCountChange }: MapProps) {
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => setShowFilters(!showFilters)}
|
onClick={() => setShowFilters(!showFilters)}
|
||||||
className="shadow-lg bg-[#0a1628]/90 border-white/10 text-white h-9"
|
className="shadow-lg rounded-full bg-pulse-midnight/90 border-primary/20 text-white h-9"
|
||||||
>
|
>
|
||||||
<Filter className="h-4 w-4" />
|
<Filter className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Badge
|
<Badge
|
||||||
variant="online"
|
variant="online"
|
||||||
className="shadow-lg self-center bg-blue-500/20 text-blue-300 border-blue-500/30"
|
className="shadow-lg self-center bg-primary/20 text-pulse-pink-light border-primary/30"
|
||||||
>
|
>
|
||||||
{filteredProfiles.filter((p) => p.status !== "offline").length} cruising
|
{filteredProfiles.filter((p) => p.status !== "offline").length} cruising
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -202,7 +202,7 @@ export function CruisingMap({ vanillaMode, onActiveCountChange }: MapProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showFilters && (
|
{showFilters && (
|
||||||
<div className="absolute top-12 left-2 z-[1000] w-72 rounded-xl border border-white/10 bg-[#0a1628]/98 backdrop-blur-md p-4 shadow-2xl space-y-4 max-h-[70vh] overflow-y-auto">
|
<div className="absolute top-12 left-2 z-[1000] w-72 rounded-xl border border-primary/15 bg-pulse-midnight/98 backdrop-blur-md p-4 shadow-pulse-card space-y-4 max-h-[70vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className="font-semibold text-sm text-white">Filters</span>
|
<span className="font-semibold text-sm text-white">Filters</span>
|
||||||
<Button variant="ghost" size="icon" onClick={() => setShowFilters(false)}>
|
<Button variant="ghost" size="icon" onClick={() => setShowFilters(false)}>
|
||||||
@@ -331,7 +331,7 @@ export function CruisingMap({ vanillaMode, onActiveCountChange }: MapProps) {
|
|||||||
{/* Recenter — above local guide dock on mobile */}
|
{/* Recenter — above local guide dock on mobile */}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="absolute bottom-32 right-3 z-[1000] p-3 rounded-full bg-[#0a1628]/90 border border-white/15 text-blue-400 shadow-lg touch-manipulation md:bottom-6"
|
className="absolute bottom-32 right-3 z-[1000] p-3 rounded-full bg-pulse-midnight/90 border border-primary/25 text-pulse-pink-light shadow-pulse-glow touch-manipulation md:bottom-6"
|
||||||
aria-label="Recenter map"
|
aria-label="Recenter map"
|
||||||
>
|
>
|
||||||
<Locate className="h-5 w-5" />
|
<Locate className="h-5 w-5" />
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function MobileHeader({
|
|||||||
<header className="md:hidden fixed top-0 left-0 right-0 z-50 flex h-12 items-center justify-between border-b border-border bg-horny-dark/95 backdrop-blur-md px-3 safe-top">
|
<header className="md:hidden fixed top-0 left-0 right-0 z-50 flex h-12 items-center justify-between border-b border-border bg-horny-dark/95 backdrop-blur-md px-3 safe-top">
|
||||||
<Link href="/" className="flex items-center gap-1.5 min-w-0">
|
<Link href="/" className="flex items-center gap-1.5 min-w-0">
|
||||||
<Logo size="sm" showText={false} />
|
<Logo size="sm" showText={false} />
|
||||||
<span className="text-sm font-bold bg-horny-gradient bg-clip-text text-transparent truncate">
|
<span className="text-sm font-bold gradient-text truncate">
|
||||||
ExposedGays
|
ExposedGays
|
||||||
</span>
|
</span>
|
||||||
{activeCount > 0 && (
|
{activeCount > 0 && (
|
||||||
@@ -44,7 +44,7 @@ export function MobileHeader({
|
|||||||
{vanillaMode ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
|
{vanillaMode ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
{isGuest ? (
|
{isGuest ? (
|
||||||
<Badge variant="outline" className="text-[8px] px-1.5 text-blue-400 border-blue-400/30">
|
<Badge variant="pill" className="text-[8px] px-1.5">
|
||||||
Guest
|
Guest
|
||||||
</Badge>
|
</Badge>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export function Nav({
|
|||||||
Vanilla
|
Vanilla
|
||||||
</Button>
|
</Button>
|
||||||
{isGuest && (
|
{isGuest && (
|
||||||
<Badge variant="outline" className="text-[10px] text-blue-400 border-blue-400/30">
|
<Badge variant="pill" className="text-[10px]">
|
||||||
Guest
|
Guest
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function Shop() {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-horny-dark">
|
<div className="min-h-screen bg-horny-dark">
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
<div className="bg-horny-gradient px-4 py-8 md:py-12">
|
<div className="bg-pulse-gradient-bold px-4 py-8 md:py-12">
|
||||||
<div className="mx-auto max-w-6xl">
|
<div className="mx-auto max-w-6xl">
|
||||||
<h1 className="text-3xl md:text-4xl font-bold text-white">
|
<h1 className="text-3xl md:text-4xl font-bold text-white">
|
||||||
ExposedGays Shop
|
ExposedGays Shop
|
||||||
|
|||||||
@@ -3,19 +3,25 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const badgeVariants = cva(
|
const badgeVariants = cva(
|
||||||
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-bold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
default:
|
||||||
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
"border-transparent bg-pulse-gradient-bold text-white shadow-sm",
|
||||||
destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
secondary:
|
||||||
outline: "text-foreground",
|
"border-transparent bg-secondary text-secondary-foreground",
|
||||||
top: "border-transparent bg-blue-500/20 text-blue-400",
|
destructive:
|
||||||
bottom: "border-transparent bg-orange-500/20 text-orange-400",
|
"border-transparent bg-destructive text-destructive-foreground shadow",
|
||||||
vers: "border-transparent bg-purple-500/20 text-purple-400",
|
outline: "border-pulse-border/60 text-foreground bg-pulse-midnight/30",
|
||||||
side: "border-transparent bg-green-500/20 text-green-400",
|
pill:
|
||||||
online: "border-transparent bg-green-500/20 text-green-400 animate-pulse",
|
"border-primary/30 bg-primary/15 text-pulse-pink-light",
|
||||||
|
top: "border-transparent bg-primary/20 text-pulse-pink-light",
|
||||||
|
bottom: "border-transparent bg-orange-500/20 text-orange-300",
|
||||||
|
vers: "border-transparent bg-pulse-violet/25 text-pulse-lavender",
|
||||||
|
side: "border-transparent bg-pulse-teal/20 text-pulse-teal",
|
||||||
|
online:
|
||||||
|
"border-transparent bg-emerald-500/20 text-emerald-300 animate-pulse",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: { variant: "default" },
|
defaultVariants: { variant: "default" },
|
||||||
|
|||||||
@@ -4,23 +4,33 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-semibold transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 touch-manipulation active:scale-[0.98]",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
default:
|
||||||
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
"rounded-full bg-pulse-gradient-bold text-white shadow-pulse-glow hover:opacity-90 hover:-translate-y-px",
|
||||||
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
destructive:
|
||||||
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
"rounded-full bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
outline:
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
"rounded-full border border-pulse-border/80 bg-pulse-midnight/40 text-foreground hover:border-primary/40 hover:bg-primary/10",
|
||||||
horny: "bg-horny-gradient text-white shadow-lg hover:opacity-90 font-semibold",
|
secondary:
|
||||||
|
"rounded-full bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||||
|
ghost:
|
||||||
|
"rounded-full hover:bg-primary/10 hover:text-primary",
|
||||||
|
link: "text-primary underline-offset-4 hover:underline rounded-none",
|
||||||
|
horny:
|
||||||
|
"rounded-full bg-pulse-gradient-bold text-white shadow-pulse-glow hover:opacity-90 hover:-translate-y-px font-bold",
|
||||||
|
pill:
|
||||||
|
"rounded-full pulse-pill-inactive font-bold hover:border-primary/35",
|
||||||
|
"pill-active":
|
||||||
|
"rounded-full pulse-pill-active font-bold",
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-10 px-4 py-2",
|
default: "h-10 px-5 py-2",
|
||||||
sm: "h-8 rounded-md px-3 text-xs",
|
sm: "h-8 px-4 text-xs",
|
||||||
lg: "h-12 rounded-md px-8 text-base",
|
lg: "h-12 px-8 text-base",
|
||||||
icon: "h-10 w-10",
|
icon: "h-10 w-10 rounded-full",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: { variant: "default", size: "default" },
|
defaultVariants: { variant: "default", size: "default" },
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||||
({ className, ...props }, ref) => (
|
({ className, ...props }, ref) => (
|
||||||
<div ref={ref} className={cn("rounded-xl border bg-card text-card-foreground shadow", className)} {...props} />
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"rounded-xl border border-white/[0.06] bg-card/90 text-card-foreground shadow-pulse-card backdrop-blur-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
Card.displayName = "Card";
|
Card.displayName = "Card";
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
|||||||
<input
|
<input
|
||||||
type={type}
|
type={type}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
"flex h-11 w-full rounded-xl border border-input bg-pulse-midnight/50 px-3 py-2 text-base text-foreground ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 focus-visible:border-primary/40 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const TabsList = React.forwardRef<
|
|||||||
<TabsPrimitive.List
|
<TabsPrimitive.List
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
"inline-flex h-auto min-h-10 items-center gap-1 rounded-full bg-pulse-midnight/60 p-1 text-muted-foreground border border-pulse-border/40",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -28,7 +28,7 @@ const TabsTrigger = React.forwardRef<
|
|||||||
<TabsPrimitive.Trigger
|
<TabsPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
"inline-flex items-center justify-center whitespace-nowrap rounded-full px-4 py-2 text-sm font-bold ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-pulse-gradient-bold data-[state=active]:text-white data-[state=active]:shadow-pulse-glow data-[state=inactive]:text-pulse-muted data-[state=inactive]:hover:text-pulse-pink-light touch-manipulation",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -42,7 +42,10 @@ const TabsContent = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<TabsPrimitive.Content
|
<TabsPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className)}
|
className={cn(
|
||||||
|
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ export const KINK_OPTIONS = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const POSITION_COLORS: Record<Position, string> = {
|
export const POSITION_COLORS: Record<Position, string> = {
|
||||||
top: "#3b82f6",
|
top: "#F92B9B",
|
||||||
bottom: "#f97316",
|
bottom: "#f97316",
|
||||||
vers: "#a855f7",
|
vers: "#a855f7",
|
||||||
side: "#22c55e",
|
side: "#22c55e",
|
||||||
|
|||||||
@@ -43,20 +43,43 @@ const config: Config = {
|
|||||||
DEFAULT: "hsl(var(--card))",
|
DEFAULT: "hsl(var(--card))",
|
||||||
foreground: "hsl(var(--card-foreground))",
|
foreground: "hsl(var(--card-foreground))",
|
||||||
},
|
},
|
||||||
|
pulse: {
|
||||||
|
pink: "#F92B9B",
|
||||||
|
"pink-light": "#FF6EC7",
|
||||||
|
"pink-dark": "#CC1A7A",
|
||||||
|
violet: "#8B22CC",
|
||||||
|
lavender: "#C084FC",
|
||||||
|
teal: "#03A4A8",
|
||||||
|
"deep-space": "#08001C",
|
||||||
|
midnight: "#1A003A",
|
||||||
|
glow: "#470070",
|
||||||
|
border: "#1E2D4A",
|
||||||
|
muted: "#8B92A8",
|
||||||
|
},
|
||||||
horny: {
|
horny: {
|
||||||
pink: "#ff2d6b",
|
pink: "#F92B9B",
|
||||||
purple: "#8b2fc9",
|
purple: "#8B22CC",
|
||||||
dark: "#0d0a0f",
|
dark: "#08001C",
|
||||||
surface: "#1a1220",
|
surface: "#1A003A",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
lg: "var(--radius)",
|
lg: "var(--radius)",
|
||||||
md: "calc(var(--radius) - 2px)",
|
md: "calc(var(--radius) - 2px)",
|
||||||
sm: "calc(var(--radius) - 4px)",
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
pill: "9999px",
|
||||||
},
|
},
|
||||||
backgroundImage: {
|
backgroundImage: {
|
||||||
"horny-gradient": "linear-gradient(135deg, #ff2d6b 0%, #8b2fc9 50%, #ff2d6b 100%)",
|
"pulse-gradient": "linear-gradient(135deg, #FF2D9B 0%, #C084FC 50%, #FF2D9B 100%)",
|
||||||
|
"pulse-gradient-bold": "linear-gradient(135deg, #FF2D9B 0%, #9B30FF 100%)",
|
||||||
|
"horny-gradient": "linear-gradient(135deg, #FF2D9B 0%, #C084FC 50%, #FF2D9B 100%)",
|
||||||
|
},
|
||||||
|
boxShadow: {
|
||||||
|
"pulse-glow": "0 0 16px rgba(249, 43, 155, 0.4), 0 0 32px rgba(249, 43, 155, 0.15)",
|
||||||
|
"pulse-card": "0 12px 40px rgba(249, 43, 155, 0.12)",
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: ["var(--font-manrope)", "system-ui", "sans-serif"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user