/* Regdel — the whole stylesheet.
 *
 * Three things it has to get right, from the stories:
 *
 *   - **Liquid glass.** Translucent panels over a soft gradient, with a blur behind them. The blur is
 *     the expensive part, so it is applied to a handful of surfaces rather than to every card in a
 *     feed that may be hundreds long — a phone scrolling a blurred list drops frames, and "fluent"
 *     is also a requirement.
 *   - **Dark, light, or the device's choice.** The device's choice is the default and needs no
 *     JavaScript: `prefers-color-scheme` decides. An explicit preference arrives as `data-theme` on
 *     `<html>` and overrides it in both directions — which is why the light block is written out
 *     rather than left to "whatever the defaults were".
 *   - **Usable on a phone, a tablet and a desktop.** Written narrow-first; the wider layouts are
 *     additions, not corrections.
 */

/* ---------------------------------------------------------------------------------------------
   Palette
   --------------------------------------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  --bg: #eef1f6;
  --bg-glow-a: #c7d6ff;
  --bg-glow-b: #ffd9ec;
  --panel: rgba(255, 255, 255, 0.62);
  --panel-solid: #ffffff;
  --panel-edge: rgba(255, 255, 255, 0.75);
  --ink: #1b2030;
  --muted: #5d6577;
  --line: rgba(27, 32, 48, 0.12);
  --accent: #3b5bdb;
  --accent-ink: #ffffff;
  --danger: #c0392b;
  --shadow: 0 1px 2px rgba(16, 21, 36, 0.05), 0 8px 24px rgba(16, 21, 36, 0.07);
  --radius: 1rem;
  --radius-sm: 0.6rem;
  --blur: 18px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f1219;
    --bg-glow-a: #1d2c58;
    --bg-glow-b: #3a1f42;
    --panel: rgba(30, 35, 48, 0.58);
    --panel-solid: #1c212c;
    --panel-edge: rgba(255, 255, 255, 0.08);
    --ink: #e8eaf0;
    --muted: #9aa3b6;
    --line: rgba(255, 255, 255, 0.1);
    --accent: #7aa2f7;
    --accent-ink: #0f1219;
    --danger: #ff8a80;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 30px rgba(0, 0, 0, 0.35);
  }
}

/* An explicit preference wins over the device, in *both* directions: a member who chose light on a
   phone set to dark must get light. That is why these repeat the values rather than only overriding
   the direction the media query does not already cover. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #eef1f6;
  --bg-glow-a: #c7d6ff;
  --bg-glow-b: #ffd9ec;
  --panel: rgba(255, 255, 255, 0.62);
  --panel-solid: #ffffff;
  --panel-edge: rgba(255, 255, 255, 0.75);
  --ink: #1b2030;
  --muted: #5d6577;
  --line: rgba(27, 32, 48, 0.12);
  --accent: #3b5bdb;
  --accent-ink: #ffffff;
  --danger: #c0392b;
  --shadow: 0 1px 2px rgba(16, 21, 36, 0.05), 0 8px 24px rgba(16, 21, 36, 0.07);
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f1219;
  --bg-glow-a: #1d2c58;
  --bg-glow-b: #3a1f42;
  --panel: rgba(30, 35, 48, 0.58);
  --panel-solid: #1c212c;
  --panel-edge: rgba(255, 255, 255, 0.08);
  --ink: #e8eaf0;
  --muted: #9aa3b6;
  --line: rgba(255, 255, 255, 0.1);
  --accent: #7aa2f7;
  --accent-ink: #0f1219;
  --danger: #ff8a80;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 30px rgba(0, 0, 0, 0.35);
}

/* ---------------------------------------------------------------------------------------------
   Page
   --------------------------------------------------------------------------------------------- */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  justify-content: center;
  /* `env(safe-area-inset-*)` is what keeps content clear of an iPhone's notch and home indicator once
     the application is installed and runs without browser chrome. */
  padding: max(1rem, env(safe-area-inset-top)) max(1rem, env(safe-area-inset-right))
           max(1rem, env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* The light the glass refracts. Fixed rather than scrolled, so panels move over a still background
   instead of dragging it with them. */
body::before {
  content: "";
  position: fixed;
  inset: -20vmax;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38vmax 38vmax at 12% 8%, var(--bg-glow-a), transparent 65%),
    radial-gradient(34vmax 34vmax at 88% 92%, var(--bg-glow-b), transparent 62%);
  opacity: 0.9;
}

/* ---------------------------------------------------------------------------------------------
   The glass surface itself
   --------------------------------------------------------------------------------------------- */

.glass {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(160%);
  backdrop-filter: blur(var(--blur)) saturate(160%);
}

/* Firefox before 103 and every browser with the feature switched off get a solid panel rather than a
   transparent one — without this the text sits on the gradient and stops being readable. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: var(--panel-solid); }
}

/* ---------------------------------------------------------------------------------------------
   Controls
   --------------------------------------------------------------------------------------------- */

/* One focus ring, on everything, and never removed. `:focus-visible` rather than `:focus` so a mouse
   click does not leave a ring behind while a Tab press does. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

input, select, textarea {
  width: 100%;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-solid);
  color: inherit;
  font: inherit;
  /* Under 16px, iOS Safari zooms the page on focus and never zooms back. */
  font-size: max(1rem, 16px);
}

textarea { resize: vertical; }

button {
  font: inherit;
  cursor: pointer;
  /* The comfortable-target size from the WCAG guidance; below it, buttons are hard to hit on a phone
     and impossible for anyone with a tremor. */
  min-height: 2.75rem;
}

button.primary, button[type="submit"] {
  padding: 0.7rem 1.1rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  box-shadow: var(--shadow);
  transition: transform 120ms ease, filter 120ms ease;
}

button.primary:hover, button[type="submit"]:hover { filter: brightness(1.08); }
button.primary:active, button[type="submit"]:active { transform: translateY(1px); }
button:disabled { opacity: 0.5; cursor: not-allowed; }

.linkish {
  min-height: 2.75rem;
  padding: 0.35rem 0.25rem;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
}

.linkish:hover { text-decoration: underline; }

a { color: var(--accent); }

/* ---------------------------------------------------------------------------------------------
   Sign-in
   --------------------------------------------------------------------------------------------- */

.signin {
  align-self: center;
  width: 100%;
  max-width: 23rem;
  margin: auto;
  padding: 2rem;
}

.signin-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

.signin-logo { width: 2.5rem; height: 2.5rem; }
.signin-brand h1 { margin: 0; font-size: 1.25rem; font-weight: 600; }

.signin-form { display: grid; gap: 1rem; }
.signin-form label { display: grid; gap: 0.35rem; }
.signin-form span { font-size: 0.8125rem; color: var(--muted); }

.signin-note, .signin-support {
  margin: 0.75rem 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.signin-error {
  margin: 0;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  background: color-mix(in oklab, var(--danger) 14%, transparent);
  color: var(--danger);
  font-size: 0.875rem;
}

.loading { min-height: 4rem; }

/* ---------------------------------------------------------------------------------------------
   The application shell
   --------------------------------------------------------------------------------------------- */

.app { width: 100%; max-width: 38rem; }

.app-bar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: -0.5rem -0.5rem 1rem;
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(160%);
  backdrop-filter: blur(var(--blur)) saturate(160%);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .app-bar { background: var(--panel-solid); }
}

.app-bar h1 { margin: 0; font-size: 1.0625rem; font-weight: 600; }

/* The title side and the actions side, each able to wrap. A community bar carries back, mark, name,
   manage, mute and leave; on a narrow screen those do not fit on one line, and without wrapping the
   name is what gets crushed. */
.app-bar { flex-wrap: wrap; }

.app-bar-title { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }

/* The name yields before anything else does — an ellipsis on a long community name is a smaller
   loss than a squeezed row of controls. */
.app-bar-title h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.app-bar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; }

h2 { font-size: 1rem; font-weight: 600; color: var(--muted); margin: 1.25rem 0 0.75rem; }

/* ---------------------------------------------------------------------------------------------
   Communities
   --------------------------------------------------------------------------------------------- */

.community-list { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: 0.75rem; }

.community {
  display: grid;
  /* The mark, the name, then the role and the count pushed to the end. */
  grid-template-columns: auto 1fr auto auto;
  gap: 0.35rem 0.75rem;
  align-items: baseline;
  padding: 1rem 1.1rem;
}

.community-name { font-weight: 600; }
.community-role, .community-count { font-size: 0.75rem; color: var(--muted); }
.community-role { text-transform: lowercase; }

.community-description {
  /* From the name onwards, so it lines up under the text rather than under the mark. */
  grid-column: 2 / -1;
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted);
}

.community.clickable { cursor: pointer; transition: transform 140ms ease, border-color 140ms ease; }
.community.clickable:hover { transform: translateY(-1px); border-color: var(--accent); }

/* ---------------------------------------------------------------------------------------------
   The feed
   --------------------------------------------------------------------------------------------- */

.composer { display: grid; gap: 0.6rem; margin: 0 0 1.25rem; }

.composer textarea {
  border-radius: var(--radius);
  background: var(--panel-solid);
}

.composer-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; }
.counter { font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.counter.over { color: var(--danger); font-weight: 600; }

.feed { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }

/* Plain panels, not glass: a feed is unbounded, and a hundred blurred surfaces is what turns
   scrolling into a slideshow on a mid-range phone. */
.post, .post-full, .comment, .share-content, .settings {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-solid);
  box-shadow: var(--shadow);
}

.post {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.85rem;
  padding: 1rem 1.1rem;
}

.post-avatar {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, var(--accent), color-mix(in oklab, var(--accent) 55%, #ff8ab8));
  color: var(--accent-ink);
  font-weight: 700;
}

.post-body { min-width: 0; }

.post-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.post-author { font-weight: 600; }
.post-when, .post-edited { font-size: 0.75rem; color: var(--muted); }
.post-edited::before { content: "·"; margin-right: 0.35rem; }

.post-text { cursor: pointer; overflow-wrap: anywhere; }
.post-text .md { margin: 0.35rem 0; }

.post-text code {
  padding: 0.1rem 0.3rem;
  border-radius: 0.25rem;
  background: color-mix(in oklab, var(--ink) 8%, transparent);
  font-size: 0.9em;
}

.post-more { color: var(--muted); }

.post-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; margin-top: 0.6rem; }

.feelings { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.feeling {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-height: 2rem;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 0.75rem;
  transition: border-color 120ms ease, color 120ms ease;
}

.feeling:hover { border-color: var(--accent); }
.feeling.chosen { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.feeling-count { font-variant-numeric: tabular-nums; }

.more {
  width: 100%;
  margin-top: 0.75rem;
  padding: 0.7rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
}

.post-full { padding: 1.15rem; }
.post-full .post-text { cursor: auto; }

.comments { list-style: none; margin: 0.75rem 0; padding: 0; display: grid; gap: 0.5rem; }

.comment {
  padding: 0.7rem 0.9rem;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.post-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }

/* ---------------------------------------------------------------------------------------------
   Pictures
   --------------------------------------------------------------------------------------------- */

.attach { display: inline-flex; align-items: center; min-height: 2.75rem; font-size: 0.875rem; color: var(--accent); cursor: pointer; }
.attach input[type="file"] { display: none; }

.attached { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.attached li { position: relative; }

.attached img {
  width: 4.5rem;
  height: 4.5rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
}

.attached .remove {
  position: absolute;
  top: -0.4rem;
  right: -0.4rem;
  width: 1.4rem;
  height: 1.4rem;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
  color: var(--bg);
  line-height: 1;
}

.mosaic {
  position: relative;
  display: grid;
  gap: 2px;
  margin-top: 0.6rem;
  border-radius: var(--radius-sm);
  overflow: hidden;
  cursor: pointer;
}

.mosaic img { width: 100%; height: 100%; object-fit: cover; display: block; }

.mosaic-1 { grid-template-columns: 1fr; max-height: 22rem; }
.mosaic-2 { grid-template-columns: 1fr 1fr; }
.mosaic-2 img { aspect-ratio: 1; }
.mosaic-3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; }
.mosaic-3 img:first-child { grid-row: span 2; height: 100%; }
.mosaic-3 img { aspect-ratio: auto; min-height: 6rem; }
.mosaic-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.mosaic-4 img { aspect-ratio: 1; }

.mosaic-more {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.62);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
}

.gallery { list-style: none; margin: 0.85rem 0 0; padding: 0; display: grid; gap: 0.85rem; }
.gallery img { width: 100%; border-radius: var(--radius-sm); display: block; }
.legend { margin: 0.35rem 0 0; font-size: 0.8125rem; color: var(--muted); }

/* ---------------------------------------------------------------------------------------------
   Public shares
   --------------------------------------------------------------------------------------------- */

.sharing { margin-top: 0.25rem; }

.share-link {
  display: grid;
  gap: 0.5rem;
  padding: 0.85rem;
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
}

.share-link input { font-size: 0.8125rem; }

.share { width: 100%; max-width: 38rem; margin: auto; }
.share-content { padding: 1.4rem; }
.share-gone { text-align: center; padding: 3rem 1rem; }
.share-gone h1 { margin: 0 0 0.5rem; font-size: 1.25rem; }

.share-footer {
  margin: 1rem 0 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
  font-size: 0.75rem;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------------------------
   Settings
   --------------------------------------------------------------------------------------------- */

.settings { display: grid; gap: 1rem; padding: 1.25rem; }
.settings label { display: grid; gap: 0.35rem; }
.settings label > span { font-size: 0.8125rem; color: var(--muted); }

.settings-readonly {
  margin: -0.5rem 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.settings-switch {
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0.25rem 0.75rem;
}

.settings-switch input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  min-height: 0;
  accent-color: var(--accent);
}

.settings-switch > span { grid-column: 2; font-size: 1rem; color: var(--ink); }
.settings-switch small { grid-column: 2; font-size: 0.8125rem; color: var(--muted); }

.settings-saved { margin: 0; font-size: 0.875rem; color: var(--accent); }

.install { margin-top: 1rem; }
.notifications { margin-top: 0.5rem; }

/* The admin's mail panel. A read-only report on what the environment said, so it reads as a
   definition list rather than as a form nobody can submit. */
.mail-panel { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.mail-panel h3 { margin: 0 0 0.75rem; font-size: 0.9375rem; }
.mail-facts { margin: 0 0 1rem; display: grid; gap: 0.35rem; }

.mail-fact {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: 0.75rem;
  align-items: baseline;
  font-size: 0.875rem;
}

.mail-fact dt { color: var(--muted); }
.mail-fact dd { margin: 0; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }

@media (max-width: 30rem) {
  .mail-fact { grid-template-columns: 1fr; gap: 0; }
}

/* Small and to the right in the community bar: a control you want the moment a community is noisy,
   and never before. */
.mute { font-size: 0.8125rem; color: var(--muted); }
.mute:hover { color: var(--accent); }

.install-note {
  margin: 1rem 0 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 0.8125rem;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------------------------
   Wider screens, and people who would rather things held still
   --------------------------------------------------------------------------------------------- */

@media (min-width: 48rem) {
  body { padding: 2rem; }
  .app { max-width: 42rem; }
  .app-bar h1 { font-size: 1.125rem; }
}

@media (min-width: 72rem) {
  .app, .share { max-width: 46rem; }
}

/* Vestibular disorders make the transforms above genuinely unpleasant. Honouring the system setting
   is one rule and costs nothing. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .community.clickable:hover { transform: none; }
}

/* Someone who asked for more contrast is asking for the glass to stop being glass. */
@media (prefers-contrast: more) {
  .glass, .app-bar { background: var(--panel-solid); }
  :root { --line: currentColor; --muted: var(--ink); }
}

/* Inviting somebody in. Given room of its own rather than tucked into a menu: it is the only way a
   person becomes a member, so on an instance with one account it is the most important control on
   the screen. */
.invite { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.invite .signin-form { margin-top: 0.5rem; }

/* Reports, leaving, and the list of public links — speaker and moderator controls that live beside
   the content they act on rather than in a separate administration area. */
.reporting, .reports, .leaving { display: inline-block; }
.leave { color: var(--danger); }
.leave:hover { color: var(--danger); }

.report-list { list-style: none; margin: 0.5rem 0; padding: 0; display: grid; gap: 0.5rem; }

.report {
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--panel-solid);
}

.report-reason { font-weight: 600; }

.shares-panel { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.shares-panel h3 { margin: 0 0 0.5rem; font-size: 0.9375rem; }
.share-list { list-style: none; margin: 0.75rem 0 0; padding: 0; display: grid; gap: 0.5rem; }

.share-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.share-row-text { min-width: 0; }
.share-row-text p { margin: 0; }

/* Administration: the member lists, the filters, and the token panel. Denser than the feed, because
   these are working screens an operator scans rather than reads. */
.filters { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; }
.filters input, .filters select { width: auto; flex: 1 1 10rem; font-size: 0.875rem; }

.member-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }

.member {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 0.75rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-solid);
}

.member-who { display: grid; gap: 0.15rem; min-width: 0; }
.member-who .post-when { font-size: 0.75rem; }

.tokens-panel { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.tokens-panel h3 { margin: 0 0 0.5rem; font-size: 0.9375rem; }

/* Logos: the picker, the preview, and the author mark once it is a picture rather than an initial. */
.logo-picker { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }

.logo-preview {
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--bg);
}

.logo-empty { border-style: dashed; }

/* An avatar that is an image needs the same disc shape the generated one has. */
img.post-avatar { object-fit: cover; background: var(--bg); }

.avatar-button { cursor: pointer; border-radius: 50%; }
.avatar-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.profile-card {
  margin-bottom: 1rem;
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-solid);
  box-shadow: var(--shadow);
}

.profile-head { display: flex; align-items: center; gap: 0.75rem; }
.profile-head > div { display: grid; }

/* The live password requirements. A tick and a class rather than colour alone, so the list reads
   for somebody who cannot tell the two shades apart. */
.password-rules { list-style: none; margin: 0.25rem 0 0; padding: 0; display: grid; gap: 0.1rem; }
.rule { font-size: 0.8125rem; color: var(--muted); display: flex; gap: 0.4rem; align-items: baseline; }
.rule-mark { width: 0.9rem; display: inline-block; text-align: center; }
.rule.met { color: var(--accent); }

/* Scroll-triggered paging leaves a sentinel at the end of the feed; the button inside it stays for
   a first page too short to produce a scroll. */
.feed-end { margin-top: 0.5rem; }

/* The media viewer. Fixed over everything, dark, and with the picture given as much room as the
   viewport allows. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(0, 0, 0, 0.88);
}

.lightbox:focus-visible { outline: none; }
.lightbox-frame { max-width: min(100%, 70rem); display: grid; gap: 0.5rem; justify-items: center; }
.lightbox-frame img { max-width: 100%; max-height: 80dvh; object-fit: contain; border-radius: var(--radius-sm); }
.lightbox-frame .legend { color: #d7dae2; text-align: center; }

.lightbox-bar { display: flex; align-items: center; gap: 1rem; }
.lightbox-bar .post-when { color: #9aa3b6; font-variant-numeric: tabular-nums; }
.lightbox-bar .linkish { color: #cdd6f4; font-size: 1.1rem; }
.lightbox-bar .linkish:disabled { opacity: 0.35; }

.gallery img { cursor: zoom-in; }

/* A community's mark. A rounded square, where a person is a circle — the two must not be mistaken
   for one another at a glance. */
.community-mark {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 0.6rem;
  object-fit: cover;
  background: var(--bg);
  border: 1px solid var(--line);
  grid-row: span 2;
  align-self: center;
}

/* No picture chosen: the initial, on the same footprint, so a list where only some communities have
   one still reads as a list rather than as something half-loaded. */
.community-mark-empty {
  display: grid;
  place-items: center;
  border: 0;
  background: linear-gradient(140deg, var(--accent), color-mix(in oklab, var(--accent) 55%, #8ad1ff));
  color: var(--accent-ink);
  font-weight: 700;
}

/* In the community's own bar it sits beside the title and needs no grid placement. */
.app-bar .community-mark { grid-row: auto; width: 1.9rem; height: 1.9rem; border-radius: 0.45rem; flex: none; }
