Something went wrong. Try again.
Central platform for European atproto.<cc> country community websites atproto.eu
community atproto
Something went wrong. Try again.
CSS
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727@import "tailwindcss";
/* * atproto.nl design system (v1). Gruvbox on cream, light-first. * Tokens from the design system doc (section 12). Poppins/--logo dropped: * the avatar is a static exported PNG, so the logo glyph isn't needed in CSS. */:root { --mono: 'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace; --sans: 'Atkinson Hyperlegible Next Variable', 'Atkinson Hyperlegible Next', system-ui, sans-serif;
/* colour — light (default) */ --paper: #fbf1c7; --surface: #f9f5d7; --terminal: #ebdbb2; --ink: #3c3836; --inkstrong: #282828; --brand: #076678; --brandfield: #458588; /* Accent = the orange pack's LIGHT roles: the fallback before Base.astro sets data-accent, which country-packs.css (generated from src/config/accents.ts) then overrides per scope. Keep these equal to accents.ts ACCENT_PACKS.orange.light — check:brand does not regenerate this file. */ --accent: #d65d0e; /* UI accent: numbers, links, controls (data-ui overrides per scope) */ --accent-fill: #af3a03; /* filled accent control */ --accent-text: #af3a03; /* accent type under 18px */ --wm-accent: #d65d0e; /* wordmark slash 1 = the country's true primary (data-accent overrides) */ --accent-2: #d65d0e; /* wordmark 2nd slash (default = single-colour); orange pack light accent */ --on-brand: #fbf1c7; --on-accent: #fbf1c7; --alert: #9d0006; --ok: #427b58; --muted: #665c54; --rule: #e3d7ac;
/* space (multiples of 4) */ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-11: 44px; --space-14: 56px; --space-22: 88px;
/* shape */ --radius-control: 6px; --radius-surface: 8px; --radius-pill: 999px; --hairline: 1px; --target-min: 44px;
color-scheme: light;}
/* dark tokens — explicit pin via data-theme="dark" */[data-theme='dark'] { --paper: #282828; --surface: #32302f; --terminal: #1d2021; --ink: #ebdbb2; --inkstrong: #fbf1c7; --brand: #83a598; --brandfield: #458588; --accent: #fe8019; --accent-fill: #fe8019; --accent-text: #fe8019; --accent-2: #fe8019; --on-brand: #282828; --on-accent: #282828; --alert: #fb4934; --ok: #8ec07c; --muted: #a89984; --rule: #504945; color-scheme: dark;}/* system default when the user hasn't pinned a theme (works without JS) */@media (prefers-color-scheme: dark) { :root:not([data-theme='light']) { --paper: #282828; --surface: #32302f; --terminal: #1d2021; --ink: #ebdbb2; --inkstrong: #fbf1c7; --brand: #83a598; --brandfield: #458588; --accent: #fe8019; --accent-fill: #fe8019; --accent-text: #fe8019; --accent-2: #fe8019; --on-brand: #282828; --on-accent: #282828; --alert: #fb4934; --ok: #8ec07c; --muted: #a89984; --rule: #504945; color-scheme: dark; }}
* { box-sizing: border-box; }
/* Deliberately no root font-size rule: 1rem stays whatever the reader set in their browser (16px by default). Overriding it here would defeat the point of using rem. */html { scroll-padding-top: 5rem;}
body { margin: 0; min-height: 100dvh; overflow-x: clip; /* guard against stray horizontal overflow (keeps sticky working) */ background: var(--paper); color: var(--ink); font-family: var(--sans); font-size: 1.0625rem; line-height: 1.65; transition: background 0.18s linear;}
a { color: var(--brand); text-decoration: underline; text-underline-offset: 3px; }/* The `hidden` attribute must win over any element's own display (e.g. .btn is inline-flex), else JS-toggled hidden buttons stay visible. */[hidden] { display: none !important; }a:hover { color: var(--accent); }
:where(a, button, [tabindex], input, summary):focus-visible { outline: 3px solid var(--brandfield); outline-offset: 3px; border-radius: 2px;}main:focus { outline: none; }
/* Skip link: off-screen until keyboard-focused. */.skip-link { position: fixed; top: 12px; left: 12px; z-index: 100; padding: 8px 14px; background: var(--surface); color: var(--ink); border: 1px solid var(--brand); border-radius: var(--radius-control); font-family: var(--mono); font-size: 0.9375rem; text-decoration: none; transform: translateY(-200%);}.skip-link:focus { transform: translateY(0); }
h1, h2, h3 { font-family: var(--mono); color: var(--inkstrong); margin: 0; }
/* --- layout: one column, one breakpoint at 720 --- */.wrap { max-width: 1180px; margin-inline: auto; padding-inline: 60px; }main { display: block; }@media (max-width: 720px) { .wrap { padding-inline: 24px; } }
/* --- shared type roles --- */.label { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted);}.display { font-family: var(--mono); font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--inkstrong);}
/* --- wordmark: //atproto.nl , two-colour on the slashes only; letters + dot in ink --- */.wordmark { font-family: var(--mono); font-weight: 700; letter-spacing: -0.03em; color: var(--inkstrong); line-height: 1; white-space: nowrap; }/* Two-colour lockup: slash 1 = primary accent, slash 2 = secondary. The dot is NOT accent — it stays ink (inkstrong), so the only colour is the two slashes. --accent-2 falls back to --accent, so single-colour countries (both packs equal) and any context without it still work. */.wordmark .s1 { color: var(--wm-accent, var(--accent)); }/* Minimal gap between the two slashes: at zero spacing the thin parallel slashes physically merge into one shape, so the two colours only read as distinct with a hair of separation. */.wordmark .s2 { color: var(--accent-2, var(--accent)); margin-left: 0.05em; }.wordmark a, a .wordmark { text-decoration: none; color: inherit; }/* Sibling wordmarks that point elsewhere (the atproto.eu network row, and the footer "part of //atproto.eu" affiliation mark on every subsite) de-emphasise their LETTERS to --muted so the flag-coloured slashes lead and the name reads as a quiet reference, not a heading. The two slashes keep their accent colours (set on .s1/.s2 above); --muted stays AA-legible on both themes. Placed after .wordmark so it wins on the shared element (equal specificity, later rule). */.network-mark, .footer-affil-mark { color: var(--muted); }/* Navbar wordmark is the sole logo now: bigger, neutral-bright letters (not the brand teal), no link underline, home link preserved. Accent slashes/dot stay. */.site-mark { font-size: 1.5rem; }.site-header .bar > a { text-decoration: none; }.site-header a .site-mark { color: var(--inkstrong); }[data-theme='dark'] .site-header a .site-mark { color: #ffffff; }@media (prefers-color-scheme: dark) { :root:not([data-theme='light']) .site-header a .site-mark { color: #ffffff; }}
/* --- header / nav --- */.site-header { background: var(--surface); border-bottom: 1px solid var(--rule); position: sticky; top: 0; z-index: 50; }.site-header .bar { display: flex; align-items: center; justify-content: space-between; min-height: 72px; gap: var(--space-4); flex-wrap: nowrap; }/* Tight gap so the widest localization (the .be nav in French, with a third language link) still fits inline on desktop instead of collapsing to the hamburger. */.nav { display: flex; align-items: center; gap: var(--space-3); }.nav-link { position: relative; font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.13em; text-transform: uppercase; text-decoration: none; color: var(--ink); white-space: nowrap; }.nav-link:hover { color: var(--brand); }/* Grows the tappable area to 24px without changing where the text sits. */.nav-link::after { content: ''; position: absolute; inset: -8px -6px; }/* Language switcher: a globe-icon disclosure (<details>) instead of the old inline endonym list, so a third locale (e.g. .be EN/NL/FR) no longer widens the bar. Absolute dropdown on desktop; the menu expands in-flow inside the mobile/collapsed hamburger overlay (see the collapse rules below) so it never covers the sign-in / theme controls stacked under it. */.lang { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.13em; color: var(--muted); white-space: nowrap; position: relative; }.lang > summary { display: inline-flex; align-items: center; gap: 4px; list-style: none; cursor: pointer; color: var(--muted); min-height: 42px; padding: 0 2px; user-select: none;}.lang > summary::-webkit-details-marker { display: none; }.lang > summary::marker { content: ''; }.lang > summary:hover { color: var(--brand); }.lang > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: var(--radius-control); }.lang-globe { display: block; }.lang-caret { width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid currentColor; transition: transform 0.15s ease;}.lang[open] > summary .lang-caret { transform: rotate(180deg); }.lang-menu { position: absolute; top: 100%; right: 0; z-index: 60; margin: 6px 0 0; padding: 6px; list-style: none; min-width: 10rem; display: flex; flex-direction: column; gap: 2px; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-control); box-shadow: 0 8px 24px rgb(0 0 0 / 0.12);}.lang-menu a { display: block; padding: 8px 12px; border-radius: 6px; text-decoration: none; color: var(--ink); white-space: nowrap;}.lang-menu a:hover { background: color-mix(in oklab, var(--brand) 12%, transparent); color: var(--brand); }.lang-menu a[aria-current='true'] { color: var(--brand); font-weight: 700; }/* Hamburger — hidden on wide screens, shown once the full nav no longer fits. */.nav-toggle { display: none; width: 42px; height: 42px; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 0; background: transparent; border: 1px solid var(--rule); border-radius: var(--radius-control); cursor: pointer; }.nav-toggle-bar { display: block; width: 18px; height: 2px; background: var(--ink); border-radius: 2px; }.nav-toggle:hover { border-color: var(--brand); }.nav-toggle:hover .nav-toggle-bar { background: var(--brand); }/* Collapsed nav. JS (fitNav in Base.astro) adds `.is-collapsed` whenever the inline nav would overflow the bar, so it adapts to the viewport AND the auth-widget width (which grows when signed in). The 720px media query pre-collapses on phones (covers the pre-JS frame + no-JS). Both use the same overlay-dropdown styling. */.site-header.is-collapsed .bar { min-height: 60px; }.site-header.is-collapsed .nav-toggle { display: inline-flex; }.site-header.is-collapsed .nav { /* Open menu is an overlay dropdown, so it does not resize the bar (no upward shift). */ display: none; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; align-items: flex-start; gap: var(--space-4); background: var(--surface); border-bottom: 1px solid var(--rule); padding: var(--space-5) 24px var(--space-6);}.site-header.is-collapsed.open .nav { display: flex; }.site-header.is-collapsed .nav-link, .site-header.is-collapsed .lang { font-size: 1rem; letter-spacing: 0.14em; }/* In the hamburger overlay the switcher menu expands in-flow (not an absolute overlay), so it pushes the sign-in / theme controls down instead of covering them. */.site-header.is-collapsed .lang-menu { position: static; margin: 4px 0 0; padding: 4px 0 0; min-width: 0; background: transparent; border: none; box-shadow: none;}.site-header.is-collapsed .lang > summary { padding-inline: 0; }@media (max-width: 720px) { .site-header .bar { min-height: 60px; } .site-header .nav-toggle { display: inline-flex; } .site-header .nav { display: none; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; align-items: flex-start; gap: var(--space-4); background: var(--surface); border-bottom: 1px solid var(--rule); padding: var(--space-5) 24px var(--space-6); } .site-header.open .nav { display: flex; } /* Header-scoped: unscoped, this also hit the footer nav. */ .site-header .nav-link, .site-header .lang { font-size: 1rem; letter-spacing: 0.14em; } .site-header .lang-menu { position: static; margin: 4px 0 0; padding: 4px 0 0; min-width: 0; background: transparent; border: none; box-shadow: none; } .site-header .lang > summary { padding-inline: 0; }}
/* --- buttons (mono caps, 6px, 44px min) --- */.btn { font-family: var(--mono); font-weight: 500; font-size: 0.9375rem; letter-spacing: 0.18em; text-transform: uppercase; min-height: var(--target-min); padding: 0 22px; border-radius: var(--radius-control); border: 1px solid var(--brand); background: var(--brand); color: var(--on-brand); cursor: pointer; display: inline-flex; align-items: center; text-decoration: none;}.btn:hover { filter: brightness(1.12); color: var(--on-brand); }.btn.ghost { background: transparent; border-color: var(--ink); color: var(--ink); }.btn.ghost:hover { filter: none; border-color: var(--brand); color: var(--brand); }
/* --- cards / chips / terminal --- */.card { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); padding: var(--space-6); }.card.next { border: 2px solid var(--accent); }.chip { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink); border: 1px solid var(--rule); border-radius: var(--radius-pill); padding: 6px 12px; }.terminal { background: var(--terminal); border-radius: var(--radius-surface); padding: var(--space-6) var(--space-8); font-family: var(--mono); font-size: 1.0625rem; line-height: 1.7; color: var(--ink); overflow-x: auto; }
/* --- sections --- */.hero { padding: var(--space-22) 0 var(--space-14); }/* Homepage hero statement (replaces the big wordmark). */.hero-lead { font-family: var(--sans); font-weight: 600; font-size: clamp(1.75rem, 5vw, 2.875rem); line-height: 1.15; letter-spacing: -0.01em; text-transform: none; color: var(--inkstrong); margin: 0; }.page-title { font-size: clamp(1.75rem, 4vw, 2.25rem); line-height: 1.2; }.hero .page-title { font-size: clamp(2.375rem, 6vw, 3.5rem); margin-bottom: var(--space-4); }.hero p { font-size: 1.1875rem; line-height: 1.5; max-width: 34em; margin: 0; }.hero p + p { margin-top: var(--space-3); }.section { padding: var(--space-22) 0; border-top: 1px solid var(--rule); }.section > h2 { font-size: 2.5rem; text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: var(--space-6); }.section > .label { display: block; margin-bottom: var(--space-4); }@media (max-width: 720px) { .section > h2 { font-size: 1.75rem; } .hero { padding: var(--space-14) 0 var(--space-8); } .section { padding: var(--space-14) 0; } .stat-num { font-size: 2.5rem; }}
/* --- members --- */.member-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-5); }/* Members info cards (become a member / find builders) */.members-info { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }@media (max-width: 720px) { .members-info { grid-template-columns: 1fr; } }.info-card { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); padding: var(--space-6); display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); }.info-card h2 { font-size: 1.375rem; margin: 0; }.info-card p { margin: 0; font-size: 0.9375rem; line-height: 1.6; }.info-card .btn { margin-top: auto; }.membership-status { font-weight: 600; color: var(--ok); }/* Builders directory */.builder-howto { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); padding: var(--space-6); max-width: 36em; }.builder-howto h2 { font-size: 1.375rem; margin: 0 0 var(--space-2); }.builder-howto p { margin: 0; font-size: 0.9375rem; line-height: 1.6; }.builder-headline { font-size: 0.9375rem; line-height: 1.5; color: var(--ink); margin: 8px 0 0; }.builder-open { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 var(--space-2); }.open-tag { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.06em; color: var(--on-brand); background: var(--brand); border-radius: var(--radius-pill); padding: 2px 9px; white-space: nowrap; }.member-card { display: flex; align-items: stretch; gap: var(--space-3); background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); padding: var(--space-6); overflow: hidden; }.member-body { min-width: 0; display: flex; flex-direction: column; }/* prose wraps anywhere; identifier tokens (handles) truncate with an ellipsis instead */.member-name, .member-bio, .post-text, .quote-text, .ext-title, .ext-desc { overflow-wrap: anywhere; }.member-handle { display: block; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }/* Pin the Sifa/Bluesky links to the bottom so they align across a row of cards. */.member-links { display: flex; gap: var(--space-4); margin-top: auto; padding-top: var(--space-4); }.apps-label { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin: var(--space-3) 0 6px; }.member-apps { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--space-3); }.apps-label + .member-apps { margin-top: 0; }.app-chip { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--rule); border-radius: var(--radius-pill); padding: 3px 8px; }.member-avatar, .post-avatar { border-radius: 50%; object-fit: cover; flex: none; aspect-ratio: 1 / 1; }.member-avatar { width: 48px; height: 48px; }.post-avatar { width: 32px; height: 32px; }.member-name, .post-name { font-family: var(--mono); font-weight: 700; letter-spacing: -0.01em; color: var(--inkstrong); }.member-handle, .post-handle { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; color: var(--muted); }.member-bio { font-size: 0.9375rem; line-height: 1.65; margin: var(--space-2) 0; white-space: pre-line; }.member-role { font-size: 0.9375rem; line-height: 1.5; color: var(--ink); margin: var(--space-2) 0 0; }.member-loc { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; color: var(--muted); margin: 4px 0 var(--space-2); }
/* --- stats (homepage) --- *//* Members section: the locality map is a full-height background of the section, with the heading, stats, member strip and CTA overlaid on top of it. The text column sits over the emptier (sea) left side of the map; the landmass falls to the right. */.members-section { position: relative; overflow: hidden; isolation: isolate; /* keep the map's z-index local to this section */ min-height: min(72vh, 620px); display: flex; align-items: center;}/* The map iframe, absolutely filling the section behind the text. Override the default 3/2 aspect-ratio from LocalityMap so it stretches to the section box. */.members-section > iframe.members-bg { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; opacity: 0.6; z-index: 0; pointer-events: none; /* Match the page so any sub-pixel edge blends in. Together with fit="cover" (the map fills the frame, no letterbox) this stops browsers that paint a default iframe background from showing grey bars above/below the map. */ background: var(--paper);}/* Scrim: paper on the left (where the text sits) fading to clear on the right (where the landmass falls), so the copy stays legible without hiding the map. */.members-section::before { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient( 90deg, var(--paper) 0%, color-mix(in oklab, var(--paper) 55%, transparent) 42%, transparent 66% );}.members-overlay { position: relative; z-index: 2; max-width: 40em;}/* h2 is no longer a direct child of .section, so restore the section-heading treatment. */.members-overlay > h2 { font-size: 2.5rem; text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 0;}.members-overlay > .stats { margin-top: var(--space-6); }.members-overlay > .member-strip { margin-top: var(--space-6); }.members-overlay > .join-cta { margin-top: var(--space-6); }
/* Member avatar strip (under the stats): overlapping circles + caption, links to /members. */.member-strip { display: block; text-decoration: none; color: inherit; max-width: 36em; }/* Single line: never wrap. Show as many avatars as the row width holds and clip the rest, with a soft right-edge fade so the cut-off reads as intentional ("and more"). */.avatar-row { display: flex; flex-wrap: nowrap; align-items: center; overflow: hidden; padding-block: 2px; -webkit-mask-image: linear-gradient(to right, #000 86%, transparent); mask-image: linear-gradient(to right, #000 86%, transparent);}.avatar-dot { flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%; object-fit: cover; border: 2px solid var(--surface); background: var(--rule); margin-left: -12px; transition: transform 0.14s ease;}.avatar-row > .avatar-dot:first-child { margin-left: 0; }.member-strip:hover .avatar-dot { transform: translateY(-2px); }.member-strip-cap { display: block; margin-top: var(--space-3); font-family: var(--mono); font-size: 0.9375rem; color: var(--muted);}.member-strip:hover .member-strip-cap { color: var(--ink); }@media (max-width: 720px) { /* Shorter section on phones; the map still fills it behind the (now full-width) text. A flat scrim (not a left-to-right fade) keeps the full-width copy legible over the map. */ .members-section { min-height: auto; } .members-overlay { max-width: none; } .members-overlay > h2 { font-size: 1.75rem; } .members-section::before { background: color-mix(in oklab, var(--paper) 62%, transparent); }}.stats { display: flex; flex-wrap: wrap; gap: var(--space-8); margin-bottom: var(--space-6); }.stat { text-decoration: none; color: inherit; display: block; }a.stat:hover .stat-num { color: var(--accent); }.stat-num { font-family: var(--mono); font-weight: 700; font-size: 3rem; letter-spacing: -0.02em; line-height: 1; color: var(--inkstrong); display: block; }.stat-label { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); margin-top: 8px; display: block; }.member-link, .post-date { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; }
/* --- feed --- */.feed { display: grid; gap: var(--space-5); max-width: 36em; }/* Past meetups span two columns on wide screens. */.meetups-feed { max-width: none; }@media (min-width: 721px) { .meetups-feed { grid-template-columns: 1fr 1fr; align-items: start; }}.post-card { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); padding: var(--space-6); }.post-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); flex-wrap: wrap; }.post-text { margin: var(--space-2) 0; white-space: pre-wrap; }/* --- activity card (non-Bluesky cross-app items) --- */.activity-app { margin-left: auto; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--rule); border-radius: var(--radius-pill); padding: 2px 8px; }.activity-body { display: block; text-decoration: none; color: inherit; }a.activity-body:hover .activity-title { color: var(--brand); }.activity-title { display: block; font-family: var(--mono); font-weight: 500; font-size: 1rem; color: var(--inkstrong); overflow-wrap: anywhere; }.activity-sub { display: block; font-family: var(--mono); font-size: 0.75rem; color: var(--muted); margin-top: 2px; }.activity-snippet { font-size: 0.9375rem; line-height: 1.6; color: var(--ink); margin: var(--space-2) 0 0; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }.post-foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-5); margin-top: var(--space-4); }.post-foot .post-date { margin-right: auto; }/* Action row: reply / repost / quote / like — icon + count, mu.social-style. */.post-act { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 0.9375rem; line-height: 1; color: var(--muted); background: transparent; border: 0; padding: 2px; min-height: 24px; min-width: 24px; justify-content: center; cursor: pointer; text-decoration: none;}.post-act .act-ico { display: block; }.post-act[data-count='0'] .act-count { display: none; }.post-act:hover { color: var(--brand); }.post-like:hover { color: var(--accent); }.post-like.liked { color: var(--accent); }.post-like.liked .act-ico { fill: currentColor; stroke: currentColor; }.post-repost.reposted { color: #689d6a; }.post-act[disabled] { opacity: 0.6; cursor: wait; }/* Space the "subscribe" button off the feed heading and the first post. */.join-cta + .feed { margin-top: var(--space-6); }.feed-subscribe-btn.subscribed { color: var(--on-brand); background: var(--brand); border-color: var(--brand); }.feed-subscribe-btn[disabled] { opacity: 0.6; cursor: wait; }/* Follow buttons (member cards + footer). Hidden until signed in; JS reveals + sets state. */.follow-btn { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; white-space: nowrap; color: var(--on-brand); background: var(--brand); border: 1px solid var(--brand); border-radius: var(--radius-pill); padding: 3px 12px; cursor: pointer; display: inline-flex; align-items: center; min-height: 24px; }.follow-btn:hover { filter: brightness(1.12); }.follow-btn.following { color: var(--ink); background: transparent; border-color: var(--rule); }.follow-btn.following:hover { border-color: var(--brand); color: var(--brand); }.follow-btn[disabled] { opacity: 0.6; cursor: wait; }
/* --- post embeds (images / external card / quote) --- */.post-images { display: grid; gap: 8px; margin: var(--space-3) 0; grid-template-columns: 1fr; }.post-images[data-count='2'], .post-images[data-count='3'], .post-images[data-count='4'] { grid-template-columns: 1fr 1fr; }.post-images img { width: 100%; max-height: 340px; object-fit: cover; display: block; border: 1px solid var(--rule); border-radius: var(--radius-control); }.post-external { display: flex; gap: var(--space-3); margin: var(--space-3) 0; text-decoration: none; color: inherit; border: 1px solid var(--rule); border-radius: var(--radius-control); overflow: hidden; }.post-external:hover { border-color: var(--brand); }.post-external img { width: 96px; height: 96px; object-fit: cover; flex: none; }.ext-body { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; min-width: 0; }.ext-title { font-family: var(--mono); font-weight: 500; font-size: 0.9375rem; color: var(--inkstrong); }.ext-desc { font-size: 0.9375rem; line-height: 1.5; color: var(--muted); }.ext-host { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; color: var(--muted); }.post-quote { display: block; margin: var(--space-3) 0; padding: var(--space-3); text-decoration: none; color: inherit; border: 1px solid var(--rule); border-radius: var(--radius-control); }.post-quote:hover { border-color: var(--brand); }.quote-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }.quote-head img { border-radius: 50%; flex: none; }.quote-name { font-family: var(--mono); font-weight: 700; font-size: 0.9375rem; color: var(--inkstrong); }.quote-handle { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); }.quote-text { display: block; font-size: 0.9375rem; line-height: 1.55; white-space: pre-wrap; }/* GIF embeds render the animated image directly, not a link card. */.post-gif { display: block; margin: var(--space-3) 0; max-width: 100%; max-height: 400px; border: 1px solid var(--rule); border-radius: var(--radius-control); }/* Media nested inside a quoted post (rendered without its own link). */.quote-images { display: grid; gap: 8px; margin-top: 8px; grid-template-columns: 1fr; }.quote-images[data-count='2'], .quote-images[data-count='3'], .quote-images[data-count='4'] { grid-template-columns: 1fr 1fr; }.quote-images img { width: 100%; max-height: 260px; object-fit: cover; display: block; border: 1px solid var(--rule); border-radius: var(--radius-control); }.quote-gif { display: block; margin-top: 8px; max-width: 100%; max-height: 300px; border: 1px solid var(--rule); border-radius: var(--radius-control); }.quote-external { display: flex; align-items: center; gap: 8px; margin-top: 8px; border: 1px solid var(--rule); border-radius: var(--radius-control); overflow: hidden; }.quote-external img { width: 56px; height: 56px; object-fit: cover; flex: none; }.quote-ext-title { font-family: var(--mono); font-weight: 500; font-size: 0.8125rem; color: var(--inkstrong); padding: 6px 10px; min-width: 0; overflow-wrap: anywhere; }
/* --- events --- */.events-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }@media (max-width: 720px) { .events-grid { grid-template-columns: 1fr; } }.events-note { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; color: var(--muted); margin-bottom: var(--space-5); }.event-card { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); padding: 28px; }.event-card.next { border: 2px solid var(--accent); }.event-top { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 4px var(--space-3); }.event-kicker { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; white-space: nowrap; color: var(--muted); }.event-kicker.next { color: var(--accent-text); }.event-date { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; white-space: nowrap; color: var(--muted); }.event-title { font-family: var(--mono); font-weight: 700; font-size: 1.75rem; letter-spacing: 0.02em; text-transform: uppercase; color: var(--inkstrong); margin: 22px 0 0; }@media (max-width: 720px) { .event-title { font-size: 1.5rem; } }.event-desc { font-size: 0.9375rem; line-height: 1.65; margin: 12px 0 0; }.event-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }.event-card.linked { display: flex; flex-direction: column; }.event-loc { display: block; margin-top: 16px; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }.event-cta { align-self: flex-start; margin-top: var(--space-6); }.event-card.linked .event-cta { margin-top: auto; }/* Organizer badge: our own events vs relevant ecosystem events. */.org-badge { display: inline-flex; align-items: center; font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; padding: 2px 9px; border-radius: var(--radius-pill); white-space: nowrap; }.org-ours { background: var(--brand); color: var(--on-brand); border: 1px solid var(--brand); }.org-ext { background: transparent; color: var(--muted); border: 1px solid var(--rule); }
/* Calendar events (community.lexicon.calendar.event, published via atmo.rsvp). */.cal-event { padding: 0; overflow: hidden; display: flex; flex-direction: column; }.cal-thumb { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; background: var(--rule); }.cal-body { padding: 24px 28px 28px; display: flex; flex-direction: column; flex: 1; }.cal-when { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.14em; color: var(--muted); white-space: nowrap; }.cal-name { font-family: var(--mono); font-weight: 700; font-size: 1.5rem; letter-spacing: 0.01em; color: var(--inkstrong); margin: 14px 0 0; }.cal-loc { margin: 12px 0 0; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }.cal-cancelled { margin: 10px 0 0; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-text); }.cal-desc { font-size: 0.9375rem; line-height: 1.65; margin: 12px 0 0; white-space: pre-line; }.cal-actions { margin-top: auto; padding-top: 28px; display: flex; flex-wrap: wrap; gap: var(--space-3); }.rsvp-btn.going { background: transparent; color: var(--brand); border-color: var(--brand); }.rsvp-btn[disabled] { opacity: 0.6; cursor: wait; }
/* --- join --- */.join-cta { margin-top: var(--space-6); display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }.join-cta + .events-note { margin-top: var(--space-5); }
/* --- footer --- */.site-footer { border-top: 1px solid var(--rule); padding: var(--space-8) 0; margin-top: var(--space-22); }.site-footer .cols { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-6); align-items: flex-end; }.footer-meta { font-family: var(--mono); font-size: 0.875rem; color: var(--muted); line-height: 1.7; margin-top: var(--space-3); }.footer-meta p { margin: 0; }.footer-disclaimer { margin-top: var(--space-3) !important; }.footer-bottom { display: flex; justify-content: flex-end; align-items: center; gap: var(--space-4); margin-top: var(--space-6); }.footer-legal { display: flex; gap: var(--space-5); }.footer-legal a { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); text-decoration: none; }.footer-legal a:hover { color: var(--brand); }.tangled-link { display: inline-flex; opacity: 0.65; }.tangled-link:hover { opacity: 1; }.tangled-link img { display: block; }/* Wraps: without it the 7 nowrap labels give this row a 713px min-content width that widens the page. Centering keeps the text links from stretching to the Follow pill's height. */.footer-links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-6);}
/* --- theme toggle button --- */.icon-btn { font-family: var(--mono); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; min-height: 38px; padding: 0 14px; border: 1px solid var(--rule); border-radius: var(--radius-control); background: var(--surface); color: var(--ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; text-decoration: none;}.icon-btn:hover { border-color: var(--brand); color: var(--brand); }
/* Segmented light/dark switch: both options always visible, the active one filled so the current theme is never ambiguous. Compact so it doesn't crowd the nav (see the .be French-width note). */.theme-toggle { display: inline-flex; border: 1px solid var(--rule); border-radius: var(--radius-control); overflow: hidden;}.theme-opt { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 0; background: var(--surface); color: var(--muted); cursor: pointer;}.theme-opt + .theme-opt { border-left: 1px solid var(--rule); }.theme-opt:hover { color: var(--brand); }.theme-opt[aria-pressed='true'] { background: var(--ink); color: var(--surface); }.theme-opt[aria-pressed='true']:hover { color: var(--surface); }
/* --- auth widget --- */.auth-widget { display: inline-flex; align-items: center; gap: var(--space-2); }.auth-who { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; color: var(--brand); }
/* --- login form --- */.login-form { display: grid; gap: var(--space-3); max-width: 26rem; }.login-input { font-family: var(--mono); font-size: 1rem; padding: 0 14px; min-height: var(--target-min); border: 1px solid var(--rule); border-radius: var(--radius-control); background: var(--surface); color: var(--ink); }/* actor-typeahead dropdown: map its themeable properties to our tokens (fixes dark mode). */actor-typeahead { color: var(--ink); --color-background: var(--surface); --color-border: var(--rule); --color-hover: color-mix(in oklab, var(--brand) 15%, transparent); --color-shadow: #000000; --color-avatar-fallback: var(--rule); --radius: var(--radius-control);}.login-status { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); min-height: 1.2em; margin: 0; }
/* --- tools --- */.tool-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-5); }.tool-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-6); background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); }.tool-head { display: flex; align-items: flex-start; gap: var(--space-3); text-decoration: none; color: inherit; }.tool-head:hover .tool-name { color: var(--brand); }.tool-logo { border-radius: 6px; flex: none; object-fit: contain; background: var(--paper); }/* Mono/dark logos (e.g. Tangled) need a constant light chip to stay visible in dark mode. */.tool-logo-chip { background: #fbf1c7; padding: 2px; box-sizing: content-box; }.logo-dark { display: none; }[data-theme='dark'] .logo-light { display: none; }[data-theme='dark'] .logo-dark { display: block; }@media (prefers-color-scheme: dark) { :root:not([data-theme='light']) .logo-light { display: none; } :root:not([data-theme='light']) .logo-dark { display: block; }}/* Let the text column shrink; break long names/hosts instead of overflowing the card. */.tool-head > span { min-width: 0; }.tool-name { font-family: var(--mono); font-weight: 700; color: var(--inkstrong); display: block; overflow-wrap: anywhere; }.tool-host { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); display: block; overflow-wrap: anywhere; }/* atstore.fyi rating: five stars filled to the mean rating, then the review count spelled out so * it's clear which number is which (the stars are the rating; the text is the count). The fill is a * gold star row clipped to --fill (rating/5) laid over a muted five-star track. */.tool-rating { display: inline-flex; align-items: center; gap: 0.5em; align-self: flex-start; text-decoration: none; }.tool-stars { position: relative; display: inline-block; font-size: 0.95rem; line-height: 1; letter-spacing: 0.12em; font-family: system-ui, "Segoe UI Symbol", sans-serif; --fill: 0%; }.tool-stars::before { content: "★★★★★"; color: var(--rule); }.tool-stars::after { content: "★★★★★"; color: #e8a317; position: absolute; top: 0; left: 0; width: var(--fill); overflow: hidden; white-space: nowrap; }.tool-rating-count { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.02em; color: var(--muted); white-space: nowrap; }.tool-rating:hover .tool-rating-count { color: var(--brand); }.tool-desc { font-size: 0.9375rem; line-height: 1.5; margin: 0; }.tool-creator { display: flex; align-items: center; gap: var(--space-2); font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; color: var(--muted); text-decoration: none; margin-top: auto; }/* A handle with no Sifa display name (e.g. angrydutchman.houseofmadness.org) is a long unbreakable token — let it break inside the card. */.tool-creator > span { min-width: 0; overflow-wrap: anywhere; }.tool-creator:hover { color: var(--brand); }.tool-creator-avatar { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; background: var(--rule); flex: 0 0 auto; }.tools-add { font-family: var(--mono); font-size: 0.9375rem; color: var(--ink); margin-top: var(--space-8); }.tools-add a { color: var(--brand); }.tools-more { font-family: var(--mono); font-size: 0.9375rem; color: var(--muted); margin-top: var(--space-3); }
/* --- event organizer guides --- */.guide-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-5); }.guide-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-6); background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-surface); text-decoration: none; color: inherit; }.guide-card:hover { border-color: var(--brand); }.guide-card:hover .guide-title { color: var(--brand); }.guide-title { font-family: var(--mono); font-weight: 700; color: var(--inkstrong); }.guide-desc { font-size: 0.9375rem; line-height: 1.5; color: var(--muted); }
/* --- long-form guide prose --- */.guide-back { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; margin-bottom: var(--space-4); }.guide-back a { color: var(--muted); text-decoration: none; }.guide-back a:hover { color: var(--brand); }/* Footer nav on each organizer guide: the other guides + back to events. */.guide-nav { margin-top: var(--space-8); padding-top: var(--space-6); border-top: 1px solid var(--rule); }.guide-nav-links { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); margin: var(--space-4) 0; }@media (max-width: 720px) { .guide-nav-links { grid-template-columns: 1fr; } }.guide-nav-back { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; margin-top: var(--space-4); }.guide-nav-back a { color: var(--muted); text-decoration: none; }.guide-nav-back a:hover { color: var(--brand); }.prose { max-width: 36em; }.prose h2 { font-size: 1.75rem; text-transform: none; letter-spacing: 0; margin: var(--space-8) 0 var(--space-3); }.prose h2:first-child { margin-top: 0; }.prose h3 { font-family: var(--mono); font-size: 1.125rem; letter-spacing: 0.02em; color: var(--inkstrong); margin: var(--space-6) 0 var(--space-2); }.prose p { margin: 0 0 var(--space-4); font-size: 1.125rem; line-height: 1.7; }/* Tailwind Preflight strips list markers globally; restore them inside prose. */.prose ul { margin: 0 0 var(--space-4); padding-left: 1.4em; list-style: disc outside; }.prose ol { margin: 0 0 var(--space-4); padding-left: 1.4em; list-style: decimal outside; }.prose li { margin: 0 0 var(--space-2); font-size: 1.125rem; line-height: 1.65; }.prose li::marker { color: var(--muted); }.prose a { color: var(--brand); text-underline-offset: 2px; }.prose strong { color: var(--inkstrong); }.prose code { font-family: var(--mono); font-size: 0.9em; background: var(--surface); border: 1px solid var(--rule); border-radius: 4px; padding: 1px 5px; }