/* ============================================================================ Collections page — visual language built on the dashboard glass tokens. Imports nothing itself: it relies on the `.trek-dash` design tokens declared in dashboard.css (which the page imports first), so light/dark, glass surfaces, radii and shadows all match the dashboard for free. Only the pieces unique to collections live here — the list rail, the hero, the place cards, the status pills and the mobile rail drawer. ============================================================================ */ /* The page wrapper: dashboard background + font, normal document flow (no fixed shell), cleared below the fixed navbar. */ .trek-dash.col-root { min-height: 100vh; padding-top: var(--nav-h); } /* Sticky left list rail + fluid body. */ .trek-dash .col-page { max-width: min(2100px, 95vw); margin: 0 auto; padding: 30px 44px 110px; display: grid; grid-template-columns: 272px minmax(0, 1fr); gap: 30px; align-items: start; } .trek-dash .col-body { min-width: 0; } /* ----------------- list rail ----------------- */ .trek-dash .col-rail { position: sticky; top: calc(var(--nav-h) + 22px); background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--r-xl); box-shadow: var(--glass-shadow), var(--glass-highlight); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); padding: 12px; display: flex; flex-direction: column; gap: 2px; max-height: calc(100vh - var(--nav-h) - 44px); overflow-y: auto; overscroll-behavior: contain; } .trek-dash .col-rail-new { display: flex; align-items: center; gap: 9px; width: 100%; padding: 10px 12px; margin-bottom: 6px; border-radius: var(--r-sm); border: 1px dashed var(--line-2); color: var(--ink-2); font-size: 13px; font-weight: 500; transition: background .15s, color .15s, border-color .15s; } .trek-dash .col-rail-new:hover { background: var(--surface-2); color: var(--ink); border-color: var(--ink-3); } .trek-dash .col-rail-label { display: flex; align-items: center; gap: 6px; padding: 14px 11px 5px; font-size: 10.5px; text-transform: uppercase; letter-spacing: .13em; color: var(--ink-3); font-weight: 600; } .trek-dash .col-rail-label .badge { margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; display: grid; place-items: center; background: var(--accent); color: #fff; font-size: 10px; letter-spacing: 0; } .trek-dash .col-rail-sep { height: 1px; background: var(--line); margin: 8px 6px; } .trek-dash .col-row { position: relative; } .trek-dash .col-row-btn { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 11px; border-radius: var(--r-sm); text-align: left; color: var(--ink-2); font-size: 13.5px; font-weight: 500; transition: background .12s, color .12s; } .trek-dash .col-row-btn:hover { background: var(--surface-2); color: var(--ink); } .trek-dash .col-row-btn.on { background: var(--surface-2); color: var(--ink); box-shadow: var(--sh-xs); } .trek-dash .col-row-btn .dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } .trek-dash .col-row-btn .ico { color: var(--ink-3); flex-shrink: 0; display: grid; place-items: center; } .trek-dash .col-row-btn.on .ico { color: var(--ink-2); } .trek-dash .col-row-btn .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .trek-dash .col-row-btn .ct { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; flex-shrink: 0; } /* The kebab lives to the right of the count and is always visible (just dimmed) so it is easy to hit — no hover-to-reveal timing. Reserve space for it. */ .trek-dash .col-row:has(.col-row-menu) .col-row-btn { padding-right: 34px; } .trek-dash .col-row-menu { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center; color: var(--ink-3); opacity: .5; transition: opacity .12s, background .12s, color .12s; } .trek-dash .col-row:hover .col-row-menu, .trek-dash .col-row-menu:hover { opacity: 1; } .trek-dash .col-row-menu:hover, .trek-dash .col-row.menu-open .col-row-menu { background: var(--bg-2); color: var(--ink); opacity: 1; } /* rename inline input */ .trek-dash .col-row-edit { width: 100%; padding: 8px 11px; border-radius: var(--r-sm); border: 1px solid var(--accent); background: var(--surface); color: var(--ink); font-size: 13.5px; font-weight: 500; outline: none; } /* The list row's kebab menu / colour picker is a Tailwind-styled popover portalled to document.body (see ListsRail), so nothing here — keeping it in the rail would let the rail's overflow + backdrop-filter clip it. */ /* incoming-invite card */ .trek-dash .col-invite { padding: 11px; border-radius: var(--r-sm); background: var(--surface-2); margin: 2px 0; } .trek-dash .col-invite .t { font-size: 12.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .trek-dash .col-invite .s { font-size: 11px; color: var(--ink-3); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .trek-dash .col-invite-actions { display: flex; gap: 7px; margin-top: 9px; } .trek-dash .col-invite-actions button { flex: 1; padding: 6px 8px; border-radius: 8px; font-size: 11.5px; font-weight: 600; transition: background .12s, opacity .12s; } .trek-dash .col-invite-accept { background: var(--accent); color: #fff; } .trek-dash .col-invite-accept:hover { opacity: .9; } .trek-dash .col-invite-decline { border: 1px solid var(--line-2); color: var(--ink-2); } .trek-dash .col-invite-decline:hover { background: var(--surface); } /* ----------------- hero ----------------- */ .trek-dash .col-hero { position: relative; isolation: isolate; overflow: hidden; display: flex; border-radius: var(--r-2xl); box-shadow: var(--sh-lg); min-height: 148px; margin-bottom: 22px; } .trek-dash .col-hero-bg { position: absolute; inset: 0; z-index: 0; background: radial-gradient(135% 130% at 10% 6%, color-mix(in oklch, var(--hero-color, var(--accent)) 55%, white) 0%, transparent 50%), linear-gradient(135deg, var(--hero-color, var(--accent)) 0%, color-mix(in oklch, var(--hero-color, var(--accent)) 60%, black 40%) 100%); } .trek-dash .col-hero-img { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; } .trek-dash .col-hero-scrim { position: absolute; inset: 0; z-index: 1; background: linear-gradient(180deg, rgba(0,0,0,.20) 0%, rgba(0,0,0,0) 42%, rgba(0,0,0,.52) 100%), linear-gradient(90deg, rgba(0,0,0,.30) 0%, rgba(0,0,0,0) 62%); } .trek-dash .col-hero-content { position: relative; z-index: 2; width: 100%; padding: 18px 28px 20px; display: flex; flex-direction: column; justify-content: flex-end; gap: 9px; color: #fff; } .trek-dash .col-hero-titlerow { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; } .trek-dash .col-hero-actions { display: flex; gap: 8px; flex-shrink: 0; align-items: center; margin-bottom: 3px; } .trek-dash .col-glass-btn { display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 15px; border-radius: 999px; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.24); color: #fff; font-size: 13px; font-weight: 600; letter-spacing: -.005em; backdrop-filter: blur(14px) saturate(1.4); -webkit-backdrop-filter: blur(14px) saturate(1.4); transition: background .15s, transform .12s; } .trek-dash .col-glass-btn:hover { background: rgba(255,255,255,.28); transform: translateY(-1px); } .trek-dash .col-glass-btn.icon { width: 38px; padding: 0; justify-content: center; } .trek-dash .col-glass-btn .cnt { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; display: grid; place-items: center; background: rgba(255,255,255,.28); font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums; } .trek-dash .col-hero-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 9px; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; font-weight: 600; opacity: .94; } .trek-dash .col-hero-eyebrow .members { display: inline-flex; align-items: center; margin-left: 2px; } .trek-dash .col-hero-title { font-size: 40px; font-weight: 600; letter-spacing: -.03em; line-height: 1.02; margin: 0; text-shadow: 0 1px 12px rgba(0,0,0,.3), 0 1px 3px rgba(0,0,0,.35); overflow-wrap: anywhere; } /* A light wash of the list colour laid over the cover photo. */ .trek-dash .col-hero-tint { position: absolute; inset: 0; z-index: 0; background: linear-gradient(135deg, color-mix(in oklch, var(--hero-color, var(--accent)) 52%, transparent) 0%, transparent 62%), color-mix(in oklch, var(--hero-color, var(--accent)) 14%, transparent); } .trek-dash .col-hero-desc { font-size: 13.5px; line-height: 1.42; color: rgba(255,255,255,.92); max-width: 620px; margin: -2px 0 2px; text-shadow: 0 1px 4px rgba(0,0,0,.4); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .trek-dash .col-hero-links { display: inline-flex; flex-wrap: wrap; gap: 6px; margin-left: 4px; text-transform: none; letter-spacing: normal; } .trek-dash .col-hero-link { display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px; border-radius: 999px; font-size: 12px; font-weight: 500; color: #fff; max-width: 220px; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.24); backdrop-filter: blur(10px) saturate(1.4); -webkit-backdrop-filter: blur(10px) saturate(1.4); transition: background .14s, transform .12s; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .trek-dash .col-hero-link:hover { background: rgba(255,255,255,.28); transform: translateY(-1px); } .trek-dash .col-hero-stats { display: flex; flex-wrap: wrap; gap: 8px; } .trek-dash .col-chip { display: inline-flex; align-items: center; gap: 7px; padding: 8px 13px; border-radius: 999px; background: rgba(255,255,255,.15); border: 1px solid rgba(255,255,255,.22); color: #fff; font-size: 12.5px; font-weight: 500; letter-spacing: -.005em; cursor: pointer; backdrop-filter: blur(12px) saturate(1.4); -webkit-backdrop-filter: blur(12px) saturate(1.4); transition: background .14s, border-color .14s, transform .12s; } .trek-dash .col-chip:hover { background: rgba(255,255,255,.24); transform: translateY(-1px); } .trek-dash .col-chip.on { background: #fff; color: oklch(0.28 0.02 260); border-color: #fff; } .trek-dash .col-chip .sw { width: 8px; height: 8px; border-radius: 50%; } .trek-dash .col-chip .n { font-weight: 700; font-variant-numeric: tabular-nums; } /* member avatar stack in the eyebrow */ .trek-dash .col-av { width: 24px; height: 24px; border-radius: 50%; margin-left: -7px; object-fit: cover; border: 2px solid rgba(255,255,255,.85); display: grid; place-items: center; font-size: 10px; font-weight: 700; color: #fff; } .trek-dash .col-av:first-child { margin-left: 0; } /* ----------------- toolbar ----------------- */ .trek-dash .col-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; } .trek-dash .col-toolbar-spacer { flex: 1; } .trek-dash .col-search { position: relative; } .trek-dash .col-search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ink-3); pointer-events: none; } .trek-dash .col-search input { height: 38px; width: 210px; padding: 0 14px 0 35px; border-radius: var(--r-sm); border: 1px solid var(--line-2); background: var(--surface); color: var(--ink); font-size: 13.5px; font-family: inherit; outline: none; transition: border-color .15s, box-shadow .15s; } .trek-dash .col-search input::placeholder { color: var(--ink-3); } .trek-dash .col-search input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 22%, transparent); } /* icon toggle button + segmented view switch reuse dashboard .seg for the group */ .trek-dash .col-iconbtn { height: 38px; width: 38px; border-radius: var(--r-sm); display: grid; place-items: center; border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2); transition: background .12s, color .12s, border-color .12s; } .trek-dash .col-iconbtn:hover { background: var(--surface-2); color: var(--ink); } .trek-dash .col-iconbtn.on { background: var(--accent); border-color: var(--accent); color: #fff; } .trek-dash .col-viewseg { display: flex; padding: 3px; border-radius: var(--r-sm); background: oklch(0.94 0.008 70); } .dark .trek-dash .col-viewseg { background: var(--bg-2); } .trek-dash .col-viewseg button { width: 34px; height: 32px; border-radius: 8px; display: grid; place-items: center; color: var(--ink-2); transition: background .12s, color .12s; } .trek-dash .col-viewseg button.on { background: var(--surface); color: var(--ink); box-shadow: var(--sh-xs); } /* select-mode action bar */ .trek-dash .col-selbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; padding: 10px 14px; border-radius: var(--r-md); background: var(--glass-bg); border: 1px solid var(--glass-border); box-shadow: var(--sh-sm); } .trek-dash .col-selbar .lbl { font-size: 13px; font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .trek-dash .col-selbar-btn { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 9px; font-size: 12.5px; font-weight: 600; color: var(--ink-2); transition: background .12s, color .12s; } .trek-dash .col-selbar-btn:hover { background: var(--surface-2); color: var(--ink); } .trek-dash .col-selbar-btn.danger { color: oklch(0.6 0.2 25); } .trek-dash .col-selbar-btn.danger:hover { background: oklch(0.6 0.2 25 / .12); } /* ----------------- map panel + floating controls ----------------- */ .trek-dash .col-map-shell { position: relative; width: 100%; height: 100%; } /* One top bar so the left cluster (collapse / select) and the right cluster (add / search) share the width and never overlap on a narrow split map — the search shrinks instead. */ /* The bar itself is click-through; only the control groups catch clicks, so the empty space between them never swallows a map/marker click. */ .trek-dash .col-map-topbar { position: absolute; top: 12px; left: 12px; right: 12px; z-index: 20; display: flex; align-items: center; gap: 10px; pointer-events: none; } .trek-dash .col-map-group { display: flex; align-items: center; gap: 8px; pointer-events: auto; } .trek-dash .col-map-group.right { margin-left: auto; min-width: 0; } .trek-dash .col-map-btn { width: 38px; height: 38px; flex-shrink: 0; border-radius: 11px; display: grid; place-items: center; color: var(--ink); background: color-mix(in oklch, var(--surface) 92%, transparent); border: 1px solid var(--glass-border); box-shadow: var(--sh-md); backdrop-filter: blur(8px) saturate(1.2); -webkit-backdrop-filter: blur(8px) saturate(1.2); transition: transform .12s, background .15s, color .15s; } .trek-dash .col-map-btn:hover { transform: translateY(-1px); background: var(--surface); } .trek-dash .col-map-btn.on { background: var(--accent); border-color: var(--accent); color: #fff; } .trek-dash .col-map-btn:disabled { opacity: .45; cursor: default; transform: none; } .trek-dash .col-map-search { display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 12px; border-radius: 11px; color: var(--ink-3); background: color-mix(in oklch, var(--surface) 92%, transparent); border: 1px solid var(--glass-border); box-shadow: var(--sh-md); backdrop-filter: blur(8px) saturate(1.2); -webkit-backdrop-filter: blur(8px) saturate(1.2); flex: 0 1 auto; min-width: 0; } .trek-dash .col-map-search svg { flex-shrink: 0; } .trek-dash .col-map-search input { flex: 1 1 auto; width: 150px; min-width: 0; background: none; border: 0; outline: none; color: var(--ink); font-size: 13.5px; font-family: inherit; } .trek-dash .col-map-search input::placeholder { color: var(--ink-3); } /* ----------------- list view ----------------- */ .trek-dash .col-listview { display: flex; flex-direction: column; gap: 7px; } .trek-dash .col-lrow { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 10px 14px; border-radius: var(--r-md); background: var(--glass-bg); border: 1px solid var(--glass-border); box-shadow: var(--sh-xs); cursor: pointer; transition: transform .12s, box-shadow .15s, border-color .15s; } /* Keep a picked row above the docked detail sheet (which covers the lower ~62vh). */ .trek-dash .col-lrow { scroll-margin: calc(var(--nav-h) + 90px) 0 62vh; } .trek-dash .col-lrow:hover { transform: translateX(3px); box-shadow: var(--sh-sm); } /* Inset ring so the highlight is never clipped by the column's overflow. */ .trek-dash .col-lrow.sel { border-color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); } .trek-dash .col-lrow .li { min-width: 0; } .trek-dash .col-lrow .li .t { font-size: 14px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .trek-dash .col-lrow .li .s { font-size: 12px; color: var(--ink-3); margin-top: 2px; display: flex; align-items: center; gap: 5px; overflow: hidden; } .trek-dash .col-lrow .li .s span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* The pin before the address must not be squeezed by a long address. */ .trek-dash .col-lrow .li .s svg { flex-shrink: 0; } .trek-dash .col-lrow-end { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } .trek-dash .col-lrow-cat { display: inline-flex; align-items: center; gap: 5px; max-width: 130px; padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 600; white-space: nowrap; overflow: hidden; color: var(--cat, var(--accent)); background: color-mix(in oklch, var(--cat, var(--accent)) 14%, transparent); } .trek-dash .col-lrow-cat svg { flex-shrink: 0; } .trek-dash .col-lrow-div { width: 1px; height: 18px; flex-shrink: 0; background: var(--line-2); } /* ----------------- filter bar (status + category dropdowns) ----------------- */ .trek-dash .col-filterbar { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; } .trek-dash .col-filter { position: relative; } .trek-dash .col-filter-select { margin-left: auto; } .trek-dash .col-filter-select.open { background: var(--accent); border-color: var(--accent); color: #fff; } .trek-dash .col-filter-select.open:hover { background: var(--accent); color: #fff; } .trek-dash .col-filter-btn { display: inline-flex; align-items: center; gap: 7px; padding: 7px 11px; border-radius: 10px; font-size: 12.5px; font-weight: 600; color: var(--ink-2); background: var(--surface); border: 1px solid var(--line-2); transition: background .12s, border-color .12s, color .12s; } .trek-dash .col-filter-btn:hover { background: var(--surface-2); color: var(--ink); } .trek-dash .col-filter-btn.open { border-color: var(--accent); color: var(--ink); } .trek-dash .col-filter-btn .col-filter-chev { color: var(--ink-3); transition: transform .15s; } .trek-dash .col-filter-btn.open .col-filter-chev { transform: rotate(180deg); } .trek-dash .col-filter-lbl { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 140px; } .trek-dash .col-filter-pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40; min-width: 190px; max-height: 320px; overflow-y: auto; padding: 6px; border-radius: 12px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-lg); display: flex; flex-direction: column; gap: 2px; } .trek-dash .col-filter-opt { display: flex; align-items: center; gap: 9px; width: 100%; padding: 7px 9px; border-radius: 8px; font-size: 13px; color: var(--ink-2); text-align: left; transition: background .12s; } .trek-dash .col-filter-opt:hover { background: var(--surface-2); } .trek-dash .col-filter-opt.on { color: var(--ink); font-weight: 600; } .trek-dash .col-filter-opt .col-filter-lbl { flex: 1; max-width: none; } .trek-dash .col-filter-count { font-size: 11px; font-weight: 600; color: var(--ink-3); font-variant-numeric: tabular-nums; } .trek-dash .col-filter-check { color: var(--accent); flex-shrink: 0; } .trek-dash .col-filter-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } .trek-dash .col-filter-dot.ghost { background: var(--line-2); } .trek-dash .col-lcheck { width: 22px; height: 22px; border-radius: 7px; display: grid; place-items: center; background: var(--surface-2); border: 1px solid var(--line-2); color: transparent; flex-shrink: 0; } .trek-dash .col-lcheck.on { background: var(--accent); border-color: var(--accent); color: #fff; } /* map view fills the body */ .trek-dash .col-mapwrap { border-radius: var(--r-xl); overflow: hidden; border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow); height: calc(100vh - var(--nav-h) - 320px); min-height: 380px; } /* list + map split (list view on wide screens): scrollable list left, sticky map right. Clicking a place pans the map (selectedPlaceId drives it). Only rendered above 1024px (the page gates it in JS). The columns animate between the split and the collapsed-list "map full" state; the map stays mounted so the grow/shrink is smooth (the page nudges it to re-layout during the anim). */ .trek-dash .col-split { display: grid; grid-template-columns: 1fr 1.05fr; gap: 20px; align-items: start; transition: grid-template-columns .4s cubic-bezier(.2,.7,.2,1), gap .4s cubic-bezier(.2,.7,.2,1); } .trek-dash .col-split.map-full { grid-template-columns: 0fr 1fr; gap: 0; } .trek-dash .col-split-list { min-width: 0; overflow: visible; transition: opacity .25s; } /* Clip only while the column collapses under the full-map view. */ .trek-dash .col-split.map-full .col-split-list { opacity: 0; pointer-events: none; overflow: hidden; } .trek-dash .col-split-map { position: sticky; top: calc(var(--nav-h) + 22px); height: calc(100vh - var(--nav-h) - 210px); min-height: 440px; border-radius: var(--r-xl); overflow: hidden; border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow); } /* The status pill itself (idea/want/visited) is the StatusBadge component, styled with utility classes so it also works outside .trek-dash (the place inspector). It is a role=button span, not a