From 70251093a85ee22ffdb48a53987dd8f03f8f1c8b Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 18 Dec 2025 15:19:25 -0500 Subject: [PATCH] beiser --- src/components/Map/MapView.jsx | 48 ++- src/components/Map/markerManager.js | 164 +++++---- src/components/Map/templateSpecs.js | 71 ++++ src/components/Posts/PostCard.jsx | 36 +- src/styles/layout.css | 8 +- src/styles/map.css | 35 +- src/styles/mapMarkers.css | 545 ++++++++++++++++++++++++++++ src/styles/posts.css | 80 ++-- 8 files changed, 855 insertions(+), 132 deletions(-) create mode 100644 src/components/Map/templateSpecs.js diff --git a/src/components/Map/MapView.jsx b/src/components/Map/MapView.jsx index b297d21..e72320d 100644 --- a/src/components/Map/MapView.jsx +++ b/src/components/Map/MapView.jsx @@ -185,7 +185,7 @@ export default function MapView({ theme = "dark" }) { }; return ( -
+
\n
{status &&
{status}
} @@ -280,26 +280,36 @@ export default function MapView({ theme = "dark" }) {
)} -
-
-
Sociowall
- -
-
-
Chat
-
    -
  • Yan
  • -
  • Marc
  • -
  • Fiso
  • -
+ +
+ + {/* BELOW THE MAP (page scroll) */} +
+
+
+
Sociowall
+ +
+ +
+
Chat
+
    +
  • Yan
  • +
  • Marc
  • +
  • Fiso
  • +
+
+ +
+
); } diff --git a/src/components/Map/markerManager.js b/src/components/Map/markerManager.js index cff2c63..0eba557 100644 --- a/src/components/Map/markerManager.js +++ b/src/components/Map/markerManager.js @@ -2,17 +2,17 @@ import maplibregl from "maplibre-gl"; import React from "react"; import { createRoot } from "react-dom/client"; -import TemplateMarkerCard from "./TemplateMarkerCard"; -import { getDefaultTemplateCached } from "../../api/templates"; +import CardRenderer from "../Cards/CardRenderer"; +import { cardTokens } from "../../theme/cardTokens"; +import { getTemplateSpecForPost, adaptPostToTemplateData } from "./templateSpecs"; export function clearAllMarkers(markersRef, expandedElRef) { if (markersRef.current) { for (const m of markersRef.current) { try { - if (m?.el && m.el.__reactRoot) { - try { m.el.__reactRoot.unmount(); } catch {} - m.el.__reactRoot = null; - } + if (m?.el && m.el.__swUnmount) m.el.__swUnmount(); + } catch {} + try { m.marker.remove(); } catch {} } @@ -72,29 +72,30 @@ export function clearOcclusion(markersRef) { } } -function escapeHtml(str) { - return String(str) - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """); +function mountCard(container, spec, data, theme) { + const root = createRoot(container); + const tokens = cardTokens?.[theme] || cardTokens.blue; + + root.render( + React.createElement(CardRenderer, { + spec, + data, + themeTokens: tokens, + onAction: (action, value) => { + if (action?.type === "open_url" && value) { + try { window.open(value, "_blank"); } catch {} + } + }, + className: "", + }) + ); + + return () => { + try { root.unmount(); } catch {} + }; } -function currentTheme() { - try { - const t = document?.body?.getAttribute("data-theme") || "dark"; - if (t === "dark" || t === "blue" || t === "light") return t; - } catch {} - return "dark"; -} - -function ensureReactRoot(el) { - if (el.__reactRoot) return el.__reactRoot; - el.__reactRoot = createRoot(el); - return el.__reactRoot; -} - -export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { +export function createMarkerForPost(post, mapRef, markersRef, expandedElRef, theme = "blue") { const map = mapRef.current; if (!map) return; @@ -117,65 +118,98 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { return; } - const title = (post.title || "").trim() || "Untitled"; - const root = document.createElement("div"); root.className = "post-pin post-pin--compact"; root.style.zIndex = "1"; + function unmountIfAny() { + if (root.__swUnmount) { + try { root.__swUnmount(); } catch {} + root.__swUnmount = null; + } + } + function renderCompact() { + unmountIfAny(); root.className = "post-pin post-pin--compact"; root.style.zIndex = "1"; + // pointer stays: .post-pin-pointer-small (UNCHANGED) root.innerHTML = ` -
-
-
${escapeHtml(title)}
-
+
`; - if (root.__reactRoot) { - try { root.__reactRoot.unmount(); } catch {} - root.__reactRoot = null; + const wrap = root.querySelector(".sw-template-mini-wrap"); + if (wrap) { + const spec = getTemplateSpecForPost(post, "mini"); + const data = adaptPostToTemplateData(post); + root.__swUnmount = mountCard(wrap, spec, data, theme); } clearOcclusion(markersRef); } - async function renderExpanded() { + function renderExpanded() { + unmountIfAny(); root.className = "post-pin post-pin--expanded"; root.style.zIndex = "999999"; + // pointer stays: .post-card-pointer (UNCHANGED) + const headline = escapeHtml(post?.title || "Untitled"); + root.innerHTML = ` -
-
Loading template…
+
+
+
+
+
+ +
+
Watching
+
+
☑ Julia ★
— I see it…
+
☑ Kim / CNN
— Blah blah blah
+
☑ Yan ★
— Watch this!!
+
+ +
+
+ +
+
${headline}
+
The news here (generated)
+
+ +
+ + + + +
+ +
+
Live chat / comments
+
+
— …
+
— what the f***?
+
— nice…
+
— my eyes!!
+
+
+ + +
+
`; - const cardEl = root.querySelector(".post-card"); - if (!cardEl) return; - - const theme = currentTheme(); - - try { - const tpl = await getDefaultTemplateCached("news"); - - const rr = ensureReactRoot(cardEl); - rr.render( - React.createElement(TemplateMarkerCard, { - post, - template: tpl, - theme, - mode: "full", - }) - ); - } catch (e) { - cardEl.innerHTML = ` -
${escapeHtml(title)}
-
(template load failed)
- `; + const wrap = root.querySelector(".sw-template-full-wrap"); + if (wrap) { + const spec = getTemplateSpecForPost(post, "full"); + const data = adaptPostToTemplateData(post); + root.__swUnmount = mountCard(wrap, spec, data, theme); } requestAnimationFrame(() => { @@ -210,3 +244,11 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { } }); } + +function escapeHtml(str) { + return String(str ?? "") + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """); +} diff --git a/src/components/Map/templateSpecs.js b/src/components/Map/templateSpecs.js new file mode 100644 index 0000000..0ad7d57 --- /dev/null +++ b/src/components/Map/templateSpecs.js @@ -0,0 +1,71 @@ +/** + * Frontend-only template specs (no DB changes). + * Keep pointers as-is: + * - compact triangle: .post-pin-pointer-small + * - expanded triangle: .post-card-pointer + */ + +export const TEMPLATE_SPECS = { + news: { + mini_spec: { + size: { w: 280, h: 110 }, + background: { type: "gradient", value: "newsBlue" }, + radius: 18, + layers: [ + { id: "badge", type: "chip", x: 14, y: 12, text: "NEWS", style: "chip.news" }, + { id: "title", type: "text", x: 14, y: 40, w: 252, h: 44, bind: "data.headline", style: "text.title", maxLines: 2 }, + { id: "meta", type: "text", x: 14, y: 88, w: 252, h: 16, bind: "data.source", style: "text.meta", maxLines: 1 } + ], + }, + full_spec: { + size: { w: 360, h: 520 }, + background: { type: "solid", value: "surface" }, + radius: 22, + layers: [ + { id: "hero", type: "image", x: 0, y: 0, w: 360, h: 220, bind: "data.image" }, + { id: "badge", type: "chip", x: 16, y: 16, text: "NEWS", style: "chip.news" }, + { id: "title", type: "text", x: 16, y: 240, w: 328, h: 78, bind: "data.headline", style: "text.h1", maxLines: 3 }, + { id: "summary", type: "text", x: 16, y: 325, w: 328, h: 110, bind: "data.summary", style: "text.body", maxLines: 5 }, + { + id: "cta", + type: "button", + x: 16, y: 450, w: 328, h: 48, + text: "Open source", + style: "button.primary", + action: { type: "open_url", bind: "data.url" } + } + ], + }, + }, +}; + +function normCat(post) { + const c = (post?.category || "").toString().toUpperCase(); + if (c === "NEWS") return "news"; + if (c === "EVENT") return "news"; + if (c === "FRIENDS") return "news"; + if (c === "MARKET") return "news"; + return "news"; +} + +export function getTemplateKeyForPost(post) { + // Future mapping: if (post.template_id === 101) return "news"; + return normCat(post); +} + +export function getTemplateSpecForPost(post, variant /* "mini"|"full" */) { + const key = getTemplateKeyForPost(post); + const t = TEMPLATE_SPECS[key] || TEMPLATE_SPECS.news; + return variant === "full" ? t.full_spec : t.mini_spec; +} + +export function adaptPostToTemplateData(post) { + const headline = post?.title || "Untitled"; + const author = post?.author ? `by ${post.author}` : ""; + const sub = post?.sub_category ? String(post.sub_category) : ""; + const source = author || sub || ""; + const summary = post?.snippet || post?.body || ""; + const url = post?.url || ""; + const image = post?.image_large || post?.image_small || post?.image || post?.media_url || ""; + return { headline, source, summary, url, image }; +} diff --git a/src/components/Posts/PostCard.jsx b/src/components/Posts/PostCard.jsx index 0a2d5a4..96172e7 100644 --- a/src/components/Posts/PostCard.jsx +++ b/src/components/Posts/PostCard.jsx @@ -1,24 +1,28 @@ import React from "react"; - -function getKmFromPost(post) { - return post.km ?? post.distance_km ?? post.distanceKm ?? post.dist_km ?? null; -} +import CardRenderer from "../Cards/CardRenderer"; +import { cardTokens } from "../../theme/cardTokens"; +import { getTemplateSpecForPost, adaptPostToTemplateData } from "../Map/templateSpecs"; export default function PostCard({ post, selected, onSelect }) { - const title = post.title || post.name || "Post"; - const fullBody = post.body || post.content || post.text || ""; - const body = fullBody.length > 80 ? fullBody.slice(0, 77) + "..." : fullBody; - const km = getKmFromPost(post); - - function handleClick() { - if (onSelect) onSelect(post); - } + const spec = getTemplateSpecForPost(post, "mini"); + const data = adaptPostToTemplateData(post); return ( -
-

{title}

-

{body}

- {km != null && {km} km} +
onSelect && onSelect(post)} + style={{ padding: 6 }} + > +
+ { + if (action?.type === "open_url" && value) window.open(value, "_blank"); + }} + /> +
); } diff --git a/src/styles/layout.css b/src/styles/layout.css index aa6e899..4510a6b 100644 --- a/src/styles/layout.css +++ b/src/styles/layout.css @@ -1,3 +1,5 @@ -.app-root { height: 100vh; display: flex; flex-direction: column; } -.main-shell { flex: 1; display: flex; padding: 0; } -.map-shell { position: relative; flex: 1; border-radius: 0; overflow: hidden; border: none; background: #020617; } +.app-root{ min-height:100vh; display:flex; flex-direction:column; } + +/* IMPORTANT: allow scrolling under the map */ +.main-shell{ flex: 0 0 auto; display:block; padding:0; } +.map-shell{ position:relative; width:100%; height:62vh; border-radius:0; overflow:hidden; border:none; background:#020617; } diff --git a/src/styles/map.css b/src/styles/map.css index 2860dc8..7fbb292 100644 --- a/src/styles/map.css +++ b/src/styles/map.css @@ -1,5 +1,19 @@ -.map-view { position: relative; width: 100%; height: 100%; } -.map-container, .maplibre-container { position: absolute; inset: 0; width: 100%; height: 100%; } +.map-page { display: flex; flex-direction: column; } + +/* Map stage (visible first). Then you scroll down for the wall. */ +.map-stage { + position: relative; + width: 100%; + height: clamp(520px, 72vh, 860px); +} + +.map-container, .maplibre-container { + position: absolute; + inset: 0; + width: 100%; + height: 100%; +} + .map-status { position: absolute; left: 0.5rem; @@ -8,4 +22,21 @@ padding: 0.2rem 0.4rem; background: rgba(0, 0, 0, 0.6); border-radius: 0.5rem; + z-index: 30; +} + +/* Below map area */ +.below-stage{ + padding: 0.25rem 0.7rem 1.0rem; +} +.below-row{ + display:flex; + gap:.6rem; + align-items:stretch; +} + +/* Mobile: stack */ +@media (max-width: 640px){ + .map-stage{ height: clamp(520px, 78vh, 900px); } + .below-row{ flex-direction: column; } } diff --git a/src/styles/mapMarkers.css b/src/styles/mapMarkers.css index c64bfdb..41a7962 100644 --- a/src/styles/mapMarkers.css +++ b/src/styles/mapMarkers.css @@ -88,3 +88,548 @@ border-top:11px solid rgba(8, 20, 40, 0.97); filter: drop-shadow(0 2px 4px rgba(0,0,0,.8)); } + +/* ===== Template marker wrappers (pointers stay the same classes) ===== */ +.sw-template-mini-wrap{ + position: absolute; + left: 0; + top: 0; + transform: translate(-50%, calc(-100% - 12px)); +} + +.sw-expanded-shell{ + padding: 10px 12px; +} + +.sw-expanded-top{ + display:flex; + gap:10px; + align-items:flex-start; +} + +.sw-expanded-left{ + flex: 1; +} + +.sw-expanded-right{ + width: 150px; + min-width: 140px; + display:flex; + flex-direction:column; + gap:8px; + padding-top: 4px; +} + +.sw-watch-title{ + font-size: 11px; + font-weight: 800; + color:#bfdbfe; + text-transform: uppercase; + letter-spacing: .06em; +} + +.sw-watch-list{ + display:flex; + flex-direction:column; + gap:6px; +} + +.sw-watch-item{ + font-size: 11px; + color:#e8f5ff; + background: rgba(3, 14, 32, 0.75); + border: 1px solid rgba(90, 190, 255, 0.35); + border-radius: 10px; + padding: 6px 8px; +} + +.sw-watch-msg{ + opacity:.85; + margin-top:2px; + font-size: 10px; + color:#c7e3ff; +} + +.sw-add-feed-btn{ + margin-top: 2px; + border: 1px solid rgba(148,163,184,.7); + border-radius: 10px; + padding: 8px 10px; + background: rgba(5, 35, 70, 0.85); + color:#e8f5ff; + font-weight: 900; + font-size: 11px; + cursor:pointer; +} + +.sw-news-generated{ + margin-top: 10px; + padding: 8px 10px; + border-radius: 12px; + background: rgba(3, 14, 32, 0.75); + border: 1px solid rgba(90, 190, 255, 0.35); +} + +.sw-news-title{ + font-size: 12px; + font-weight: 900; + color:#e8f5ff; + margin-bottom: 2px; +} + +.sw-news-sub{ + font-size: 10px; + color:#9eb7ff; +} + +.sw-actions-row{ + margin-top: 8px; +} + +.sw-livechat{ + margin-top: 8px; +} + +.sw-livechat-title{ + font-weight: 800; + letter-spacing:.04em; + margin-bottom: 6px; +} + +.sw-livechat-body{ + display:flex; + flex-direction:column; + gap:3px; + margin-bottom: 8px; + opacity:.95; +} + +.sw-chat-line{ + font-size: 10px; + color:#c7e3ff; +} + +.sw-livechat-inputrow{ + display:flex; + gap:8px; + align-items:center; +} + +.sw-livechat-input{ + flex:1; + border-radius: 999px; + border: 1px solid rgba(90, 190, 255, 0.35); + background: rgba(3, 14, 32, 0.75); + color:#e8f5ff; + padding: 8px 10px; + font-size: 11px; + outline: none; +} + +.sw-livechat-post{ + border:none; + border-radius: 10px; + padding: 8px 12px; + background: rgba(56,189,248,0.22); + color:#e8f5ff; + font-weight: 900; + font-size: 11px; + cursor:pointer; +} + +/* ===== Template marker wrappers (pointers stay the same classes) ===== */ +.sw-template-mini-wrap{ + position: absolute; + left: 0; + top: 0; + transform: translate(-50%, calc(-100% - 12px)); +} + +.sw-expanded-shell{ + padding: 10px 12px; +} + +.sw-expanded-top{ + display:flex; + gap:10px; + align-items:flex-start; +} + +.sw-expanded-left{ + flex: 1; +} + +.sw-expanded-right{ + width: 150px; + min-width: 140px; + display:flex; + flex-direction:column; + gap:8px; + padding-top: 4px; +} + +.sw-watch-title{ + font-size: 11px; + font-weight: 800; + color:#bfdbfe; + text-transform: uppercase; + letter-spacing: .06em; +} + +.sw-watch-list{ + display:flex; + flex-direction:column; + gap:6px; +} + +.sw-watch-item{ + font-size: 11px; + color:#e8f5ff; + background: rgba(3, 14, 32, 0.75); + border: 1px solid rgba(90, 190, 255, 0.35); + border-radius: 10px; + padding: 6px 8px; +} + +.sw-watch-msg{ + opacity:.85; + margin-top:2px; + font-size: 10px; + color:#c7e3ff; +} + +.sw-add-feed-btn{ + margin-top: 2px; + border: 1px solid rgba(148,163,184,.7); + border-radius: 10px; + padding: 8px 10px; + background: rgba(5, 35, 70, 0.85); + color:#e8f5ff; + font-weight: 900; + font-size: 11px; + cursor:pointer; +} + +.sw-news-generated{ + margin-top: 10px; + padding: 8px 10px; + border-radius: 12px; + background: rgba(3, 14, 32, 0.75); + border: 1px solid rgba(90, 190, 255, 0.35); +} + +.sw-news-title{ + font-size: 12px; + font-weight: 900; + color:#e8f5ff; + margin-bottom: 2px; +} + +.sw-news-sub{ + font-size: 10px; + color:#9eb7ff; +} + +.sw-actions-row{ + margin-top: 8px; +} + +.sw-livechat{ + margin-top: 8px; +} + +.sw-livechat-title{ + font-weight: 800; + letter-spacing:.04em; + margin-bottom: 6px; +} + +.sw-livechat-body{ + display:flex; + flex-direction:column; + gap:3px; + margin-bottom: 8px; + opacity:.95; +} + +.sw-chat-line{ + font-size: 10px; + color:#c7e3ff; +} + +.sw-livechat-inputrow{ + display:flex; + gap:8px; + align-items:center; +} + +.sw-livechat-input{ + flex:1; + border-radius: 999px; + border: 1px solid rgba(90, 190, 255, 0.35); + background: rgba(3, 14, 32, 0.75); + color:#e8f5ff; + padding: 8px 10px; + font-size: 11px; + outline: none; +} + +.sw-livechat-post{ + border:none; + border-radius: 10px; + padding: 8px 12px; + background: rgba(56,189,248,0.22); + color:#e8f5ff; + font-weight: 900; + font-size: 11px; + cursor:pointer; +} + +/* ===== Template marker wrappers (pointers stay the same classes) ===== */ +.sw-template-mini-wrap{ + position: absolute; + left: 0; + top: 0; + transform: translate(-50%, calc(-100% - 12px)); +} + +.sw-expanded-shell{ padding: 10px 12px; } + +.sw-expanded-top{ + display:flex; + gap:10px; + align-items:flex-start; +} + +.sw-expanded-left{ flex: 1; } + +.sw-expanded-right{ + width: 150px; + min-width: 140px; + display:flex; + flex-direction:column; + gap:8px; + padding-top: 4px; +} + +.sw-watch-title{ + font-size: 11px; + font-weight: 800; + color:#bfdbfe; + text-transform: uppercase; + letter-spacing: .06em; +} + +.sw-watch-list{ display:flex; flex-direction:column; gap:6px; } + +.sw-watch-item{ + font-size: 11px; + color:#e8f5ff; + background: rgba(3, 14, 32, 0.75); + border: 1px solid rgba(90, 190, 255, 0.35); + border-radius: 10px; + padding: 6px 8px; +} + +.sw-watch-msg{ + opacity:.85; + margin-top:2px; + font-size: 10px; + color:#c7e3ff; +} + +.sw-add-feed-btn{ + margin-top: 2px; + border: 1px solid rgba(148,163,184,.7); + border-radius: 10px; + padding: 8px 10px; + background: rgba(5, 35, 70, 0.85); + color:#e8f5ff; + font-weight: 900; + font-size: 11px; + cursor:pointer; +} + +.sw-news-generated{ + margin-top: 10px; + padding: 8px 10px; + border-radius: 12px; + background: rgba(3, 14, 32, 0.75); + border: 1px solid rgba(90, 190, 255, 0.35); +} + +.sw-news-title{ + font-size: 12px; + font-weight: 900; + color:#e8f5ff; + margin-bottom: 2px; +} + +.sw-news-sub{ font-size: 10px; color:#9eb7ff; } + +.sw-actions-row{ margin-top: 8px; } + +.sw-livechat{ margin-top: 8px; } + +.sw-livechat-title{ + font-weight: 800; + letter-spacing:.04em; + margin-bottom: 6px; +} + +.sw-livechat-body{ + display:flex; + flex-direction:column; + gap:3px; + margin-bottom: 8px; + opacity:.95; +} + +.sw-chat-line{ font-size: 10px; color:#c7e3ff; } + +.sw-livechat-inputrow{ display:flex; gap:8px; align-items:center; } + +.sw-livechat-input{ + flex:1; + border-radius: 999px; + border: 1px solid rgba(90, 190, 255, 0.35); + background: rgba(3, 14, 32, 0.75); + color:#e8f5ff; + padding: 8px 10px; + font-size: 11px; + outline: none; +} + +.sw-livechat-post{ + border:none; + border-radius: 10px; + padding: 8px 12px; + background: rgba(56,189,248,0.22); + color:#e8f5ff; + font-weight: 900; + font-size: 11px; + cursor:pointer; +} + +/* ========================================================= + RESPONSIVE SIZING FIX + - Mini markers were too big (280x110 real size) + - Expanded card was overflowing on mobile + ========================================================= */ + +/* Mini template wrapper: keep pointer EXACTLY as-is, only scale the card */ +.sw-template-mini-wrap{ + /* was: translate(-50%, calc(-100% - 12px)) */ + transform: translate(-50%, calc(-100% - 12px)) scale(var(--sw-mini-scale, 0.72)); + transform-origin: bottom center; + will-change: transform; +} + +/* Expanded card: make it fit phone screens nicely */ +.post-pin--expanded .post-card{ + max-width: min(92vw, 380px); + width: auto; + max-height: min(72vh, 640px); + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +/* Layout in expanded sketch area */ +.sw-expanded-top{ + gap: 10px; +} + +/* Mobile tweaks */ +@media (max-width: 640px){ + /* Shrink mini markers even more on phones */ + .sw-template-mini-wrap{ + --sw-mini-scale: 0.58; + } + + /* Expanded: stack instead of side-by-side */ + .sw-expanded-top{ + flex-direction: column; + } + + /* Right panel becomes horizontal strip (or you can hide it if you prefer) */ + .sw-expanded-right{ + width: 100%; + min-width: 0; + flex-direction: row; + gap: 8px; + align-items: center; + overflow-x: auto; + padding-top: 0; + } + + .sw-watch-title{ + white-space: nowrap; + margin-right: 6px; + } + + .sw-watch-list{ + flex-direction: row; + gap: 8px; + } + + .sw-watch-item{ + min-width: 180px; + flex: 0 0 auto; + } + + .sw-add-feed-btn{ + flex: 0 0 auto; + white-space: nowrap; + } +} + + +/* SW_EXPANDED_OFFSET_FIX: lower expanded cards on phones (keep pointers unchanged) */ +@media (max-width: 640px){ + .post-pin--expanded .post-card{ + transform: translate(-50%, calc(-100% - 6px)); + } +} + + +/* SW_MOBILE_EXPANDED_TIGHTEN: make expanded marker card less tall on phones (no pointer change) */ +@media (max-width: 640px){ + .post-pin--expanded .post-card{ + padding: 8px 10px; + max-width: 300px; + } + .post-pin--expanded .post-card-main{ gap: 6px; margin-bottom: 6px; } + .post-pin--expanded .post-card-media{ width: 56px; height: 56px; border-radius: 10px; } + .post-pin--expanded .post-card-title{ font-size: 12px; line-height: 15px; } + .post-pin--expanded .post-card-body{ font-size: 11px; max-height: 56px; } +} + +/* SW_TEMPLATE_FULL_TIGHTEN: make template-full card less tall on phones */ +@media (max-width: 640px){ + .sw-template-full{ + transform: translate(-50%, calc(-100% - 14px)) scale(0.88); + transform-origin: bottom center; + } +} + +/* ===== MOBILE TUNING: expanded marker popup (template OR classic) ===== */ +@media (max-width: 640px){ + /* shrink the whole expanded marker a bit */ + .post-pin--expanded{ + transform: translate3d(0,0,0) scale(0.86); + transform-origin: bottom center; + } + + /* keep it inside screen */ + .post-pin--expanded .post-card{ + max-width: min(92vw, 340px) !important; + } + + /* title/body: prevent giant blocks */ + .post-pin--expanded .post-card-title{ font-size: 12px !important; line-height: 15px !important; } + .post-pin--expanded .post-card-body{ font-size: 11px !important; line-height: 14px !important; max-height: 54px !important; } + + /* buttons/footer area: tighter */ + .post-pin--expanded .post-card-footer{ gap: 5px !important; } + .post-pin--expanded .post-card-btn{ font-size: 10px !important; padding: 3px 7px !important; } +} diff --git a/src/styles/posts.css b/src/styles/posts.css index 704a732..39bf383 100644 --- a/src/styles/posts.css +++ b/src/styles/posts.css @@ -1,34 +1,39 @@ -.map-overlay-wall { - position:absolute; - left:.7rem; right:.7rem; bottom:.6rem; - display:flex; gap:.6rem; align-items:stretch; - pointer-events:none; z-index:10; +/* Sociowall + Chat BELOW the map */ +.below-row{ + display:flex; + gap:.6rem; + align-items:stretch; } -.map-overlay-wall * { pointer-events:auto; } .sociowall-panel { - flex: 1.5; - min-height: 80px; - max-height: 150px; + flex: 1.8; + min-height: 160px; background: rgba(15, 23, 42, 0.96); border-radius: 14px; border: 1px solid rgba(148, 163, 184, 0.9); box-shadow: 0 10px 28px rgba(0,0,0,.9), 0 0 18px rgba(56,189,248,.45); padding: .45rem .55rem; - display:flex; flex-direction:column; -} -.sociowall-header { - font-size: .78rem; font-weight: 600; - letter-spacing: .06em; text-transform: uppercase; - color:#bfdbfe; margin-bottom:.25rem; + display:flex; + flex-direction:column; } -.post-list { flex:1; overflow-y:auto; padding-right:.15rem; } -.post-list-header { display:flex; align-items:center; gap:.5rem; margin-bottom:.2rem; font-size:.7rem; color:#cbd5f5; } -.km-filter input[type="range"] { width:130px; } +.sociowall-header { + font-size: .78rem; + font-weight: 700; + letter-spacing: .06em; + text-transform: uppercase; + color:#bfdbfe; + margin-bottom:.25rem; +} + +.post-list { flex: 1; overflow-y: auto; padding-right: .15rem; max-height: 44vh; } +.post-list-header { display:flex; align-items:center; gap:.5rem; margin-bottom:.25rem; font-size:.7rem; color:#cbd5f5; } +.km-filter input[type="range"] { width:160px; } + .status-text { font-size:.72rem; opacity:.85; margin:.15rem 0; } .status-error { color:#fecaca; } +/* list items compact */ .post-card { border-radius:10px; border:1px solid rgba(55, 65, 81, 0.9); @@ -53,28 +58,41 @@ .post-card h3 { margin:0 0 .12rem 0; font-size:.8rem; } .post-card p { margin:0; font-size:.72rem; opacity:.9; } -.post-km { - display:inline-block; margin-top:.12rem; font-size:.68rem; - padding:.05rem .35rem; border-radius:999px; - background: rgba(15, 118, 110, 0.2); - border: 1px solid rgba(45, 212, 191, 0.7); - color: #a5f3fc; -} - .chat-panel { - width:150px; min-width:130px; - max-height:150px; + width: 170px; + min-width: 170px; background: rgba(15, 23, 42, 0.96); border-radius: 14px; border: 1px solid rgba(148, 163, 184, 0.9); box-shadow: 0 10px 28px rgba(0,0,0,.9), 0 0 18px rgba(56,189,248,.45); padding:.4rem .45rem; - display:flex; flex-direction:column; + display:flex; + flex-direction:column; + + /* stays visible beside wall while scrolling inside the list */ + position: sticky; + top: 10px; + align-self: flex-start; } + .chat-header { - font-size:.78rem; font-weight:600; letter-spacing:.06em; text-transform:uppercase; - color:#bfdbfe; margin-bottom:.2rem; + font-size:.78rem; + font-weight:700; + letter-spacing:.06em; + text-transform:uppercase; + color:#bfdbfe; + margin-bottom:.2rem; } .chat-users { list-style:none; padding:0; margin:0; font-size:.76rem; } .chat-users li { display:flex; align-items:center; gap:.3rem; padding:.18rem .1rem; } .chat-users li::before { content:"👤"; font-size:.72rem; opacity:.9; } + +/* Mobile: stack */ +@media (max-width: 640px){ + .below-row{ flex-direction: column; } + .chat-panel{ width: 100%; min-width: 0; position: static; } + .post-list{ max-height: 46vh; } +} + +/* Guard: never render Sociowall overlay on top of the map */ +.map-overlay-wall{ display:none !important; }