/* Members' app styles. The tokens come from the design stage (prototype/ds.css and design-system.md,
   11 Nov 2026); docs/DESIGN.md says which to use where. No external fonts, scripts or stylesheets:
   the /app CSP allows none. */
/* The display face cut to what the app draws with it: weight 700 to 800, normal width, optical size 12 to 60
   (scripts/subset-font.py, LICENSES/bricolage-grotesque.txt). Set it only at a weight in that range. */
@font-face { font-family: "Bricolage Grotesque"; src: url("fonts/bricolage-grotesque-700-800.woff2") format("woff2"); font-weight: 700 800; font-display: swap; }

/* ------------------------------------------------------------------ 1. Tokens */
:root {
  /* Brand (shared with remotebuilders.io). Raw values: components use the roles below. */
  --plum: #2B1240; --plum-2: #5C4566; --blush: #FFF6F9; --cobalt: #3346E8; --marigold: #FFB31A; --pink: #FF5C9D; --jade: #0FA37F;
  /* The sign-in marks, in their owners' colours (.method): decoration, as the words beside them say the same. */
  --mark-telegram: #1A7BBE; --mark-whatsapp: #25D366;

  /* Roles, light */
  --bg: #FFF6F9;            /* page paper (blush) */
  --surface: #FFFFFF;       /* raised: things you act on as one unit, sheets, inputs, menus */
  --tint: #FFE1EA;          /* quiet fill: tags, segmented track, skeleton base */
  --hover: #FCEAF1;         /* row hover on paper */
  --press: #F7DCE7;         /* row press on paper */
  --ink: #2B1240;           /* text, 15.7:1 on paper */
  --ink-2: #5C4566;         /* secondary text, 7.9:1 on paper */
  --line: #EEDDEB;          /* hairlines and card edges (decorative) */
  --line-strong: #9E89A2;   /* edges that identify a control: 3:1 or more (WCAG 1.4.11) */
  --accent: #3346E8;        /* one meaning: the primary action, selection and state */
  --accent-press: #2535C7;
  --accent-ink: #FFFFFF;
  --accent-soft: #E9EBFF;   /* tonal buttons, selected chips, current nav pill */
  --accent-soft-ink: #2A3AC9;
  --hl: #FFDF94;            /* the highlighter: only under "why you'd meet" */
  --hl-glyph: #FFB31A;
  /* Its band: the lower half of the line here. Dark draws a thin amber band below the text instead, as a
     dark band behind light text read as a strike-through (the networking audit, 15 Nov 2026). */
  --hl-band: var(--hl); --hl-from: 50%; --hl-to: 94%;
  --ok: #0B7A5F; --ok-graphic: #0E9673; --ok-soft: #DDF5EC;
  --err: #B4232F; --err-soft: #FDE8EB;
  --warn: #7A4F00; --warn-soft: #FFF0CC;
  --warm: #FFE1EA;          /* "First time" and other welcoming tags */
  --inverse: #2B1240; --inverse-ink: #FFF6F9;  /* toasts */
  --scrim: rgb(23 8 35 / .45);

  /* Avatar initials tints (bg / fg), chosen by a stable hash of the member id. */
  --av1-bg: #E3E6FF; --av1-fg: #2A3AC9;
  --av2-bg: #FFE6AE; --av2-fg: #5A3A00;
  --av3-bg: #D3F2E6; --av3-fg: #0A5E49;
  --av4-bg: #FFDCEA; --av4-fg: #8A1D4C;
  --av5-bg: #EBDDF0; --av5-fg: #4A2C5C;
  --av6-bg: #2B1240; --av6-fg: #FFE1EA;

  /* Type: one display face (Bricolage Grotesque, self-hosted) and the system UI stack for everything else. */
  --font-display: "Bricolage Grotesque", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-ui: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --fs-12: 12px; --fs-14: 14px; --fs-16: 16px; --fs-18: 18px; --fs-20: 20px; --fs-24: 24px;
  --fs-28: 28px; --fs-30: 30px; --fs-36: 36px; --fs-48: 48px; --fs-60: 60px;

  /* Space (4 px base), radius by role, elevation, motion, layout */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px; --sp-16: 64px;
  --r-xs: 6px; --r-sm: 10px; --r-md: 14px; --r-lg: 20px; --r-xl: 24px; --r-pill: 999px;
  --sh-1: 0 1px 2px rgb(43 18 64 / .06), 0 2px 8px -4px rgb(43 18 64 / .10);
  --sh-2: 0 10px 30px -12px rgb(43 18 64 / .28), 0 2px 6px rgb(43 18 64 / .06);
  --sh-3: 0 24px 64px -16px rgb(43 18 64 / .40);
  --dur-press: 100ms; --dur-1: 150ms; --dur-2: 200ms; --dur-3: 250ms;
  --sk-wait: 300ms;         /* a skeleton shows only once a wait passes this */
  --dur-shimmer: 1400ms;    /* the skeleton's sweep: the one thing that moves on its own */
  --ease-out: cubic-bezier(.22, .8, .3, 1); --ease-in: cubic-bezier(.5, 0, .75, 0);
  --gutter: 16px; --top-h: 56px; --tab-h: 64px; --side-w: 248px; --col-w: 640px; --rail-w: 300px; --wide-w: 1120px;
  --auth-w: 400px;         /* Sign in and Join: the widest Google draws its button */
  --z-top: 20; --z-tab: 30; --z-sheet: 50; --z-toast: 60;

  /* Names today's screens still use, mapped onto the roles (design-system.md section 12). */
  --card: var(--surface); --muted: var(--ink-2); --field: var(--surface); --radius: var(--r-lg); --shadow: var(--sh-1); --display: var(--font-display);
  color-scheme: light;
}

/* Dark: follows the system unless the page says data-theme="light"; data-theme="dark" forces it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #160A21; --surface: #211230; --tint: #2A1839; --hover: #1F102D; --press: #2A1839;
    --ink: #F8EEF9; --ink-2: #C3ADCB; --line: #3A2549; --line-strong: #7D6689;
    --accent: #8C97FF; --accent-press: #A7B0FF; --accent-ink: #160A21; --accent-soft: #272653; --accent-soft-ink: #C3C9FF;
    --hl: #6A4B0C; --hl-glyph: #FFB31A; --hl-band: var(--hl-glyph); --hl-from: 86%; --hl-to: 100%;
    --ok: #4FD1A5; --ok-graphic: #3CC497; --ok-soft: #12302A; --err: #FF8A9B; --err-soft: #3A1520; --warn: #FFC75A; --warn-soft: #36290F;
    --warm: #4A1B33; --inverse: #F8EEF9; --inverse-ink: #2B1240; --scrim: rgb(5 2 9 / .6);
    --av1-bg: #2A2D66; --av1-fg: #C9CEFF; --av2-bg: #4A3410; --av2-fg: #FFD98A; --av3-bg: #123A30; --av3-fg: #8BE6C6;
    --av4-bg: #4A1B33; --av4-fg: #FFB8D4; --av5-bg: #3A2549; --av5-fg: #E6D3EE; --av6-bg: #FFE1EA; --av6-fg: #2B1240;
    --sh-1: none; --sh-2: 0 12px 32px -12px rgb(0 0 0 / .6); --sh-3: 0 24px 64px -16px rgb(0 0 0 / .7);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #160A21; --surface: #211230; --tint: #2A1839; --hover: #1F102D; --press: #2A1839;
  --ink: #F8EEF9; --ink-2: #C3ADCB; --line: #3A2549; --line-strong: #7D6689;
  --accent: #8C97FF; --accent-press: #A7B0FF; --accent-ink: #160A21; --accent-soft: #272653; --accent-soft-ink: #C3C9FF;
  --hl: #6A4B0C; --hl-glyph: #FFB31A; --hl-band: var(--hl-glyph); --hl-from: 86%; --hl-to: 100%;
  --ok: #4FD1A5; --ok-graphic: #3CC497; --ok-soft: #12302A; --err: #FF8A9B; --err-soft: #3A1520; --warn: #FFC75A; --warn-soft: #36290F;
  --warm: #4A1B33; --inverse: #F8EEF9; --inverse-ink: #2B1240; --scrim: rgb(5 2 9 / .6);
  --av1-bg: #2A2D66; --av1-fg: #C9CEFF; --av2-bg: #4A3410; --av2-fg: #FFD98A; --av3-bg: #123A30; --av3-fg: #8BE6C6;
  --av4-bg: #4A1B33; --av4-fg: #FFB8D4; --av5-bg: #3A2549; --av5-fg: #E6D3EE; --av6-bg: #FFE1EA; --av6-fg: #2B1240;
  --sh-1: none; --sh-2: 0 12px 32px -12px rgb(0 0 0 / .6); --sh-3: 0 24px 64px -16px rgb(0 0 0 / .7);
  color-scheme: dark;
}

/* ------------------------------------------------------------------ 2. Base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 400 var(--fs-16)/1.5 var(--font-ui); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }
a { color: var(--accent); text-underline-offset: .18em; text-decoration-thickness: 2px; }
a:hover { text-decoration-color: var(--pink); }
img { max-width: 100%; }
button, input, textarea, select { font: inherit; color: inherit; }
button, a, input, label, select, textarea, summary { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
::selection { background: var(--accent-soft); color: var(--ink); }
input, textarea { caret-color: var(--accent); }
.hidden { display: none !important; }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.num { font-variant-numeric: tabular-nums; }
h1, h2, .display { font-family: var(--font-display); }

/* ------------------------------------------------------------------ 3. Shell */
/* Phones: a slim top bar, the page and five tabs. 960 px and up: the side navigation, no tabs.
   A focused control is never hidden under the top bar or the tabs (WCAG 2.4.11). */
html {
  scroll-padding-top: calc(var(--top-h) + env(safe-area-inset-top) + 8px);
  scroll-padding-bottom: calc(var(--tab-h) + env(safe-area-inset-bottom) + 8px);
}
body { min-height: 100vh; min-height: 100dvh; }
.skip { position: absolute; left: 8px; top: -60px; z-index: 100; padding: 10px 14px; border-radius: var(--r-sm); background: var(--inverse); color: var(--inverse-ink); }
.skip:focus { top: 8px; }
.app { min-height: 100vh; min-height: 100dvh; }
.col { min-width: 0; }
.side { display: none; }
.top {
  position: sticky; top: 0; z-index: var(--z-top);
  min-height: calc(var(--top-h) + env(safe-area-inset-top)); padding: env(safe-area-inset-top) max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left));
  display: flex; align-items: center; gap: var(--sp-2);
  background: var(--bg); background: color-mix(in srgb, var(--bg) 86%, transparent); -webkit-backdrop-filter: saturate(1.5) blur(16px); backdrop-filter: saturate(1.5) blur(16px);
  border-bottom: 1px solid var(--line);
}
.top-brand { display: flex; align-items: center; gap: 10px; min-width: 0; min-height: 44px; text-decoration: none; color: var(--ink); font: 800 var(--fs-18)/1.1 var(--font-display); letter-spacing: -.015em; }
.top-brand span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-brand small { display: block; font: 500 var(--fs-12)/1.3 var(--font-ui); letter-spacing: 0; color: var(--ink-2); }
@media (max-width: 480px) { .top-brand small { display: none; } }
.mark { width: 30px; height: 30px; flex: none; }
.top-back { display: inline-flex; align-items: center; gap: 2px; min-width: 0; min-height: 44px; padding: 0 var(--sp-3) 0 var(--sp-1); margin-left: -6px; border-radius: var(--r-pill); color: var(--ink); text-decoration: none; font-weight: 600; }
.top-back span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-back:hover { background: var(--hover); }
.top-actions { margin-left: auto; display: flex; align-items: center; gap: 2px; }
.top-actions > a:not(.bell) { display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px; border-radius: var(--r-pill); white-space: nowrap; text-decoration: none; color: var(--ink); font-size: var(--fs-14); font-weight: 600; }
.top-actions > a:not(.bell):hover { background: var(--hover); }
.top-actions > a.primary { background: var(--accent); color: var(--accent-ink); }
.top-actions > a.outline { box-shadow: inset 0 0 0 1px var(--line-strong); }
.top-actions > a.primary:hover { background: var(--accent-press); }
/* The bell and the Messages link: 44 px icon buttons with an unread dot (or the count, UNREAD_MARKER in ui.js). */
.bell { position: relative; display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: var(--r-pill); color: var(--ink); text-decoration: none; }
.bell:hover { background: var(--hover); }
.bell .dot { top: 9px; right: 9px; }
.bell-count { position: absolute; top: 4px; right: 2px; min-width: 18px; height: 18px; padding: 0 var(--sp-1); border-radius: var(--r-pill); background: var(--accent); color: var(--accent-ink); font-size: var(--fs-12); font-weight: 700; line-height: 18px; text-align: center; }

main { max-width: var(--wide-w); margin: 0 auto; min-width: 0;
  padding: var(--sp-6) max(var(--gutter), env(safe-area-inset-right)) var(--sp-12) max(var(--gutter), env(safe-area-inset-left)); }
.narrow { max-width: var(--col-w); margin: 0 auto; }
footer.site { max-width: var(--wide-w); margin: 0 auto; padding: 0 var(--gutter) calc(var(--sp-10) + env(safe-area-inset-bottom)); color: var(--ink-2); font-size: var(--fs-14); }
/* With the tabs showing, the end of the page clears them and the home indicator. */
body.has-tabs footer.site { padding-bottom: calc(var(--tab-h) + var(--sp-6) + env(safe-area-inset-bottom)); }

.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-tab);
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  padding: 6px max(4px, env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) max(4px, env(safe-area-inset-left));
  background: var(--surface); background: color-mix(in srgb, var(--surface) 90%, transparent); -webkit-backdrop-filter: saturate(1.5) blur(16px); backdrop-filter: saturate(1.5) blur(16px);
  border-top: 1px solid var(--line); overscroll-behavior: contain;
}
.tabbar:empty, body:not(.has-tabs) .tabbar { display: none; }
.tab { display: flex; flex-direction: column; align-items: center; gap: 3px; min-height: 52px; padding: 2px 0; text-decoration: none; color: var(--ink-2); font-size: var(--fs-12); font-weight: 600; letter-spacing: -.005em; border-radius: var(--r-md); }
.tab-ic { position: relative; display: grid; place-items: center; width: 56px; height: 30px; border-radius: var(--r-pill); }
.tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The current tab shows by more than colour: a pill behind the icon and a heavier stroke. */
.tab[aria-current] { color: var(--ink); font-weight: 700; }
.tab[aria-current] .tab-ic { background: var(--accent-soft); color: var(--accent-soft-ink); }
.tab[aria-current] .i { stroke-width: 2.25; }
.tabbar .dot { top: 1px; right: 12px; box-shadow: 0 0 0 2px var(--surface); }

.side-brand { display: flex; align-items: center; gap: 10px; padding: var(--sp-1) 10px var(--sp-5); text-decoration: none; color: var(--ink); }
.side-brand b { display: block; font: 800 var(--fs-18)/1.1 var(--font-display); letter-spacing: -.015em; }
.side-brand small { display: block; color: var(--ink-2); font-size: var(--fs-12); line-height: 1.3; }
.side-nav { display: flex; flex-direction: column; flex: 1; }
.side-list { display: grid; gap: 2px; }
.side-list + .side-list { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.side-link { position: relative; display: flex; align-items: center; gap: var(--sp-3); min-height: 44px; padding: 0 var(--sp-3); border-radius: var(--r-pill); color: var(--ink); text-decoration: none; font-weight: 600; }
.side-link:hover { background: var(--hover); }
.side-link[aria-current] { background: var(--accent-soft); color: var(--accent-soft-ink); }
.side-link[aria-current] .i { stroke-width: 2.25; }
.side-link .dot, .side-link .bell-count { position: static; margin-left: auto; }
.side-me { margin-top: auto; display: flex; align-items: center; gap: var(--sp-3); min-width: 0; padding: var(--sp-2) var(--sp-3); border-radius: var(--r-lg); color: var(--ink); text-decoration: none; }
.side-me > span:last-child { min-width: 0; }
.side-me:hover { background: var(--hover); }
.side-me[aria-current] { background: var(--accent-soft); }
.side-me b { display: block; font-weight: 600; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-me small { display: block; color: var(--ink-2); font-size: var(--fs-12); }
.side-foot { display: flex; flex-wrap: wrap; column-gap: var(--sp-3); padding: var(--sp-4) var(--sp-3) 0; font-size: var(--fs-12); color: var(--ink-2); }
.side-foot a { color: var(--ink-2); }
/* The three links don't fit one line of the side list, and wrapping left Privacy alone on the second line.
   remotebuilders.io takes the first line, so BSTC and Privacy share the second (UI research, 15 Nov 2026). */
.side-foot a:first-child { flex-basis: 100%; justify-content: flex-start; }

@media (min-width: 960px) {
  .app.signed-in { display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); }
  .app.signed-in .side {
    display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; height: 100dvh; overflow: auto; overscroll-behavior: contain;
    padding: var(--sp-5) var(--sp-3) var(--sp-4); border-right: 1px solid var(--line); background: var(--surface);
  }
  .tabbar { display: none; }
  /* The side navigation carries the mark, Messages and the bell, so a tab's screen needs no top bar. */
  .app.signed-in .top:not(.top-sub) { display: none; }
  .app.signed-in .top.top-sub { padding-inline: var(--sp-8); }
  main { padding: var(--sp-8) var(--sp-8) var(--sp-16); }
  body.has-tabs footer.site { padding-bottom: var(--sp-10); }
  /* One left edge (UI research, 15 Nov 2026): a narrow page starts where the wide ones do, the footer too, and a
     screen the side list names needs no bar to go back to Me. */
  .app.signed-in .narrow { margin-left: 0; }
  footer.site { padding-inline: var(--sp-8); }
  .app.signed-in .top.top-in-side { display: none; }
}

.demo-bar { background: var(--warn-soft); color: var(--warn); font-size: var(--fs-14); text-align: center; padding: 6px var(--gutter); }
.demo-bar button { font: inherit; background: none; border: 0; color: inherit; text-decoration: underline; cursor: pointer; min-height: 24px; padding: 0 var(--sp-1); }

/* Unread or waiting: a dot, never a number, with words for screen readers on its control. */
.dot { position: absolute; top: 2px; right: 10px; width: 10px; height: 10px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--bg); }

/* Avatars. People are round; businesses are rounded squares. Initials when there's no photo. */
.av { position: relative; display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; background: var(--av1-bg); color: var(--av1-fg); font: 700 15px/1 var(--font-display); letter-spacing: -.01em; user-select: none; }
.av > img, .av > svg { width: 100%; height: 100%; object-fit: cover; }
.av-24 { width: 24px; height: 24px; font-size: 10px; }
.av-32 { width: 32px; height: 32px; font-size: 12px; }
.av-48 { width: 48px; height: 48px; font-size: 17px; }
.av-56 { width: 56px; height: 56px; font-size: 19px; }
.av-64 { width: 64px; height: 64px; font-size: 22px; }
.av-96 { width: 96px; height: 96px; font-size: 32px; }
.av-120 { width: 120px; height: 120px; font-size: 40px; }
.av.t2 { background: var(--av2-bg); color: var(--av2-fg); } .av.t3 { background: var(--av3-bg); color: var(--av3-fg); }
.av.t4 { background: var(--av4-bg); color: var(--av4-fg); } .av.t5 { background: var(--av5-bg); color: var(--av5-fg); }
.av.t6 { background: var(--av6-bg); color: var(--av6-fg); }

/* Icons: Lucide on a 24 px grid. Decorative unless the control has no text, then the control carries aria-label. */
.i { width: 24px; height: 24px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.i-20 { width: 20px; height: 20px; }
.i-16 { width: 16px; height: 16px; stroke-width: 2; }

/* The Me hub: you, then grouped rows for the pages that aren't tabs. */
.page { max-width: var(--col-w); margin-inline: auto; min-width: 0; }
:where(.list, .group) { list-style: none; margin: 0; padding: 0; }
.me-head { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--sp-4); row-gap: var(--sp-4); align-items: center; }
.me-head h1 { margin: 0; overflow-wrap: anywhere; }
.me-head p { margin: 2px 0 0; color: var(--ink-2); overflow-wrap: anywhere; }
.me-head .btn-row { grid-column: 1 / -1; }
.me-out { margin-top: var(--sp-8); }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.group { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--sp-1) var(--sp-4); box-shadow: var(--sh-1); }
.group > li + li { border-top: 1px solid var(--line); }
.list-inset > li + li { border-top: 0; position: relative; }
.list-inset > li + li::before { content: ""; position: absolute; top: 0; right: 0; left: var(--inset, 48px); border-top: 1px solid var(--line); }
h2.group-title, .group-title { margin: var(--sp-6) 0 var(--sp-2) var(--sp-1); color: var(--ink-2); font: 600 var(--fs-14)/1.3 var(--font-ui); letter-spacing: 0; }
.set { display: flex; align-items: center; gap: var(--sp-3); min-height: 56px; padding: var(--sp-3) 0; }
.set-ic { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: var(--r-sm); background: var(--tint); color: var(--ink); }
.set-main { flex: 1; min-width: 0; }
.set-main b { display: block; font-weight: 600; line-height: 1.3; }
.set-main span { display: block; color: var(--ink-2); font-size: var(--fs-14); line-height: 1.4; overflow-wrap: anywhere; }
a.set { color: var(--ink); text-decoration: none; }
/* A switch (design-system.md): <input type="checkbox" role="switch" class="switch"> at the end of a label.set
   row, which is its target. Off to start for anything that shares a member's data. The thumb's place says
   off or on, so it's 3:1 on its track in both themes: --ink-2 on --tint off, --accent-ink on --accent on. */
label.set { cursor: pointer; }
.switch { appearance: none; position: relative; flex: none; width: 52px; height: 32px; margin: 0; border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--tint); cursor: pointer; }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%; background: var(--ink-2); }
.switch:checked { background: var(--accent); border-color: var(--accent); }
.switch:checked::after { transform: translateX(20px); background: var(--accent-ink); }
/* Forced colours (Windows contrast themes) paint every background Canvas, which took the thumb and the on
   fill away; here the switch draws itself in the system's colours, as a tick box does. */
@media (forced-colors: active) {
  .switch, .switch::after { forced-color-adjust: none; }
  .switch { background: Canvas; border-color: CanvasText; }
  .switch::after { background: CanvasText; }
  .switch:checked { background: Highlight; border-color: Highlight; }
  .switch:checked::after { background: HighlightText; }
  .switch:focus-visible { outline-color: CanvasText; }
}
a.set:hover .set-main b { text-decoration: underline; }
.chev { flex: none; color: var(--ink-2); }

/* ------------------------------------------------------------------ 4. Type */
/* Type roles (UI research, 15 Nov 2026): app titles, not a poster scale. Weights 400, 500, 600 and 700; 800 is
   the brand mark's, Home's greeting's and big figures'. */
h1 { font: 700 var(--fs-24)/30px var(--font-display); letter-spacing: -.01em; margin: 0 0 var(--sp-2); }
@media (min-width: 960px) { h1 { font-size: var(--fs-28); line-height: 36px; } }
h1.greet { font: 800 var(--fs-30)/36px var(--font-display); letter-spacing: -.02em; }
@media (min-width: 960px) { h1.greet { font-size: var(--fs-36); line-height: 40px; } }
h2 { font: 700 var(--fs-20)/28px var(--font-display); letter-spacing: -.005em; margin: 0 0 var(--sp-2); }
h3 { font-size: var(--fs-16); line-height: 1.3; margin: 0 0 var(--sp-1); }
.lead { color: var(--ink-2); margin: 0 0 var(--sp-5); font-size: var(--fs-16); max-width: 60ch; }
.muted { color: var(--ink-2); }
.small { font-size: var(--fs-14); line-height: 1.45; }

/* ------------------------------------------------------------------ 5. Shared components (public/ui.js) */
/* Focus: every control shows the same ring when the keyboard reaches it (3:1 on the page and on a
   surface, tests/design.test.mjs). The page itself takes focus after a move, without a ring. */
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
#view:focus { outline: none; }

/* Icon button: 44 px, round, an aria-label for its words. */
.iconbtn { position: relative; display: inline-grid; place-items: center; flex: none; width: 44px; height: 44px; padding: 0; border: 0; border-radius: var(--r-pill); background: transparent; color: var(--ink); cursor: pointer; text-decoration: none; }
.iconbtn:hover { background: var(--hover); }

/* Faces, then names in words. Never a count of other people. */
.facepile { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.faces { display: inline-flex; align-items: center; flex: none; }
.faces .av { box-shadow: 0 0 0 2px var(--bg); }
.faces .av + .av { margin-left: -8px; }
:is(.card, .group, .sheet, .toast) .faces .av { box-shadow: 0 0 0 2px var(--surface); }
.facepile-words { min-width: 0; color: var(--ink-2); font-size: var(--fs-14); line-height: 1.4; }

/* Skeletons: the shape of what's coming, shown only once the wait passes --sk-wait. */
.sk-wrap { display: grid; gap: var(--sp-3); min-width: 0; animation: sk-wait var(--dur-1) var(--ease-out) var(--sk-wait) both; }
@keyframes sk-wait { from { opacity: 0; } to { opacity: 1; } }
.sk { display: block; height: 12px; border-radius: var(--r-sm); background: var(--tint); }
.sk-title { height: 30px; width: 55%; max-width: 320px; border-radius: var(--r-md); }
.sk-w80 { width: 80%; } .sk-w60 { width: 60%; } .sk-w40 { width: 40%; }
.sk-av { flex: none; width: 40px; height: 40px; border-radius: 50%; }
.sk-row { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.sk-stack { flex: 1; display: grid; gap: 10px; min-width: 0; }
.sk-rows > .sk-row + .sk-row { padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.sk-cards { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }
.sk-card { display: grid; gap: var(--sp-3); padding: var(--sp-5); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); }

/* Toast: one at a time in the polite status region, above the tabs on phones. */
.toast-region { position: fixed; left: 0; right: 0; bottom: calc(var(--sp-3) + env(safe-area-inset-bottom)); z-index: var(--z-toast); display: grid; justify-items: center; padding: 0 var(--gutter); pointer-events: none; }
body.has-tabs .toast-region { bottom: calc(var(--tab-h) + var(--sp-3) + env(safe-area-inset-bottom)); }
.toast { display: flex; align-items: center; gap: var(--sp-3); max-width: 520px; min-height: 48px; padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4); border-radius: var(--r-md); background: var(--inverse); color: var(--inverse-ink); box-shadow: var(--sh-2); font-size: var(--fs-14); font-weight: 600; pointer-events: auto; }
.toast > span { padding-right: var(--sp-2); }
.toast-act { margin-left: auto; min-height: 44px; padding: 0 var(--sp-3); border: 0; border-radius: var(--r-sm); background: transparent; color: inherit; font-weight: 700; text-decoration: underline; cursor: pointer; }
.toast :focus-visible { outline-color: currentColor; }
@media (min-width: 960px) {
  .toast-region, body.has-tabs .toast-region { bottom: var(--sp-6); }
  .app.signed-in ~ .toast-region { padding-left: calc(var(--side-w) + var(--gutter)); }
}

/* Sheet: a <dialog> opened with showModal(). A bottom sheet on phones, a centred dialog from 640 px. */
dialog.sheet {
  position: fixed; inset: auto 0 0 0; z-index: var(--z-sheet); width: 100%; max-width: 100%; max-height: 92vh; max-height: 92dvh; margin: 0; padding: 0;
  border: 0; border-radius: var(--r-xl) var(--r-xl) 0 0; background: var(--surface); color: var(--ink); box-shadow: var(--sh-3);
  overflow: auto; overscroll-behavior: contain;
}
.sheet[open] { display: flex; flex-direction: column; }
.sheet::backdrop { background: var(--scrim); }
.sheet-grab { flex: none; width: 40px; height: 5px; margin: var(--sp-2) auto 0; border-radius: var(--r-pill); background: var(--line-strong); }
.sheet-head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-1) var(--sp-2) 0 var(--sp-5); }
.sheet-head h2 { flex: 1; min-width: 0; margin: 0; overflow-wrap: anywhere; }
.sheet-x { margin-left: auto; }
.sheet-body { padding: 0 var(--sp-5) calc(var(--sp-5) + env(safe-area-inset-bottom)); min-width: 0; overflow-wrap: anywhere; }
.sheet-foot { position: sticky; bottom: 0; display: flex; gap: var(--sp-2); margin-top: auto; padding: var(--sp-3) var(--sp-5) calc(var(--sp-4) + env(safe-area-inset-bottom)); background: var(--surface); border-top: 1px solid var(--line); }
@media (min-width: 640px) {
  dialog.sheet { inset: 50% auto auto 50%; transform: translate(-50%, -50%); width: min(var(--col-w), calc(100% - 48px)); max-height: min(85vh, 760px); max-height: min(85dvh, 760px); border-radius: var(--r-xl); }
  .sheet-grab { display: none; }
  .sheet-head { padding-top: var(--sp-2); }
  .sheet-body { padding-bottom: var(--sp-6); }
}

/* Empty state: what will show here, and one next step. */
.empty { display: grid; justify-items: center; gap: var(--sp-3); padding: var(--sp-12) var(--sp-4); text-align: center; }
.empty h2, .empty h3 { margin: 0; }
.empty p { margin: 0; max-width: 40ch; color: var(--ink-2); }
.empty .btn { margin-top: var(--sp-2); }
.empty-ic { display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; background: var(--tint); color: var(--ink-2); }
.empty-ic .i { width: 28px; height: 28px; }
.empty-inline { padding: var(--sp-8) var(--sp-4); border: 1px dashed var(--line-strong); border-radius: var(--r-lg); }

/* Segmented control (a tablist): the current view is a raised segment in heavier type. Its ring is what
   draws it on the track (the fill is 1.1:1 there): --ink-2 is 7:1, and differs from the accent focus ring. */
.seg { display: flex; gap: 2px; padding: var(--sp-1); margin-bottom: var(--sp-4); border-radius: var(--r-pill); background: var(--tint); overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; }
.seg::-webkit-scrollbar { display: none; }
.seg [role="tab"] { position: relative; flex: 1 0 auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; padding: 0 var(--sp-4); border: 0; border-radius: var(--r-pill); background: none; color: var(--ink-2); font-size: var(--fs-14); font-weight: 600; white-space: nowrap; cursor: pointer; }
.seg [role="tab"]:hover { color: var(--ink); }
.seg [aria-selected="true"] { background: var(--surface); color: var(--ink); font-weight: 700; box-shadow: var(--sh-1), inset 0 0 0 1px var(--ink-2); }
/* Inside the tab: the tabs sit 2 px apart in a pill track, so a ring outside would run into the next one. */
.seg [role="tab"]:focus-visible { outline-offset: -3px; }
.seg .dot { position: static; }

/* Chips: filters and quick answers. A selected chip carries a tick as well as its colour. Today's
   tick-box chips (a label around a hidden checkbox) and the directory's filter chips look the same. */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* A scroller clips whatever paints outside it, so its padding leaves room for the 4 px focus ring. */
.chips-scroll { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: calc(-1 * var(--gutter)); padding: 6px var(--gutter); scroll-padding-inline: var(--gutter); overscroll-behavior-x: contain; }
.chips-scroll::-webkit-scrollbar { display: none; }
:is(button, a, span).chip, .fchip, label.chip > span {
  flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 var(--sp-4); border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  background: var(--surface); color: var(--ink); font: inherit; font-size: var(--fs-14); font-weight: 600; line-height: 1.2; white-space: nowrap; text-decoration: none; cursor: pointer;
}
:is(button, a).chip:hover, .fchip:hover, label.chip:hover > span { background: var(--hover); }
:is(button, a).chip[aria-pressed="true"], .fchip[aria-pressed="true"], label.chip > input:checked + span { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-soft-ink); }
:is(button, a).chip[aria-pressed="true"]::before, .fchip[aria-pressed="true"]::before, label.chip > input:checked + span::before {
  content: ""; flex: none; width: 10px; height: 5px; margin: -3px 2px 0 -2px; border: solid currentColor; border-width: 0 0 2px 2px; transform: rotate(-45deg);
}
label.chip { position: relative; display: inline-flex; margin: 0; font-weight: 500; cursor: pointer; }
label.chip > input { position: absolute; opacity: 0; pointer-events: none; }
label.chip > input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 3px; }
.chip .i { width: 16px; height: 16px; }
/* A chosen value with its remove button (the stack picker). The button is a 44 px target drawn as a
   28 px circle: it reaches 8 px past the circle each way (padding, with the background kept to the
   circle) and takes no more room in the chip than the circle did (margin -8px). */
span.chip.on { gap: 2px; padding: 0 var(--sp-1) 0 var(--sp-3); cursor: default; }
.chip-x { display: inline-grid; place-items: center; width: 44px; height: 44px; padding: 8px; margin: -8px; border: 0; border-radius: var(--r-pill); background: none; background-clip: content-box; color: var(--ink-2); cursor: pointer; }
.chip-x:hover, .chip-x:focus-visible { background-color: var(--hover); color: var(--ink); }
.chip-x:focus-visible { outline-offset: -6px; }

/* Press feedback and the entrances: transform and opacity only, and none of it under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .btn, .iconbtn, .chip, .fchip, .tab-ic, .side-link, .seg [role="tab"] { transition: background-color var(--dur-1) var(--ease-out), transform var(--dur-press) var(--ease-out); }
  .switch, .switch::after { transition: background-color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
  .btn:active:not([disabled]) { transform: scale(.97); }
  .iconbtn:active, .bell:active { transform: scale(.92); }
  :is(button, a).chip:active, .fchip:active, label.chip:active > span { transform: scale(.96); }
  .tab:active .tab-ic { transform: scale(.92); }
  .sk { background: linear-gradient(90deg, var(--tint) 0%, color-mix(in srgb, var(--tint) 40%, var(--surface)) 50%, var(--tint) 100%); background-size: 200% 100%; animation: sk-sweep var(--dur-shimmer) linear infinite; }
  @keyframes sk-sweep { from { background-position: 100% 0; } to { background-position: -100% 0; } }
  .sheet[open] { animation: sheet-in var(--dur-3) var(--ease-out); }
  @keyframes sheet-in { from { transform: translateY(100%); } }
  .toast { animation: toast-in var(--dur-2) var(--ease-out); }
  @keyframes toast-in { from { transform: translateY(8px); opacity: 0; } }
}
@media (prefers-reduced-motion: no-preference) and (min-width: 640px) {
  .sheet[open] { animation-name: sheet-in-centre; }
  @keyframes sheet-in-centre { from { transform: translate(-50%, -46%); opacity: 0; } }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

/* ------------------------------------------------------------------ 6. Today's screens, on the tokens */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--sh-1); }
.card + .card, .stack > * + * { margin-top: var(--sp-3); }
.grid > .card, .tiles > * { margin-top: 0; }
.grid { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.tiles { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); margin-top: var(--sp-5); }
.tile { display: block; text-decoration: none; color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--sp-4); }
.tile:hover { border-color: var(--accent); }
.tile strong { display: block; margin-bottom: 2px; }
.tile .badge { float: right; }

/* Notices */
.note { border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); margin: 0 0 var(--sp-4); background: var(--accent-soft); color: var(--ink); }
.note.ok { background: var(--ok-soft); }
.note.warn { background: var(--warn-soft); }
.note p { margin: 0; }
.note p + p { margin-top: 6px; }
.badge { display: inline-block; font-size: var(--fs-12); font-weight: 600; padding: 2px var(--sp-2); border-radius: var(--r-pill); background: var(--accent-soft); color: var(--accent-soft-ink); white-space: nowrap; }
.badge.ok { background: var(--ok-soft); color: var(--ok); }
.badge.warn { background: var(--warn-soft); color: var(--warn); }
.badge.plain { background: var(--tint); color: var(--ink-2); }

/* Forms */
label { display: block; font-weight: 600; font-size: var(--fs-14); margin: var(--sp-4) 0 6px; }
.opt { font-weight: 400; color: var(--ink-2); }
input[type=text], input[type=email], input[type=url], input[type=tel], input[type=search], input[type=datetime-local], select, textarea {
  width: 100%; min-height: 48px; padding: 11px var(--sp-3); border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); font: inherit;
}
textarea { min-height: 88px; resize: vertical; }
/* The browsers' own placeholder grey fails 4.5:1 (Safari's most of all) and Firefox dims it: --ink-2 is 7:1 or more. */
input::placeholder, textarea::placeholder { color: var(--ink-2); opacity: 1; }
[aria-invalid="true"] { border-color: var(--err); }
/* The file picker's button: a 44 px outline pill, not the browser's small grey one. */
input[type=file] { max-width: 100%; min-height: 44px; font-size: var(--fs-14); color: var(--ink-2); }
input[type=file]::file-selector-button { min-height: 44px; margin-right: var(--sp-3); padding: 0 var(--sp-4); border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--surface); color: var(--ink); font: inherit; font-weight: 600; cursor: pointer; }
input[type=file]::file-selector-button:hover { background: var(--hover); }
/* A disclosure (Report or block, Bring a founder, the organisers' editors) is a 44 px target. */
summary { min-height: 44px; padding-block: 10px; cursor: pointer; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-3); }
.row3 { display: grid; grid-template-columns: 2fr 1fr; gap: 0 var(--sp-3); align-items: end; }
@media (max-width: 560px) { .row, .row3 { grid-template-columns: 1fr; } }
/* A tick row is a 44 px target like every other main one (overnight decision 21): 24 px of text and 10 px above
   and below; a label that wraps grows. The live /join keeps its own (index.html). */
.check { display: flex; gap: 10px; align-items: flex-start; min-height: 44px; padding-block: 10px; font-weight: 400; font-size: var(--fs-16); margin: 2px 0 0; }
.check input { margin-top: 3px; width: 18px; height: 18px; flex: none; accent-color: var(--accent); }
.hint { font-size: var(--fs-14); line-height: 1.45; color: var(--ink-2); margin-top: var(--sp-1); }
/* min-width: 0 because a fieldset is as wide as its widest content by default, which pushed the
   profile page past a 390px phone screen (the file inputs under Pictures). */
fieldset { border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--sp-1) var(--sp-4) var(--sp-4); margin: var(--sp-5) 0 0; min-width: 0; }
legend { font-weight: 700; padding: 0 6px; }
.stack-pick { display: grid; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.stack-pick .chips:empty { display: none; }
.rules { font-size: var(--fs-14); color: var(--ink-2); background: var(--tint); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px var(--sp-3); margin-top: var(--sp-2); }
.rules ul { margin: var(--sp-1) 0 0; padding-left: 18px; }
/* Member-typed notes and addresses can be one long word; they wrap rather than widen a phone's page. */
.rights-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: grid; gap: var(--sp-2); min-width: 0; }
.rights-list li, .rights-row, .listing, .add-email { min-width: 0; overflow-wrap: anywhere; }
.rights-row h3 { margin: 0; }
.rights-card h3 { margin-top: var(--sp-5); }
.rights-card .status:empty { min-height: 0; margin: 0; }
.rights-queue h2 { margin-top: var(--sp-6); }
.add-email { margin-top: var(--sp-4); }

.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2); text-decoration: none; border: 1px solid transparent; border-radius: var(--r-pill); padding: 10px var(--sp-5); min-height: 44px;
  font: inherit; font-weight: 600; line-height: 1.2; cursor: pointer; background: var(--accent); color: var(--accent-ink); }
.btn.block { display: flex; width: 100%; margin-top: var(--sp-4); }
.btn.ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); font-weight: 600; }
.btn.small { padding: 6px 14px; min-height: 36px; font-size: var(--fs-14); }
.btn.danger { background: var(--surface); color: var(--err); border-color: var(--err); }
.remove-step { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); }
.remove-step > input { flex: 1 1 220px; min-width: 0; }
.btn-tonal { background: var(--accent-soft); color: var(--accent-soft-ink); }
.btn-outline { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn[disabled], button.set[disabled] { opacity: .55; cursor: wait; }
.actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-3); }
.actions > .badge { align-self: center; }
.status { min-height: 20px; margin-top: 10px; font-size: var(--fs-14); }
.status.err { color: var(--err); }
.status.ok { color: var(--ok); }

/* Sign-in */
.signin { display: grid; gap: var(--sp-2); margin-top: var(--sp-5); }
.signin .btn { width: 100%; }
.signin > .method, .signin > .google-slot { margin: 0; }
.divider { display: flex; align-items: center; gap: var(--sp-3); color: var(--ink-2); font-size: var(--fs-14); margin: var(--sp-3) 0 var(--sp-2); }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
/* Cloudflare shows its check only when a person has to act (interaction-only), so no room is held for it. */
.cf-check { min-height: 0; }
/* Google draws its own 40 px pill in a 44 px frame, centred in the column. color-scheme: light, or Chrome paints
   a white box behind Google's light frame on the dark page. */
.google-slot { display: flex; align-items: center; justify-content: center; min-height: 44px; color-scheme: light; }

/* Auth cards (Sign in, Join and their messages): a column as wide as Google's button can be, centred, with the
   page footer centred under it. 468 px = 400 of content, 32 px padding each side and the 2 px ink edge (a brand
   signature from remotebuilders.io's hero surfaces). */
.auth.card { max-width: calc(var(--auth-w) + 2 * var(--sp-8) + 4px); margin: var(--sp-8) auto 0; padding: var(--sp-8); border: 2px solid var(--ink); }
.auth h1 { font: 700 var(--fs-24)/30px var(--font-display); letter-spacing: -.01em; margin: 0; }
.auth .lead { margin: var(--sp-2) 0 0; }
.auth .signin { margin-top: var(--sp-6); }
.auth .signin label { margin-top: 0; }
.auth .signin .btn.block { min-height: 48px; }
.auth .join-email { margin-top: var(--sp-2); }
.auth .join-email > .small { margin: 0; }
.auth > p.small { margin: var(--sp-6) 0 0; }
.auth .status:empty { min-height: 0; margin: 0; }
body:has(.auth) footer.site { text-align: center; }
@media (min-width: 600px) { .auth h1 { font-size: var(--fs-28); line-height: 36px; } }
@media (max-width: 599px) { .auth.card { margin-top: var(--sp-4); padding: var(--sp-6) var(--sp-5); } }
/* Joining with no community named: both, as two rows to pick from. */
.picks { display: grid; gap: var(--sp-2); margin-top: var(--sp-6); }
.pick { display: flex; align-items: center; gap: var(--sp-3); min-height: 64px; padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--surface); color: var(--ink); text-decoration: none; }
.pick:hover { background: var(--hover); }
.pick-main { flex: 1; min-width: 0; }
.pick-main b { display: block; font-weight: 600; }
.pick-main span { display: block; color: var(--ink-2); font-size: var(--fs-14); line-height: 20px; }

/* Directory */
.filters { display: grid; grid-template-columns: 2fr 1fr 1.1fr 1fr 1.2fr; gap: var(--sp-2); margin-bottom: var(--sp-4); }
@media (max-width: 760px) { .filters { grid-template-columns: 1fr 1fr; } .filters input[type=search] { grid-column: 1 / -1; } }
.member { display: flex; flex-direction: column; gap: 10px; cursor: pointer; text-align: left; font: inherit; color: inherit; width: 100%; }
.member:hover { border-color: var(--accent); }
.member-head { display: flex; gap: var(--sp-3); align-items: center; min-width: 0; }
.avatar { width: 52px; height: 52px; border-radius: var(--r-md); background: var(--accent-soft); color: var(--accent-soft-ink); display: grid; place-items: center; font-weight: 700; overflow: hidden; flex: none; }
.avatar.round { border-radius: 50%; }
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar.logo img { object-fit: contain; background: #fff; }
.avatar.tile { background: none; }
.avatar.big { width: 84px; height: 84px; font-size: var(--fs-24); }
.member-head div { min-width: 0; }
.member-head strong, .member-head .muted { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.links { display: flex; flex-wrap: wrap; gap: 0 var(--sp-4); font-size: var(--fs-14); }
.links a, .linkrow > a:not(.btn), footer.site a, .side-foot a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; }
/* The page footer's Privacy link starts a line of text that wraps on phones: its 44 px box reaches 12 px
   above and below the line, so that line is no taller than the next. It reaches 12 px each side too, so
   its focus ring, pulled in by 10 px, sits 2 px out from the word instead of running through the next line.
   One layer up, it takes the taps on the part of its box over the next line, which would otherwise take them. */
footer.site a { margin-block: -12px; padding-inline: 12px; margin-inline: -12px; position: relative; z-index: 1; }
footer.site a:focus-visible { outline-offset: -9px; }
/* In a list with a line under each, the link's target grows 10 px each way without moving anything, and
   its focus ring sits 2 px out from the words, not round the target, where it crossed the line under it.
   One layer up, so that line doesn't take the taps on the target's lowest 10 px. */
.checklist a { display: inline-block; padding-block: 10px; margin-block: -10px; padding-inline: 10px; margin-inline: -10px; position: relative; z-index: 1; }
.checklist a:focus-visible { outline-offset: -7px; }

dialog { border: 0; border-radius: var(--r-lg); padding: 0; max-width: var(--col-w); width: calc(100% - 32px); background: var(--surface); color: var(--ink); box-shadow: var(--sh-3); }
dialog::backdrop { background: var(--scrim); }
.kv { display: grid; grid-template-columns: 120px 1fr; gap: 6px var(--sp-3); font-size: var(--fs-16); margin: var(--sp-3) 0; }
.kv dt { color: var(--ink-2); }
.kv dd { margin: 0; overflow-wrap: anywhere; }

/* Profile pictures */
.pics { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-3); }
@media (max-width: 560px) { .pics { grid-template-columns: minmax(0, 1fr); } }
.pic { display: flex; gap: var(--sp-3); align-items: center; border: 1px dashed var(--line); border-radius: var(--r-md); padding: var(--sp-3); min-width: 0; }
.pic > div { min-width: 0; }
.pic .avatar { width: 64px; height: 64px; }
.pic b { display: block; margin-bottom: 6px; }
/* The browser's "No file chosen" doesn't fit beside the picture on a phone and showed cut short;
   the line under the button says what's happening instead. The button keeps its own colour. */
.pic input[type=file] { color: transparent; }

/* Organisers */
.stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
/* Organisers on phones (UI research, 15 Nov 2026): under 600 px the views are a select and the numbers one line, with
   the cards a press away; from 600 px the tabs and the cards. Each shows at one width only. */
.org-views > .org-section { display: none; }
.org-section label { margin-top: 0; }
.stats-line { display: none; }
@media (max-width: 599px) {
  .org-views > .org-section { display: grid; margin-bottom: var(--sp-4); }
  .org-views > .seg { display: none; }
  .stats-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin: 0; }
  .stats-box:not(.open) > .stats { display: none; }
  .stats-box.open > .stats { margin-top: var(--sp-3); }
}
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--sp-3) 14px; }
.stat b { display: block; font-size: var(--fs-24); font-variant-numeric: tabular-nums; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-14); }
.table th, .table td { text-align: left; padding: var(--sp-2) 6px; border-top: 1px solid var(--line); vertical-align: top; }
.table th { color: var(--ink-2); font-weight: 600; border-top: 0; }
.scroll { overflow-x: auto; }

/* Resources (Markdown) */
.prose { max-width: 62ch; }
.prose h2 { margin-top: 1.4em; }
.prose h3 { margin-top: 1.2em; }
.prose li + li { margin-top: var(--sp-1); }
.prose code { background: var(--tint); padding: 1px 5px; border-radius: var(--r-xs); font-size: .92em; }

/* Home */
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.card-head h2 { margin: 0; }
/* A head's own link (All events, Directory) is a 44 px target that reaches 8 px into the room
   around the head (a card's padding, the gap below), so the head barely moves. */
.card-head > a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; margin-block: -8px; }
section > .card-head { margin: var(--sp-6) 0 var(--sp-3); }
.dash { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: start; margin-top: var(--sp-4); }
.dash > .card { margin: 0; }
/* Home's cards (app.js viewHome): a plain box, so the cards lay out as they did without it. While their reads are
   out it holds placeholders in the cards' own grid (.dash) and top margin, so the cards land where these sat. */
.home-cards > .sk-wrap { margin-top: var(--sp-4); grid-template-columns: minmax(0, 1fr); }
.home-cards > .sk-wrap > .sk-cards { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.checklist { list-style: none; margin: var(--sp-1) 0 0; padding: 0; display: grid; gap: var(--sp-3); }
.checklist li { display: grid; grid-template-columns: 26px 1fr; gap: 10px; align-items: start; }
.checklist .tick { width: 24px; height: 24px; border-radius: var(--r-pill); border: 2px solid var(--line-strong); display: grid; place-items: center; }
.checklist .tick .i { width: 14px; height: 14px; stroke-width: 3; }
.checklist li.done .tick { background: var(--ok-graphic); border-color: var(--ok-graphic); color: var(--surface); }
.checklist li.done s { color: var(--ink-2); }
.checklist a { font-weight: 600; }
.eventlist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.eventlist li { display: grid; grid-template-columns: 92px 1fr; gap: 10px; }
.eventlist .when { font-size: var(--fs-14); font-weight: 600; color: var(--accent); }
.linkrow { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* Directory filters */
.filters.dir { grid-template-columns: 2fr 1fr 1fr; }
@media (max-width: 760px) { .filters.dir { grid-template-columns: 1fr 1fr; } }
.chipbox { display: grid; gap: var(--sp-2); margin-bottom: 14px; }
/* Each row: its label, then chips that wrap (never a hidden sideways scroll). On a phone the rows sit behind
   the Filters button, each label over its chips. */
.chiprow { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 6px var(--sp-2); align-items: start; min-width: 0; }
.chiprow .chips { flex-wrap: wrap; gap: 6px; min-width: 0; }
.chiprow .chips:empty { display: none; }
.filters-toggle { display: none; }
.btn.filters-toggle { min-height: 44px; }
@media (max-width: 767px) { .filters-toggle { display: inline-flex; } .chipbox:not(.open) { display: none; } }
.chiprow-label { padding-top: 8px; font-size: var(--fs-14); line-height: 20px; font-weight: 600; color: var(--ink-2); }
.dir-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.dir-bar p { margin: 0; }
@media (max-width: 767px) { .chiprow { grid-template-columns: minmax(0, 1fr); } .chiprow-label { padding-top: 0; } .filters-toggle { margin-bottom: var(--sp-3); } }

/* People (public/people.js): a person first. One markup, two forms: a row on phones and cards from 960 px;
   suggestions are cards that swipe on phones. The highlighter marks only why two members would meet. */
.people-bar { display: flex; gap: var(--sp-2); align-items: center; margin: var(--sp-4) 0 var(--sp-3); }
.people-bar input[type=search] { flex: 1; min-width: 0; margin: 0; }
.people-bar .btn { flex: none; }
.people-on:not(:empty) { margin-bottom: var(--sp-3); }
.people-d6 { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.people-d6 p { flex: 1 1 240px; margin: 0; }
.people-suggest { margin-bottom: var(--sp-6); }
.people-suggest .card-head { align-items: center; flex-wrap: wrap; row-gap: var(--sp-2); }
.people-widen, .people-foot { justify-content: center; margin-top: var(--sp-3); }
/* How you show in People: each tick-box row is a 44 px target on one line or several, a single line in its middle. */
.check.people-check { display: grid; grid-template-columns: auto minmax(0, 1fr); align-content: center; min-height: 44px; }
.people { list-style: none; margin: 0; padding: 0; display: grid; min-width: 0; }
.person { position: relative; display: grid; min-width: 0; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "av head act" "av body body"; column-gap: var(--sp-3); row-gap: 2px; padding: var(--sp-4) 0; }
.people > .person + .person { border-top: 1px solid var(--line); }
.person > .av { grid-area: av; }
.person-head { grid-area: head; min-width: 0; align-self: center; }
.person-act { grid-area: act; align-self: center; position: relative; z-index: 1; display: flex; gap: var(--sp-2); }
.person-body { grid-area: body; min-width: 0; }
/* A member with just a name (a new profile starts that way) has no body row (people.js), so the name sits level with
   the face rather than in the top half of a row the face stretched, and the cards below end at their padding. */
.person:not(:has(> .person-body)) { grid-template-areas: "av head act"; }
.person-name { margin: 0; font: 700 var(--fs-18)/1.2 var(--font-display); letter-spacing: -.012em; overflow-wrap: anywhere; }
.person-name a { color: var(--ink); text-decoration: none; }
.person-name a:hover { text-decoration: underline; }
:is(.person-name, .profile-name) .badge { margin-left: 6px; vertical-align: 3px; font-family: var(--font-ui); letter-spacing: 0; }
.person-biz { display: flex; align-items: center; gap: 6px; margin: 3px 0 0; color: var(--ink-2); font-size: var(--fs-14); line-height: 1.35; min-width: 0; }
.person-biz span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.person-biz .i, .profile-where .i { flex: none; width: 16px; height: 16px; }
.person-line { margin: 6px 0 0; font-size: var(--fs-14); line-height: 1.45; overflow-wrap: anywhere; }
.person-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: var(--sp-2) 0 0; min-width: 0; }
.tag { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; max-width: 100%; padding: 0 var(--sp-3); border-radius: var(--r-pill); background: var(--tint); color: var(--ink); font-size: var(--fs-14); font-weight: 500; overflow-wrap: anywhere; }
.tag .i { flex: none; width: 16px; height: 16px; color: var(--ink-2); }
.reason { display: flex; gap: 6px; align-items: flex-start; margin: var(--sp-2) 0 0; font-size: var(--fs-14); line-height: 1.45; }
.reason .i { flex: none; width: 16px; height: 16px; margin-top: 2px; color: var(--ink-2); }
.reason mark { color: inherit; padding: 0 .14em; margin: 0 -.14em; background: linear-gradient(to bottom, transparent var(--hl-from), var(--hl-band) var(--hl-from), var(--hl-band) var(--hl-to), transparent var(--hl-to)); -webkit-box-decoration-break: clone; box-decoration-break: clone; }
/* The name's link opens the page from anywhere on the card; the menu sits above it. */
.stretch::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-md); }
.people-scroll { gap: var(--sp-3); grid-auto-flow: column; grid-auto-columns: minmax(248px, 80%); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; margin-inline: calc(-1 * var(--gutter)); padding: 6px var(--gutter) var(--sp-2); scroll-padding-inline: var(--gutter); overscroll-behavior-x: contain; }
.people-scroll::-webkit-scrollbar { display: none; }
.people-scroll > .person { scroll-snap-align: start; }
.people-scroll > .person { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "av act" "head head" "body body"; align-content: start; row-gap: var(--sp-2); padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--sh-1); }
.people-scroll > .person:not(:has(> .person-body)) { grid-template-areas: "av act" "head head"; }
@media (min-width: 960px) {
  .people-scroll { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); overflow: visible; margin-inline: 0; padding: 0; }
  .people-dir { gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); }
  .people-dir > .person { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "av act" "head head" "body body"; align-content: start; row-gap: var(--sp-2); padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--sh-1); }
  .people-dir > .person:not(:has(> .person-body)) { grid-template-areas: "av act" "head head"; }
}
.people-dir > .person:hover, .people-scroll > .person:hover { border-color: var(--line-strong); }
.people-scroll > .person > .av, .people-dir > .person > .av { justify-self: start; }
@media (prefers-reduced-motion: no-preference) {
  .people-scroll > .person, .people-dir > .person { transition: border-color var(--dur-1) var(--ease-out), transform var(--dur-press) var(--ease-out); }
  .person:has(.stretch:active) { transform: scale(.985); }
}
/* What's held back says how to see it (give to get), never blurred. */
.lock { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); padding: var(--sp-3) var(--sp-4); border: 1px dashed var(--line-strong); border-radius: var(--r-md); color: var(--ink-2); font-size: var(--fs-14); }
.lock p { flex: 1 1 200px; margin: 0; }
.lock .i { flex: none; width: 16px; height: 16px; }
.fset { min-width: 0; margin: 0; padding: 0; border: 0; }
.fset + .fset { margin-top: var(--sp-6); }
.fset > legend { padding: 0; margin-bottom: var(--sp-3); font-weight: 600; }
/* A member's page */
.profile-head { display: grid; gap: var(--sp-3); justify-items: start; min-width: 0; padding: var(--sp-5); border: 2px solid var(--ink); border-radius: var(--r-lg); background: var(--surface); }
.profile-head > * { margin: 0; max-width: 100%; }
.profile-name { font-size: var(--fs-36); line-height: 1.05; letter-spacing: -.03em; overflow-wrap: anywhere; }
.profile-tagline { color: var(--ink-2); font-size: var(--fs-18); line-height: 1.4; max-width: 46ch; overflow-wrap: anywhere; }
.profile-where { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); color: var(--ink-2); font-size: var(--fs-14); }
.profile-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-1); }
.profile-actions:empty, .people-note:empty { display: none; }
.profile-sec { margin-top: var(--sp-8); min-width: 0; overflow-wrap: anywhere; }
.profile-sec h2 { margin-bottom: var(--sp-3); font-size: var(--fs-18); letter-spacing: -.01em; }
.profile-sec p { margin: 0 0 var(--sp-2); max-width: 62ch; }
.profile-biz { font-weight: 600; }
@media (min-width: 960px) { .profile-name { font-size: var(--fs-48); } }
/* The networking audit (15 Nov 2026): Ask on a card, each kind of chip under a visible label, Open to asks
   beside How you show in People, and a member's page with Ask first, contact details as a text link and,
   on a desk, why you'd meet, vouches and what asking shares in a column beside it. */
.people-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2); margin: 0 0 var(--sp-3); }
.people-tools > .chip { min-height: 44px; }
.person-chips { display: grid; gap: 6px; margin: var(--sp-2) 0 0; min-width: 0; }
.tag-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; min-width: 0; }
.tag-label { color: var(--ink-2); font-size: var(--fs-14); font-weight: 600; }
.person-ask { position: relative; z-index: 1; margin-top: var(--sp-3); min-width: 0; }
.person-ask .btn { max-width: 100%; }
.person-asked { display: inline-flex; align-items: center; min-height: 44px; margin: 0; color: var(--ink-2); font-size: var(--fs-14); font-weight: 600; }
button.textlink { display: inline-flex; align-items: center; min-height: 44px; padding: 0; border: 0; background: none; color: var(--accent); font: inherit; font-size: var(--fs-14); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.profile-main { min-width: 0; }
.profile-side { display: grid; gap: var(--sp-6); margin-top: var(--sp-6); min-width: 0; }
.profile-side > * { margin: 0; min-width: 0; }
.profile-side > :empty { display: none; }
.profile-side-sec h2 { margin-bottom: var(--sp-2); font-size: var(--fs-18); letter-spacing: -.01em; }
.profile-side-sec p { margin: 0; max-width: 62ch; }
@media (min-width: 1100px) {
  .people-member.has-side { max-width: calc(var(--col-w) + var(--rail-w) + var(--sp-10)); display: grid; grid-template-columns: minmax(0, 1fr) var(--rail-w); column-gap: var(--sp-10); align-items: start; }
  .people-member.has-side > .profile-head { grid-column: 1; grid-row: 1; }
  .people-member.has-side > .profile-main { grid-column: 1; grid-row: 2; }
  .people-member.has-side > .profile-side { grid-column: 2; grid-row: 1 / span 2; margin-top: 0; }
}

/* What builders use */
.ranking { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: grid; gap: var(--sp-1); max-width: 720px; }
.ranking a { display: grid; grid-template-columns: minmax(110px, 180px) 1fr 44px; gap: var(--sp-3); align-items: center; text-decoration: none; color: var(--ink); padding: var(--sp-2) 10px; min-height: 44px; border-radius: var(--r-sm); }
.ranking a:hover { background: var(--surface); }
.rank-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar { height: 10px; background: var(--tint); border: 1px solid var(--line); border-radius: var(--r-xs); overflow: hidden; }
.bar span { display: block; height: 100%; background: var(--accent); border-radius: 0 var(--r-xs) var(--r-xs) 0; }
.rank-val { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-2); font-weight: 600; }

/* Sign in through @BSTCHostBot. Telegram's own blue: white on it is 4.6:1. */
.btn.tg { background: #1A7BBE; border-color: #1A7BBE; color: #fff; display: inline-flex; align-items: center; justify-content: center; gap: 10px; text-decoration: none; }
.btn.tg:hover { background: #1873B3; }
.tg-mark { width: 20px; height: 20px; fill: currentColor; flex: none; }
/* A way to sign in (design-system.md .method): Telegram and WhatsApp as the same outline pill as Google's own
   button, the mark on the left in its owner's colour (beside words that say the same, so it's decoration) and
   the words centred. Its spacing is .btn.block's, which it replaces. */
.method { position: relative; isolation: isolate; display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; margin-top: var(--sp-4); padding: 0 var(--sp-3); border: 0; border-radius: var(--r-pill); background: none; color: var(--ink); font: 500 var(--fs-14)/20px var(--font-ui); text-decoration: none; cursor: pointer; }
.method::before { content: ""; position: absolute; inset: 2px 0; z-index: -1; border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--surface); }
.method:hover::before { background: var(--hover); }
.method:focus-visible { outline-offset: -2px; }
.method[disabled] { opacity: .55; cursor: wait; }
.method > svg { width: 18px; height: 18px; flex: none; }
.method > span { flex: 1; min-width: 0; text-align: center; }
.method .tg-mark { fill: var(--mark-telegram); }
.method .wa-mark { fill: var(--mark-whatsapp); }
@media (prefers-reduced-motion: no-preference) {
  .method { transition: background-color var(--dur-1) var(--ease-out), transform var(--dur-press) var(--ease-out); }
  .method:active:not([disabled]) { transform: scale(.98); }
}
.tg-panel { display: grid; gap: 10px; text-align: center; margin: 0; }
.tg-panel p { margin: 0; }
.tg-number { font: 800 var(--fs-60)/1 var(--font-display); letter-spacing: .04em; color: var(--accent); font-variant-numeric: tabular-nums; }
.dir-card { display: grid; gap: 10px; align-content: start; }
.dir-card h2, .dir-card p { margin: 0; }
.dir-card .btn { justify-self: start; }
.dir-card textarea { font: 13px/1.4 var(--font-mono); margin: var(--sp-2) 0; }
section.dir-card + .note, h1 + .dir-card { margin-bottom: var(--sp-4); }

/* The profile in sections (public/profile.js): each card shows what's saved, and its Edit opens a form of its own. */
.psec-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.psec-head h2 { margin: 0; min-width: 0; }
.psec-head .btn { flex: none; min-height: 44px; }
.psec-read { display: grid; grid-template-columns: minmax(0, 1fr); margin: var(--sp-2) 0 0; }
.psec-read dt { margin-top: var(--sp-3); font-size: var(--fs-14); font-weight: 600; color: var(--ink-2); }
.psec-read dd { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--sp-2); margin: 2px 0 0; min-width: 0; }
.psec-read .val { min-width: 0; overflow-wrap: anywhere; white-space: pre-line; }
.psec-read .unset { color: var(--ink-2); }
@media (min-width: 720px) {
  .psec-read { grid-template-columns: minmax(0, 2fr) minmax(0, 5fr); gap: var(--sp-3) var(--sp-4); margin-top: var(--sp-4); }
  .psec-read dt, .psec-read dd { margin: 0; }
}
/* An empty status line takes no room: under a section, and at the foot of the directory card (it left a blank band). */
.psec > .status:empty, .dir-card > .status:empty { min-height: 0; margin: 0; }
/* Who sees a field sits on its label's line, as wide as its longest choice; the label wraps beside it, and the box
   below takes the card's width, so neither is cut short on a phone. */
.fld-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-2) var(--sp-3); margin: var(--sp-4) 0 6px; }
.fld-head > label, .pair-label { flex: 1 1 auto; min-width: 0; margin: 0; font-weight: 600; font-size: var(--fs-14); }
.fld-head > select { flex: none; width: auto; min-height: 44px; padding-block: 8px; }
.psec-form > .hint:first-child { margin: var(--sp-2) 0 0; }
/* Save and Cancel stay in view while a section is open: above the tabs on a phone, and above the keyboard (--kb,
   which profile.js measures, as a sticky bar alone would sit behind it). */
.sec-bar { position: sticky; bottom: var(--kb, 0px); z-index: 5; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2);
  margin: var(--sp-4) calc(-1 * var(--sp-5)) 0; padding: var(--sp-3) var(--sp-5); background: var(--surface); border-top: 1px solid var(--line); }
body.has-tabs .sec-bar { bottom: max(var(--kb, 0px), calc(var(--tab-h) + env(safe-area-inset-bottom))); }
html:has(.sec-bar) { scroll-padding-bottom: calc(var(--tab-h) + env(safe-area-inset-bottom) + 84px + var(--kb, 0px)); }
@media (min-width: 960px) { body.has-tabs .sec-bar { bottom: var(--kb, 0px); } }
/* The head start (profile.js, 0027): a member's earlier answers, offered once above the sections, set apart as the
   one thing to do there. */
.head-start { border: 2px solid var(--accent); margin-bottom: var(--sp-4); }
.head-start h2 { margin: 0; }
.head-start > .hint { margin: var(--sp-2) 0 0; }
.head-start > .status:empty { min-height: 0; margin: 0; }

/* Profile growth (J6, J7, J8) */
/* min-width: 0 so a long link or a member's one-word note wraps instead of widening a phone's page. */
.dash > *, .invite-card, .perks-card, .share-prompt, .invite-who { min-width: 0; overflow-wrap: anywhere; }
[data-growth="meter-box"]:not(:empty) { margin-bottom: 14px; }
.meter-bar { height: 10px; background: var(--tint); border: 1px solid var(--line); border-radius: var(--r-pill); overflow: hidden; margin: var(--sp-1) 0 10px; }
.meter-bar span { display: block; height: 100%; background: var(--ok-graphic); border-radius: var(--r-pill); }
.meter-steps { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: grid; gap: var(--sp-2); }
.meter-steps li { display: grid; gap: 1px; min-width: 0; }
.invite-card { display: grid; gap: var(--sp-2); align-content: start; }
.invite-card h2, .invite-card p { margin: 0; }
.invite-card label { margin: var(--sp-1) 0 0; }
.invite-card textarea { min-height: 72px; }
/* The link takes the card's width when Copy can't sit beside 240px of it (it showed "https://remote"). */
.copyrow { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.copyrow .copy-field { flex: 1 1 240px; min-width: 0; }
.copy-field { font-size: var(--fs-14); }
.share-apps .btn { flex: 1 1 auto; }
.totals { font-size: var(--fs-14); }
.toggle-row .hint { margin: 0 0 0 28px; }
.founding { display: grid; gap: 6px; justify-items: start; padding-top: var(--sp-2); border-top: 1px solid var(--line); }
/* The founding label's words are Lachlan's, up to 80 characters: they wrap rather than run off a phone. */
.founding .badge, .invite-who .badge { white-space: normal; max-width: 100%; }
.share-prompt .actions { margin-top: var(--sp-2); }
.perks-card h3 { margin: 14px 0 6px; font-size: var(--fs-14); color: var(--ink-2); }
.perk-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.perk-list li { display: grid; gap: 2px; justify-items: start; min-width: 0; }
.perk-list .btn { margin-top: var(--sp-1); }
.invite-who { margin: var(--sp-3) 0 var(--sp-4); }
.gets { margin: 6px 0 0; padding-left: var(--sp-5); }
.gets li + li { margin-top: var(--sp-1); }

/* Connections, notifications, reports and messages (social lane, wave 3b) */
.connect-panel { margin-top: 14px; min-width: 0; }
.connect-panel h3 { margin-top: 0; }
.connect-panel p { margin: 0 0 var(--sp-2); }
.safety { margin-top: 14px; min-width: 0; font-size: var(--fs-14); }
.safety summary, .disclose > summary { display: flex; align-items: center; min-height: 44px; color: var(--ink-2); cursor: pointer; }
.safety select, .safety textarea { font-size: var(--fs-16); }
.block-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }
.block-row > span { min-width: 0; overflow-wrap: anywhere; }
.copied p { margin: 0 0 var(--sp-1); overflow-wrap: anywhere; }
:where(.conn-list, .notifs, .convos) { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
:where(.conn-list, .notifs, .convos) > * { min-width: 0; }
.conn-who { display: flex; align-items: flex-start; gap: var(--sp-3); min-width: 0; }
.conn-main { flex: 1; min-width: 0; }
.conn-main h3 { margin: 0; font-size: var(--fs-16); overflow-wrap: anywhere; }
/* A name that opens the member's page (People on) reads as the name, underlined on hover. */
:is(.conn-main h3, .thread-who h1) a { color: inherit; text-decoration: none; }
:is(.conn-main h3, .thread-who h1) a:hover { text-decoration: underline; }
.conn-main p { margin: 2px 0 0; overflow-wrap: anywhere; }
:is(.conn, .notif-act) .quote { margin-top: var(--sp-2); padding-left: var(--sp-3); border-left: 3px solid var(--line-strong); color: var(--ink); }
.conn .actions { margin-top: var(--sp-3); }
/* The item a link opened: a heavier border and a bar down its side, not colour alone. */
.conn.is-focus { border-color: var(--accent); box-shadow: inset 4px 0 0 var(--accent), var(--sh-1); }
.conn-panel .empty-inline { margin-top: var(--sp-2); }
/* An empty status box takes no room (the gap above Report or block, M5). */
:is(.conn, .notif-act, .compose) .status:empty { min-height: 0; margin: 0; }
.intro-cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); }
.intro-cta p { flex: 1 1 16rem; margin: 0; }
/* The introduction picker (introduce.js): people as rows, the chosen ones tinted. */
.picker-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.picker-row, .picker-person { display: flex; align-items: center; gap: var(--sp-3); width: 100%; min-height: 56px; padding: var(--sp-2); border-radius: var(--r-md); text-align: left; }
.picker-row { border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
.picker-row:hover { background: var(--hover); }
.picker-person { background: var(--tint); flex-wrap: wrap; }
.picker-person .btn { margin-left: auto; flex: none; }
/* The name asks for 10rem before the button shares its line, so on a phone the button wraps under it. */
.picker-who { display: grid; flex: 1 1 10rem; min-width: 0; }
.picker-who .small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-label { margin: var(--sp-4) 0 var(--sp-2); font-weight: 600; }
.picker-open input[type=search] { margin-bottom: var(--sp-2); }
/* After an accept (introduce.js openMeet): the next night's line sits with its link, whose 44 px box already
   puts 12 px above its words. */
.meet-night p { margin: 0; }
.city-add { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-2); }
.city-add > div { flex: 1 1 12rem; min-width: 0; }
.notif > a, .convo > a { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--sp-3); min-height: 64px;
  padding: var(--sp-3); border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface); color: var(--ink); text-decoration: none; }
.notif > a:hover, .convo > a:hover { background: var(--hover); }
.notif.is-new > a, .convo.unread > a { border-color: var(--accent); background: var(--accent-soft); }
.convo-who b { font-weight: 600; }
.notif.is-new .notif-main, .convo.unread b { font-weight: 700; }
/* A row answered in place: the card holds the link and, under it, Accept and Not now. */
.notif.has-act { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.notif.has-act.is-new { border-color: var(--accent); background: var(--accent-soft); }
.notif.has-act > a { border: 0; background: none; }
.notif-act { padding: 0 var(--sp-3) var(--sp-3); }
.notif-av { position: relative; display: inline-grid; }
.notif-kind { position: absolute; right: -4px; bottom: -4px; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px var(--line-strong); }
.notif-main, .convo-who { min-width: 0; overflow-wrap: anywhere; }
.convo-who { display: grid; gap: 2px; }
.convo-who .small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-time { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); font-size: var(--fs-12); white-space: nowrap; }
.row-time .dot { position: static; box-shadow: none; }
.thread-head { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.thread-who { min-width: 0; }
.thread-who h1 { margin: 0; font-size: var(--fs-24); overflow-wrap: anywhere; }
.thread-who p { margin: 2px 0 0; }
.thread { list-style: none; margin: var(--sp-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.msg { max-width: 85%; min-width: 0; padding: 10px 14px; border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--surface); }
.msg.mine { align-self: flex-end; background: var(--accent-soft); border-color: transparent; }
.msg.theirs { align-self: flex-start; }
.msg p { margin: 0 0 var(--sp-1); white-space: pre-wrap; overflow-wrap: anywhere; }
.linkish { font: inherit; background: none; border: 0; padding: 0; color: inherit; text-decoration: underline; cursor: pointer; min-height: 24px; }
/* A message's More (three dots) sits in its small line: a 44 px target that reaches 10 px above and below the line
   without making the bubble taller. Its menu (Report) opens under the line. */
.msg-meta { display: flex; align-items: center; gap: var(--sp-1); }
.msg-more { margin: -10px -8px -10px auto; color: var(--ink-2); }
.msg-menu:empty { display: none; }
/* The box to write in, docked at the foot of the screen (no tabs on a conversation), Send beside it. */
.thread-foot { position: sticky; bottom: 0; z-index: 1; margin: var(--sp-4) calc(-1 * var(--gutter)) 0; padding: var(--sp-2) var(--gutter) calc(var(--sp-2) + env(safe-area-inset-bottom));
  background: var(--bg); border-top: 1px solid var(--line); }
.compose { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: var(--sp-2); }
.compose :is(.status, .hint) { grid-column: 1 / -1; margin: 0; }
.compose textarea { font-size: var(--fs-16); min-height: 44px; max-height: 160px; resize: none; }
/* Phones: 44 px buttons on these screens (.btn.small is 36 px elsewhere). The hint stays read out. */
@media (max-width: 959px) {
  .compose .hint { display: none; }
  :is(.conn-page, .thread-page, .notifs, .picker) .btn.small { min-height: 44px; }
  /* The organisers' page (organisers.js): its numbers line, and every view under its picker, safety.js's reports among them. */
  :is(.stats-line, .org-views ~ div) .btn.small { min-height: 44px; }
}
.report-msg { margin-top: var(--sp-4); }

/* Rooms, scan to connect, going and teams */
.room-card { display: grid; gap: 6px; text-decoration: none; color: var(--ink); min-width: 0; }
.room-card h2 { margin: 0; overflow-wrap: anywhere; }
.door { text-align: center; min-width: 0; }
.door-code { font: 800 var(--fs-60)/1 var(--font-display); letter-spacing: .06em; margin: var(--sp-3) 0; color: var(--accent); font-variant-numeric: tabular-nums; white-space: nowrap; }
.scan-code { font-size: var(--fs-36); }
.door-qr { display: flex; justify-content: center; }
.door-qr svg.qr { width: min(240px, 100%); height: auto; border-radius: var(--r-sm); }
.scan-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.scan-grid > * { min-width: 0; }
.scan-video { width: 100%; max-width: 320px; border-radius: var(--r-md); margin-top: 10px; }
.going, .bring, .team-panel { margin-top: var(--sp-3); min-width: 0; }
.bring summary { color: var(--ink-2); }
.bring textarea { font-size: var(--fs-16); }

/* Home addressed to the member, vouches and the weekly digest (public/home.js). One column on phones, in the
   order of what's most useful; from 1100 px a 300 px side column for the profile, the digest and the rest
   (design-system.md). Rows, never a feed, and no counts. */
.home { max-width: calc(var(--col-w) + var(--rail-w) + var(--sp-10)); margin-inline: auto; min-width: 0; }
.home-grid { display: grid; gap: 0 var(--sp-10); }
.home-grid > *, .home-rail > * { min-width: 0; }
@media (min-width: 1100px) { .home-grid { grid-template-columns: minmax(0, 1fr) var(--rail-w); align-items: start; } }
.home-sec, .home-rail > .card, .home .empty { margin-top: var(--sp-6); }
.home section > .card-head { margin: 0 0 var(--sp-3); }
.home-row, .home-event { display: flex; gap: var(--sp-3); padding: var(--sp-3) 0; min-width: 0; }
.home-row-main { flex: 1; min-width: 0; }
.home-row-main p { margin: 0; overflow-wrap: anywhere; }
.home-row-main .home-quote, .home-row-main .home-reason, .home-row-main .hint { margin-top: 6px; }
.home-row-title { font-weight: 600; line-height: 1.3; }
.home-row-sub { color: var(--ink-2); font-size: var(--fs-14); line-height: 1.4; }
.home-row-line, .home-quote { font-size: var(--fs-14); line-height: 1.45; }
.home-row-main .btn-row { margin-top: var(--sp-2); }
.home-row-main .status:empty { min-height: 0; margin: 0; }
.home-event-title { margin: 0; overflow-wrap: anywhere; }
/* The highlighter, the one bold device: only on why two members would meet, with the overlap glyph. */
.home-reason { display: flex; gap: 6px; align-items: flex-start; font-size: var(--fs-14); line-height: 1.45; }
.home-reason mark { color: inherit; padding: 0 .14em; margin: 0 -.14em; background: linear-gradient(to bottom, transparent var(--hl-from), var(--hl-band) var(--hl-from), var(--hl-band) var(--hl-to), transparent var(--hl-to)); -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.glyph { flex: none; width: 20px; height: 16px; margin-top: 2px; }
.glyph .g-lens { fill: var(--hl-glyph); }
.glyph .g-ring { fill: none; stroke: var(--ink-2); stroke-width: 1.4; }
.home-date { display: grid; place-items: center; align-content: center; flex: none; width: 52px; height: 56px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); line-height: 1; }
.home-date b { font: 800 var(--fs-20)/1 var(--font-display); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.home-date span { margin-top: 3px; color: var(--ink-2); font-size: var(--fs-12); font-weight: 600; }
.home-night { padding-block: var(--sp-1); }
/* Pressed shows a tick as well as its colour. */
.home-toggle[aria-pressed="true"] { background: var(--ok-soft); color: var(--ok); border-color: transparent; }
.home-foot { margin: var(--sp-2) 0 0 var(--sp-1); color: var(--ink-2); font-size: var(--fs-14); }
.home-vouch { margin-top: var(--sp-3); min-width: 0; }
.home-vouch p { margin: var(--sp-2) 0 0; }
/* Waiting for you: three rows, then Show the rest (M8). A hidden row stays hidden whatever .home-row sets. */
.home-row[hidden] { display: none; }
.home-more { margin-top: var(--sp-3); width: 100%; }
.home-next { display: grid; gap: var(--sp-3); margin-top: var(--sp-2); min-width: 0; border-radius: var(--r-sm); }
.home-vouch-offer p { margin: 0 0 var(--sp-2); }
/* Answers in a row are 44 px on phones (the networking audit: .btn.small is 36 px). */
@media (max-width: 767px) { .home .btn.small, .take-asks .btn, .outcome .chip, .people-page .btn.small { min-height: 44px; } }
/* "Let members ask to connect?" (asks.js) and "Did anything come of it?" (outcome.js). */
.take-asks { margin-top: var(--sp-6); }
.take-asks h2 { margin-bottom: var(--sp-2); font-size: var(--fs-18); }
.take-asks p { margin: 0 0 var(--sp-3); }
.take-asks .fset { margin-bottom: var(--sp-3); }
.take-asks-act { gap: var(--sp-2); }
.take-asks .status:empty { min-height: 0; margin: 0; }
.outcome { min-width: 0; }
.outcome > p { margin: 0 0 var(--sp-2); font-weight: 600; }
.outcome .chips { gap: 6px; }
.outcome .status:empty { min-height: 0; margin: 0; }
/* ------------------------------------------------------------------ 7. First run and events (public/firstrun.js) */
/* Events: rows with a date tile, one card for the next night. Never a headcount. */
.datetile { display: grid; place-items: center; align-content: center; width: 52px; height: 56px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); line-height: 1; }
.datetile b { font: 800 var(--fs-20)/1 var(--font-display); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.datetile span { margin-top: 3px; color: var(--ink-2); font-size: var(--fs-12); font-weight: 600; }
.events { list-style: none; margin: 0; padding: 0; }
.event, .ecard { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--sp-3); align-items: start; }
.event { padding: var(--sp-4) 0; }
.event + .event { border-top: 1px solid var(--line); }
.ecard { padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--sh-1); }
.event-title { margin: 0; font: 700 var(--fs-18)/1.2 var(--font-display); letter-spacing: -.012em; overflow-wrap: anywhere; }
.event-title a { color: var(--ink); }
.event-when { margin: 4px 0 0; color: var(--ink-2); font-size: var(--fs-14); }
:is(.event, .ecard) :is(.btn-row, .going, .bring) { margin-top: var(--sp-3); }
.ecard-foot { grid-column: 1 / -1; min-width: 0; }
.card > .ecard { padding: 0; border: 0; background: none; box-shadow: none; }
.events.card { padding: 0 var(--sp-5); }
.btn-toggle[aria-pressed="true"] { background: var(--ok-soft); color: var(--ok); }
.btn-toggle[aria-pressed="false"] > .i { display: none; }
/* People handed over, and cities */
.fr-people { list-style: none; margin: 0; padding: 0; }
.fr-people > li + li { border-top: 1px solid var(--line); }
.fr-person, .fr-pick { display: flex; align-items: center; gap: var(--sp-3); width: 100%; min-height: 64px; padding: var(--sp-2) 0; border: 0; background: none; color: var(--ink); font: inherit; text-align: left; }
button.fr-person { cursor: pointer; }
button.fr-person:hover b { text-decoration: underline; }
.fr-pick > span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.fr-who { display: grid; min-width: 0; }
.fr-who b { font-weight: 600; overflow-wrap: anywhere; }
.fr-who span { color: var(--ink-2); font-size: var(--fs-14); overflow-wrap: anywhere; }
.fr-who .reason, .fr-who .reason span { color: var(--ink); }
.fr-add { display: flex; flex-wrap: wrap; align-items: end; gap: var(--sp-2); margin-top: var(--sp-3); }
.fr-add > div { flex: 1 1 200px; min-width: 0; }
/* Rooms and check-in, in the same dated rows as Events. A room's row opens from anywhere on it: its
   title's link reaches over the row, and the row holds nothing else to press. */
.room-row { position: relative; }
.room-row .event-title a { color: var(--ink); text-decoration: none; }
.room-row .event-title a::after { content: ""; position: absolute; inset: 0; }
.room-row:hover .event-title a { text-decoration: underline; }
.room-row .tags { margin-top: var(--sp-2); }
.room-head { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--sp-3); align-items: start; }
.room-head h1 { margin: 0 0 var(--sp-2); overflow-wrap: anywhere; }
.room-body { margin-top: var(--sp-4); }
.room-sec { margin-top: var(--sp-6); }
.card > .tags + h3 { margin-top: var(--sp-2); }
/* ------------------------------------------------------------------ Sign-in, Account and the profile editor (wave 3b) */
/* The emailed code: one field drawn large (prototype signin-code.html), the resend, and what to do when it doesn't come.
   While the code step shows, the screen's other ways in step aside; its help offers Telegram instead. */
.signin.on-code > :not(.email-code) { display: none; }
input.otp { min-height: 64px; padding-left: .5em; font: 800 var(--fs-30)/1 var(--font-display); letter-spacing: .5em; text-align: center; font-variant-numeric: tabular-nums; }
input.otp::placeholder { font: 400 var(--fs-16)/1 var(--font-ui); letter-spacing: normal; }
.btn.block.resend { margin-top: var(--sp-2); }
.code-help { margin-top: var(--sp-6); padding-top: var(--sp-5); border-top: 1px solid var(--line); }
.code-help h2 { margin: 0 0 var(--sp-2); font: 600 var(--fs-16)/1.4 var(--font-ui); letter-spacing: 0; }
.code-help p { margin: 0 0 var(--sp-3); color: var(--ink-2); font-size: var(--fs-14); }
.email-code form > .status:first-child { margin: 0 0 var(--sp-4); }
/* Account (prototype account.html): the ways to sign in and your data as grouped rows. A row that's a button
   reads as a row; Leave is the one in the error colour, and its sheet's buttons share the foot. */
.account-page > .group-title:first-of-type { margin-top: var(--sp-4); }
.group-foot { margin: var(--sp-2) 0 var(--sp-6) var(--sp-1); color: var(--ink-2); font-size: var(--fs-14); }
.signin-methods .set, .google-row, .whatsapp-row { flex-wrap: wrap; }
.google-row, .whatsapp-row { display: flex; align-items: center; gap: var(--sp-3); min-height: 56px; padding: var(--sp-3) 0; }
/* While a row reads its state: a placeholder the height of the line it holds, so nothing jumps when it arrives.
   The group's own placeholder, until the member's ways to sign in are known, sits as a row would. */
.set-main .set-wait { color: var(--ink-2); }
.signin-methods > li > .sk-wrap { padding: var(--sp-4) 0; }
.set-more { flex: 1 0 100%; min-width: 0; }
.set-more > p { margin: 0 0 var(--sp-2); }
.set-more > .btn.block:first-child, .set-more > .method:first-child, .set-more > .tg-panel { margin-top: 0; }
button.set { width: 100%; margin: 0; padding-inline: 0; border: 0; background: none; color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
button.set:hover .set-main b { text-decoration: underline; }
.set-danger .set-main b { color: var(--err); }
.leave-row { margin-top: var(--sp-2); }
.leave-list { margin: 0 0 var(--sp-3); padding-left: var(--sp-5); }
.leave-list li + li { margin-top: var(--sp-2); }
/* The profile editor's pair (J6): what they're looking for, then what they can help with, both optional. */
.pair-label { margin: var(--sp-4) 0 6px; font-weight: 600; font-size: var(--fs-14); }
.pair-vis { max-width: 240px; margin-top: 6px; }
/* The invite card on Home and the invite page, /i/<code> (J7, J8). The card: the link first, the apps as 44 px
   buttons in a grid, and the invite page's settings as rows. The page: the inviter's face and tags, what members
   get with an icon each, one Join button, and the next event with its day as a tile. */
.invite-card-head { display: flex; gap: var(--sp-3); align-items: flex-start; margin-bottom: var(--sp-2); }
.invite-card-head > div { min-width: 0; }
.invite-card .invite-label { margin: var(--sp-3) 0 0; font: 600 var(--fs-14)/1.4 var(--font-ui); letter-spacing: 0; }
.copyrow .btn { white-space: nowrap; }
.share-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: var(--sp-2); }
.share-grid .btn { min-width: 0; padding-inline: var(--sp-3); }
.invite-card .totals { display: flex; gap: var(--sp-2); align-items: flex-start; margin-top: var(--sp-2); }
.totals .i { margin-top: 3px; color: var(--ink-2); }
.invite-card .invite-set { list-style: none; margin: 0; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; }
.invite-set > li { padding: var(--sp-2) 0; }
.invite-set > .invite-set-link { padding: 0; }
.invite-set .check { min-height: 44px; align-items: center; margin: 0; }
.invite-set .toggle-row .hint { margin: 0 0 var(--sp-1) 28px; }
.invite-set > .founding { padding: var(--sp-3) 0 var(--sp-2); }
.invite-set > .founding:first-child { border-top: 0; }
.invite-set a.set .i { color: var(--ink-2); }
.invite-page { display: grid; gap: var(--sp-4); }
.invite-page > * { min-width: 0; overflow-wrap: anywhere; }
.invite-page .card + .card { margin-top: 0; }
.invite-head { display: grid; justify-items: center; gap: var(--sp-2); text-align: center; }
.invite-head h1 { margin: var(--sp-2) 0 0; text-wrap: balance; }
.invite-head p { margin: 0; }
.invite-mark { display: grid; place-items: center; width: 64px; height: 64px; border-radius: var(--r-lg); background: var(--accent-soft); color: var(--accent-soft-ink); }
.invite-mark .i { width: 32px; height: 32px; }
.invite-biz b { font-weight: 600; }
.invite-line { color: var(--ink-2); }
.invite-tags { justify-content: center; }
.invite-tags .badge, .invite-ask .badge { display: inline-flex; align-items: center; gap: 4px; white-space: normal; max-width: 100%; }
.invite-asks { display: grid; gap: var(--sp-3); margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.invite-ask h2 { margin: 0 0 var(--sp-1); font: 600 var(--fs-14)/1.4 var(--font-ui); letter-spacing: 0; color: var(--ink-2); }
.invite-ask p { margin: 0; }
.invite .invite-lead { margin: var(--sp-5) 0 0; }
.invite-note { margin: var(--sp-2) 0 0; text-align: center; }
.invite-gets-box h2, .invite-event h2 { margin: 0 0 var(--sp-3); font-size: var(--fs-18); }
.invite-gets { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.invite-gets li { display: flex; gap: var(--sp-3); align-items: center; }
.invite-gets .i { flex: none; box-sizing: content-box; padding: 6px; border-radius: var(--r-sm); background: var(--tint); color: var(--ink); }
.invite-event-row { display: flex; gap: var(--sp-3); align-items: flex-start; }
.invite-date { display: grid; place-items: center; align-content: center; flex: none; width: 56px; height: 56px; border-radius: var(--r-md); background: var(--tint); line-height: 1.1; }
.invite-date b { font: 800 var(--fs-20)/1 var(--font-display); }
.invite-date span { font-size: var(--fs-12); color: var(--ink-2); }
.invite-event-main { flex: 1; min-width: 0; }
.invite-event-main h3 { margin: 0 0 2px; font-size: var(--fs-16); }
.invite-event-main p { margin: 0; }
.invite-where { display: flex; gap: 4px; align-items: center; }
.invite-event .facepile { margin-top: var(--sp-2); }
.invite-event .linkrow { margin: var(--sp-2) 0 0; }
.invite-signin { justify-content: center; align-items: center; gap: 4px; margin: 0; }
