Files
vindn.de/frontend/public/styles.css
T
2026-10-09 16:37:53 +02:00

456 lines
21 KiB
CSS

/* ============================================================
VINDN — Events platform
Design concept: the "board" — every event is treated like an
entry on a departure board (date / time / place rendered in
tabular mono type on a dark strip). It is the one motif that
repeats across hero, listings, search results and detail page,
tying "find an event" to the universal feeling of checking
what's on, right now, near you.
============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap');
:root{
/* ---- color ---- */
--paper: #F7F7F4;
--paper-dim: #EFEFE9;
--ink: #14140F;
--ink-soft: #3C3C34;
--muted: #74746A;
--line: #DEDED5;
--line-strong: #C7C7BC;
--accent: #2440FF;
--accent-deep: #1530CC;
--accent-soft: #E7EAFF;
--warn: #C97A00;
--warn-soft: #FFEFD2;
--board-bg: #14140F;
--board-bg-2: #1D1D16;
--board-text: #F4F3EC;
--board-muted: #9A9A8C;
--board-accent: #6E86FF;
--board-warn: #FFC04D;
/* ---- type ---- */
--f-display: 'Space Grotesk', sans-serif;
--f-body: 'Inter', sans-serif;
--f-mono: 'IBM Plex Mono', monospace;
/* ---- shape / space ---- */
--r-card: 10px;
--r-pill: 999px;
--r-flat: 2px;
--gutter: clamp(20px, 5vw, 64px);
--maxw: 1240px;
}
*{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
body{
margin:0;
background: var(--paper);
color: var(--ink);
font-family: var(--f-body);
font-size: 16px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img,svg{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
ul{ margin:0; padding:0; list-style:none; }
button{ font-family:inherit; cursor:pointer; }
.wrap{ max-width: var(--maxw); margin:0 auto; padding:0 var(--gutter); }
/* focus visibility — accessibility floor */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible{
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 3px;
}
@media (prefers-reduced-motion: reduce){
*{ animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
/* ============ type scale ============ */
h1,h2,h3{ font-family: var(--f-display); font-weight:700; letter-spacing:-0.01em; margin:0; }
.eyebrow{
font-family: var(--f-mono);
font-size: 12px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--muted);
}
.mono{ font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
/* ============ top navigation ============ */
.site-header{
position: sticky; top:0; z-index: 50;
background: rgba(247, 247, 244, 0.85);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border-bottom: 1px solid var(--line);
}
.site-header .wrap{
display:flex; align-items:center; justify-content:space-between;
height: 76px;
}
.brand{ display:flex; align-items:center; gap:10px; }
.brand img{ height: 76px; width:auto; }
.main-nav{ display:flex; align-items:center; gap: 30px; }
.main-nav a{
font-size: 14px; font-weight:600; color: var(--ink-soft);
padding: 8px 2px; position:relative;
}
.main-nav a.is-active{ color: var(--ink); }
.main-nav a.is-active::after{
content:""; position:absolute; left:0; right:0; bottom:-2px; height:2px; background: var(--accent);
}
.nav-search{
display:flex; align-items:center; gap:8px;
border:1px solid var(--line-strong); border-radius: var(--r-pill);
padding: 8px 14px; font-size:13px; color:var(--muted);
min-width: 220px;
}
.nav-search svg{ width:15px; height:15px; flex:none; }
.nav-search:focus-within{ border-color:var(--accent); }
.nav-search button{ background:none; border:none; padding:0; display:flex; color:inherit; flex:none; }
.nav-search input{ border:none; background:none; outline:none; padding:0; font-family:inherit; font-size:13px; color:var(--ink); flex:1; min-width:0; }
.nav-search input::placeholder{ color:var(--muted); }
.nav-cta{
background: var(--ink); color: var(--paper);
font-size: 13px; font-weight:600;
padding: 11px 18px; border-radius: var(--r-pill);
border:none;
}
.nav-actions{ display:flex; align-items:center; gap:16px; }
.lang-switch{ display:flex; align-items:center; gap:2px; font-family:var(--f-mono); font-size:12px; }
.lang-switch a, .lang-switch span{ padding:5px 7px; border-radius:var(--r-pill); color:var(--muted); }
.lang-switch a:hover{ color:var(--ink); }
.lang-switch .is-active{ background:var(--ink); color:var(--paper); }
.nav-burger{ display:none; background:none; border:none; padding:6px; }
.nav-burger span{ display:block; width:22px; height:2px; background:var(--ink); margin:5px 0; transition:transform .2s ease, opacity .2s ease; }
.nav-burger.is-open span:nth-child(1){ transform:translateY(7px) rotate(45deg); }
.nav-burger.is-open span:nth-child(2){ opacity:0; }
.nav-burger.is-open span:nth-child(3){ transform:translateY(-7px) rotate(-45deg); }
.mobile-menu{ display:none; }
/* ============ buttons ============ */
.btn{
display:inline-flex; align-items:center; gap:8px;
font-family: var(--f-body); font-weight:600; font-size:14px;
padding: 13px 22px; border-radius: var(--r-pill); border:1px solid transparent;
transition: transform .15s ease, background .15s ease;
}
.btn-primary{ background: var(--ink); color:var(--paper); }
.btn-primary:hover{ background: var(--accent-deep); }
.btn-ghost{ background: transparent; color:var(--ink); border-color: var(--line-strong); }
.btn-ghost:hover{ border-color: var(--ink); }
.btn-accent{ background: var(--accent); color:#fff; }
.btn-accent:hover{ background: var(--accent-deep); }
.btn:active{ transform: translateY(1px); }
.btn-sm{ padding:9px 16px; font-size:13px; }
/* ============ chips / tags ============ */
.chip-row{ display:flex; flex-wrap:wrap; gap:10px; }
/* collapsible chip-row: CSS-only checkbox toggle, no JS needed */
.chip-row-collapsible{ max-height:100px; overflow:hidden; }
.chip-toggle-checkbox{ position:absolute; opacity:0; pointer-events:none; }
.chip-toggle-checkbox:checked ~ .chip-row-collapsible{ max-height:none; }
.chip-toggle-btn{
display:inline-flex; margin-top:12px; cursor:pointer;
font-family:var(--f-mono); font-size:12px; font-weight:600; color:var(--accent);
}
.chip-toggle-btn:hover{ color:var(--accent-deep); }
.chip-toggle-btn .show-less{ display:none; }
.chip-toggle-checkbox:checked ~ .chip-toggle-btn .show-more{ display:none; }
.chip-toggle-checkbox:checked ~ .chip-toggle-btn .show-less{ display:inline; }
.chip{
font-family: var(--f-mono); font-size: 12px; letter-spacing:.02em;
padding: 7px 14px; border-radius: var(--r-pill);
border:1px solid var(--line-strong); color: var(--ink-soft);
background: var(--paper); white-space:nowrap;
}
.chip.is-active{ background: var(--ink); color: var(--paper); border-color: var(--ink); }
/* ============ pagination (first/prev/current/next/last) ============ */
.pager{ display:flex; justify-content:center; align-items:center; gap:8px; margin-top:36px; flex-wrap:wrap; }
.pager a, .pager span{
padding:9px 16px; border:1px solid var(--line); border-radius:8px;
font-family:var(--f-mono); font-size:13px; white-space:nowrap;
}
.pager a:hover{ border-color:var(--line-strong); }
.pager span.is-active{ background:var(--ink); color:var(--paper); border-color:var(--ink); font-weight:600; }
.tag{
font-family: var(--f-mono); font-size:11px; letter-spacing:.04em; text-transform:uppercase;
padding: 4px 9px; border-radius: var(--r-flat); background: var(--accent-soft); color: var(--accent-deep);
}
.tag.tag-warn{ background: var(--warn-soft); color: var(--warn); }
.tag.tag-dark{ background: var(--ink); color: var(--paper); }
/* ============ category glyph (replaces stock photography) ============
Small abstract line-glyphs per category drawn with currentColor,
set on a soft tinted tile — keeps the system illustrative and
consistent instead of relying on photography. */
.glyph-tile{
display:flex; align-items:center; justify-content:center;
border-radius: var(--r-card);
aspect-ratio: 4/3;
position:relative; overflow:hidden;
}
.glyph-tile svg{ width:34%; height:34%; }
.glyph-tile::after{
content:""; position:absolute; inset:0;
background-image: radial-gradient(circle at 20% 20%, rgba(255,255,255,.5), transparent 45%);
}
.t-music{ background:#E7EAFF; color:#2440FF; }
.t-tech{ background:#E4F3EC; color:#1F8A56; }
.t-community{ background:#FFEFD2; color:#C97A00; }
.t-sports{ background:#FDE3E0; color:#D14B3A; }
.t-arts{ background:#F1E6FB; color:#7A3FC9; }
.t-food{ background:#FFF1DC; color:#B9740B; }
/* ============ departure board — the signature motif ============ */
.board{
background: var(--board-bg);
border-radius: var(--r-card);
color: var(--board-text);
overflow:hidden;
}
.board-head{
display:flex; align-items:center; justify-content:space-between;
padding: 16px 22px; border-bottom:1px solid #2B2B22;
}
.board-head .eyebrow{ color: var(--board-muted); }
.board-clock{ font-family:var(--f-mono); font-size:13px; color: var(--board-accent); }
.board-row{
display:grid;
grid-template-columns: 96px 1fr 140px 90px;
align-items:center;
gap: 18px;
padding: 16px 22px;
border-bottom: 1px solid #232319;
font-family: var(--f-mono);
}
.board-row:last-child{ border-bottom:none; }
.board-row:hover{ background: var(--board-bg-2); }
.board-date{ color: var(--board-accent); font-size:13px; letter-spacing:.03em; }
.board-date .dow{ display:block; color: var(--board-muted); font-size:11px; margin-top:2px; }
.board-name{ font-family: var(--f-body); font-weight:600; font-size:15px; color: var(--board-text); }
.board-name .where{ display:block; font-family:var(--f-mono); font-weight:400; font-size:12px; color: var(--board-muted); margin-top:3px; letter-spacing:.02em; }
.board-status{ font-size:12px; text-align:right; color: var(--board-muted); }
.board-status.is-soon{ color: var(--board-warn); }
.board-status.is-live{ color: #6CE3A0; }
.board-go{ text-align:right; font-size:12px; color: var(--board-accent); }
/* ============ section scaffolding ============ */
.section{ padding: 64px 0; }
.section-head{
display:flex; align-items:flex-end; justify-content:space-between;
gap: 20px; margin-bottom: 28px; flex-wrap:wrap;
}
.section-head h2{ font-size: clamp(24px,3vw,32px); }
.section-link{ font-size:13px; font-weight:600; color:var(--accent); display:flex; gap:6px; align-items:center; }
/* ============ card grid ============ */
.card-grid{ display:grid; grid-template-columns: repeat(3,1fr); gap: 22px; }
.event-card{
border:1px solid var(--line); border-radius: var(--r-card); background:#fff;
overflow:hidden; display:flex; flex-direction:column;
transition: border-color .15s ease, transform .15s ease;
}
.event-card:hover{ border-color: var(--line-strong); transform: translateY(-2px); }
.event-card .body{ padding: 16px 18px 18px; display:flex; flex-direction:column; gap:8px; flex:1; }
.event-card .meta-row{ display:flex; align-items:center; gap:10px; }
.event-card h3{ font-size:16px; font-family: var(--f-body); font-weight:600; line-height:1.3; }
.event-card .when{ font-family: var(--f-mono); font-size:12px; color: var(--muted); }
.event-card .place{ font-size:13px; color: var(--muted); margin-top:auto; }
.event-card .price{ font-family:var(--f-mono); font-weight:600; font-size:13px; }
/* ============ footer ============ */
.site-footer{ border-top:1px solid var(--line); padding: 48px 0 28px; margin-top:40px; }
.footer-grid{ display:grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 32px; }
.footer-grid h4{ font-family:var(--f-mono); font-size:12px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); margin:0 0 14px; }
.footer-grid li{ margin-bottom:10px; font-size:14px; }
.footer-grid li a:hover{ color: var(--accent); }
.footer-bottom{ display:flex; justify-content:space-between; align-items:center; margin-top:40px; padding-top:20px; border-top:1px solid var(--line); font-size:12px; color:var(--muted); font-family:var(--f-mono); }
/* ============ misc utility ============ */
.divider{ height:1px; background:var(--line); border:none; margin: 0; }
.skip-link{ position:absolute; left:-999px; }
.skip-link:focus{ left: 12px; top: 12px; background: var(--ink); color:#fff; padding:8px 14px; border-radius:6px; z-index:100; }
/* ============ responsive ============ */
@media (max-width: 980px){
.card-grid{ grid-template-columns: repeat(2,1fr); }
.footer-grid{ grid-template-columns: 1.4fr 1fr 1fr; }
.board-row{ grid-template-columns: 80px 1fr 76px; }
.board-go{ display:none; }
}
@media (max-width: 760px){
.main-nav, .nav-search{ display:none; }
.nav-burger{ display:block; }
.card-grid{ grid-template-columns: 1fr 1fr; }
.footer-grid{ grid-template-columns: 1fr 1fr; }
.section{ padding: 44px 0; }
.mobile-menu{
display:block;
position:absolute; top:100%; left:0; right:0; z-index:49;
background:var(--paper); border-bottom:1px solid var(--line);
padding:8px 20px 20px;
box-shadow:0 10px 30px rgba(20,20,15,.08);
}
.mobile-menu[hidden]{ display:none; }
.mobile-menu nav{ display:flex; flex-direction:column; }
.mobile-menu nav a{
padding:14px 0; font-size:15px; font-weight:600; color:var(--ink-soft);
border-bottom:1px solid var(--line);
}
.mobile-menu nav a.is-active{ color:var(--ink); }
.mobile-menu .mobile-search{ display:flex; gap:8px; margin-top:14px; }
.mobile-menu .mobile-search input{
flex:1; min-width:0; border:1px solid var(--line-strong); border-radius:var(--r-pill);
padding:10px 14px; font-size:14px; font-family:inherit; color:var(--ink); background:none;
}
.mobile-menu .mobile-search button{
background:var(--ink); color:var(--paper); border:none; border-radius:var(--r-pill);
padding:10px 16px; font-size:13px; font-weight:600;
}
}
@media (max-width: 520px){
.card-grid{ grid-template-columns: 1fr; }
.board-row{ grid-template-columns: 70px 1fr; }
.board-status{ display:none; }
}
/* ============ interactive map stage (home hero + /map) ============ */
.stage{ position:relative; height: calc(100vh - 76px); min-height:520px; }
.stage-compact{ height:560px; min-height:420px; border-radius:var(--r-card); overflow:hidden; box-shadow:0 10px 30px rgba(20,20,15,.08); }
.stage-compact .panel{ width:300px; }
.stage:fullscreen{ height:100vh; border-radius:0; }
.stage:-webkit-full-screen{ height:100vh; border-radius:0; }
#mapCanvas{ position:absolute; inset:0; background: var(--paper-dim); z-index: 10;}
.leaflet-tile-pane, .maplibregl-map{ filter: grayscale(0.85) brightness(1.08) contrast(0.92); }
.leaflet-popup-content-wrapper{ border-radius:10px; box-shadow:0 10px 30px rgba(20,20,15,.18); }
.leaflet-popup-content{ margin:14px 16px; font-family:var(--f-body); }
.leaflet-control-attribution{ font-size:10px; }
.map-overlay-top{
position:absolute; top:5px; left:50px; right:10px; z-index:30;
display:flex; align-items:flex-start; justify-content:space-between; gap:14px; flex-wrap:wrap;
pointer-events:none;
}
.float-card{
background: rgba(247,247,244,0.85);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border:1px solid var(--line); border-radius:14px;
box-shadow: 0 8px 24px rgba(20,20,15,.10);
pointer-events:auto;
}
.search-card{ padding:14px 16px; flex:1; max-width:560px; }
/* the compact card holds just the date row — size it to that, not to 560px */
.stage-compact .search-card{ flex:none; max-width:100%; }
.date-range{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:8px; font-family:var(--f-mono); font-size:11px; color:var(--muted); text-transform:uppercase; letter-spacing:.06em; }
.date-range:first-child{ margin-top:0; }
.date-range input{ padding:5px 8px; border:1px solid var(--line-strong); border-radius:6px; font-family:var(--f-mono); font-size:12px; background:#fff; color:var(--ink); }
.date-range input{ width:112px; }
.date-range .flatpickr-wrapper{ display:inline-block; position:static; }
/* Anchor the popup to the row (Browse) or the whole card (maps) instead of
the input it belongs to — otherwise the "From" calendar, ~308px wide,
starts at the input and runs off the right edge of a phone screen. */
.date-range{ position:relative; }
.search-card{ position:relative; }
.search-card .date-range{ position:static; }
.date-range .flatpickr-calendar.static{ left:0; right:auto; }
.date-range .flatpickr-calendar:before, .date-range .flatpickr-calendar:after{ display:none; }
/* the calendar renders inside .date-range (static), so undo its uppercase mono label styling */
.date-range .flatpickr-calendar{ text-transform:none; letter-spacing:normal; font-family:var(--f-body); font-size:14px; color:var(--ink); }
.flatpickr-day.selected, .flatpickr-day.selected:hover{ background:var(--ink); border-color:var(--ink); }
.flatpickr-day.today:not(.selected){ border-color:var(--accent); }
.date-clear{ background:none; border:none; padding:0 4px; font-family:var(--f-mono); font-size:12px; text-transform:none; letter-spacing:0; color:var(--accent); text-decoration:underline; }
.chip-row-tight{ display:flex; gap:8px; flex-wrap:wrap; max-height:64px; overflow-y:auto; }
.chip-sm{ font-family:var(--f-mono); font-size:11px; padding:6px 12px; border-radius:var(--r-pill); border:1px solid var(--line-strong); background:#fff; color:var(--ink-soft); }
.chip-sm.is-active{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
/* margin-left:auto anchors it to the right within map-overlay-top's flex
row regardless of whether .search-card (hidden in compact mode) precedes
it — space-between alone only works when both cards are present. */
.locate-card{ padding:10px; flex:none; width:220px; margin-left:auto; }
#locationSearchForm{ display:flex; gap:6px; }
#locationSearchForm input{ flex:1; min-width:0; padding:9px 12px; border:1px solid var(--line-strong); border-radius:var(--r-pill); font-size:12px; }
.locate-btn{
display:flex; align-items:center; gap:8px; background:var(--ink); color:var(--paper);
border:none; border-radius:var(--r-pill); padding:11px 16px; font-size:13px; font-weight:600; width:100%;
}
.range-label{
display:flex; align-items:center; gap:8px; margin-top:10px;
font-family:var(--f-mono); font-size:11px; color:var(--muted);
}
.range-label select{
flex:1; padding:6px 10px; border:1px solid var(--line-strong); border-radius:6px;
font-family:var(--f-mono); font-size:12px; background:#fff; color:var(--ink);
}
.locate-status{ font-family:var(--f-mono); font-size:11px; color:var(--muted); margin-top:8px; max-width:200px; }
.locate-status.is-error{ color:var(--warn); font-weight:600; }
.legend{
position:absolute; left:18px; bottom:18px; z-index:30; padding:10px 14px;
display:flex; gap:14px; flex-wrap:wrap; max-width:30vw; flex-direction: column;
}
.legend span{ display:flex; align-items:center; gap:6px; font-family:var(--f-mono); font-size:11px; color:var(--ink-soft); }
.legend .dot{ width:9px; height:9px; border-radius:50%; }
.panel{
position:absolute; top:200px; right:10px; bottom:18px; width:360px; z-index:25;
display:flex; flex-direction:column; overflow:hidden;
}
/* Overrides .board's solid background just for the map's floating events
panel, to match the other map overlay elements — other .board usages
(event cards, home hero board) keep their solid background. */
.panel.board{
background: rgba(20,20,15,0.85);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
.panel-head{ padding:16px 18px; border-bottom:1px solid var(--line); display:flex; justify-content:space-between; align-items:center; }
.panel-head .count{ font-family:var(--f-mono); font-size:12px; color:var(--muted); }
.panel-list{ overflow-y:auto; flex:1; }
.map-row{ display:grid; grid-template-columns: 58px 1fr 22px; gap:12px; align-items:center; padding:13px 18px; border-bottom:1px solid #232319; cursor:pointer; }
.map-row.no-dist{ grid-template-columns: 1fr 22px; }
.map-row:last-child{ border-bottom:none; }
.map-row:hover, .map-row.is-highlighted{ background:var(--board-bg-2); }
.map-row .dist{ font-family:var(--f-mono); font-size:13px; color:var(--board-accent); }
.map-row .dist .u{ display:block; font-size:10px; color:var(--board-muted); }
.map-row .name{ font-family:var(--f-body); font-weight:600; font-size:13.5px; color:var(--board-text); line-height:1.3; }
.map-row .when{ display:block; font-family:var(--f-mono); font-size:11px; color:var(--board-muted); margin-top:3px; }
.map-row .go{ color:var(--board-accent); text-align:right; }
.pin-pop{ min-width:170px; }
.pin-pop .cat{ font-family:var(--f-mono); font-size:10px; text-transform:uppercase; letter-spacing:.05em; }
.pin-pop h4{ font-size:14px; margin:6px 0 4px; font-family:var(--f-body); font-weight:600; }
.pin-pop p{ font-family:var(--f-mono); font-size:11.5px; color:var(--muted); margin:0 0 8px; }
.pin-pop a{ font-size:12px; font-weight:600; color:var(--accent); }
/* reskin markercluster's default green/orange bubbles to the site's ink tone */
/* !important: MarkerCluster.Default.css loads after this file (in each
page's head_extra block), so an equal-specificity override would lose
the tie without it. */
.marker-cluster-small, .marker-cluster-medium, .marker-cluster-large{ background-color: rgba(20,20,15,.18) !important; }
.marker-cluster-small div, .marker-cluster-medium div, .marker-cluster-large div{ background-color: var(--ink) !important; }
.marker-cluster span{ color:#fff !important; font-family:var(--f-mono); font-weight:600; }
@media (max-width: 900px){
.stage{ height:auto; }
.stage-compact{ height:auto; }
#mapCanvas{ position:static; height:calc(100dvh - 76px); }
.panel, .stage-compact .panel{ position:static; width:auto; height:auto; max-height:50vh; margin-top:14px; }
.map-overlay-top{ position:absolute; }
.legend{ display:none; }
}