/* federado: one stylesheet for the shell and every module.
   Layout: one sticky top bar across the window (a bottom bar too on phones),
   and under it a single reading column, where posts follow one another
   separated by hairlines.
   System fonts only, so the page asks no third party for anything. */

:root {
  /* Neutral greys, with no cast: the teal accent is the only colour (#170,
     in the spirit of Bolhinha's theme). The page a step darker than the
     reading column's panel. */
  --bg: #f2f2f2;
  --surface: #ffffff;
  /* What sits on the column's panel and must stand out from it (fields,
     buttons, cards): the page's grey, set in (#170). */
  --inset: #f2f2f2;
  /* The fill of buttons, fields and cards: the surface on the page, set in
     on the reader's panel (main[data-module] sets it). */
  --control: var(--surface);
  --sunken: #ececec;
  --fg: #161616;
  --muted: #5c5c5c;
  --line: #e2e2e2;
  --accent: #0d7068;
  --accent-fg: #ffffff;
  --accent-soft: #dcefec;
  --danger: #b3261e;
  --danger-soft: #fbe9e7;
  --danger-fg: #ffffff;
  --shadow: 0 10px 30px rgb(23 36 42 / 0.16), 0 2px 6px rgb(23 36 42 / 0.08);
  /* Behind a modal dialog, in the shadow's colour. */
  --scrim: rgb(23 36 42 / 0.35);
  /* A pressed favourite and a pressed bookmark. */
  --star: #b7791f;
  --mark: #c2410c;

  /* Post actions, drawn for federado: masks painted in the text colour. */
  --icon-thread: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M20 11.5a7.5 7.5 0 0 1-11 6.6L4 19.5l1.4-4.6A7.5 7.5 0 1 1 20 11.5z'/></svg>");
  --icon-reply: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9 15L4 10l5-5'/><path d='M4 10h10a6 6 0 0 1 6 6v3'/></svg>");
  --icon-boost: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M17 3l3 3-3 3'/><path d='M4 11V9a3 3 0 0 1 3-3h13'/><path d='M7 21l-3-3 3-3'/><path d='M20 13v2a3 3 0 0 1-3 3H4'/></svg>");
  --icon-star: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 3l2.7 5.6 6.1.8-4.5 4.2 1.1 6.1L12 16.8l-5.4 2.9 1.1-6.1-4.5-4.2 6.1-.8z'/></svg>");
  --icon-star-on: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 3l2.7 5.6 6.1.8-4.5 4.2 1.1 6.1L12 16.8l-5.4 2.9 1.1-6.1-4.5-4.2 6.1-.8z'/></svg>");
  --icon-mark: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 4h12v17l-6-4-6 4z'/></svg>");
  --icon-mark-on: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 4h12v17l-6-4-6 4z'/></svg>");
  --icon-edit: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 20h4L19 9l-4-4L4 16z'/><path d='M13.5 6.5l4 4'/></svg>");
  --icon-delete: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 7h16'/><path d='M10 11v6M14 11v6'/><path d='M9 7V4h6v3'/><path d='M6 7l1 13h10l1-13'/></svg>");

  /* The top bar and the menus. */
  --icon-search: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='6.5'/><path d='M16 16l4 4'/></svg>");
  --icon-bell: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 16V11a6 6 0 0 1 12 0v5l2 2H4z'/><path d='M10 20a2 2 0 0 0 4 0'/></svg>");
  --icon-person: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='8' r='4'/><path d='M4 21c1-5 4-7 8-7s7 2 8 7'/></svg>");
  --icon-sign-out: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14 4h5v16h-5'/><path d='M10 8l-4 4 4 4M6 12h10'/></svg>");
  --icon-plus: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 5v14M5 12h14'/></svg>");
  --icon-apps: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='4' y='4' width='6' height='6' rx='1'/><rect x='14' y='4' width='6' height='6' rx='1'/><rect x='4' y='14' width='6' height='6' rx='1'/><rect x='14' y='14' width='6' height='6' rx='1'/></svg>");
  --icon-eye: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z'/><circle cx='12' cy='12' r='3'/></svg>");
  --icon-settings: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='3'/><path d='M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M4.9 19.1L7 17M17 7l2.1-2.1'/></svg>");
  --icon-warning: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 4L2.5 20h19z'/><path d='M12 10v4.5M12 17.5v.01'/></svg>");
  --icon-globe: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='9'/><path d='M3 12h18'/><path d='M12 3a14 14 0 0 1 0 18a14 14 0 0 1 0-18'/></svg>");
  --icon-lock: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='5' y='11' width='14' height='10' rx='2'/><path d='M8 11V7a4 4 0 0 1 8 0v4'/></svg>");
  --icon-unlock: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='5' y='11' width='14' height='10' rx='2'/><path d='M8 11V7a4 4 0 0 1 7.5-2'/></svg>");
  --icon-media: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='5' width='18' height='14' rx='2'/><circle cx='9' cy='10' r='1.6'/><path d='M21 16l-5-5-9 8'/></svg>");
  --icon-close: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");

  /* The status menu. */
  --icon-more: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'><circle cx='5' cy='12' r='1.8'/><circle cx='12' cy='12' r='1.8'/><circle cx='19' cy='12' r='1.8'/></svg>");
  --icon-link: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M10 14a4.5 4.5 0 0 0 6.4 0l3-3a4.5 4.5 0 0 0-6.4-6.4l-1 1'/><path d='M14 10a4.5 4.5 0 0 0-6.4 0l-3 3a4.5 4.5 0 0 0 6.4 6.4l1-1'/></svg>");
  --icon-share: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 3v12'/><path d='M7 8l5-5 5 5'/><path d='M5 13v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6'/></svg>");
  --icon-at: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='4'/><path d='M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8'/></svg>");
  --icon-mail: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='5' width='18' height='14' rx='2'/><path d='M3 7l9 6 9-6'/></svg>");
  --icon-mute: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 9h4l5-4v14l-5-4H4z'/><path d='M17 9l5 6M22 9l-5 6'/></svg>");
  --icon-block: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='8.5'/><path d='M6 6l12 12'/></svg>");
  --icon-flag: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M5 21V4'/><path d='M5 4h11l-2 4 2 4H5'/></svg>");
  --icon-smile: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='9'/><path d='M8.5 14.5a4.5 4.5 0 0 0 7 0'/><path d='M9 9.5v.01M15 9.5v.01'/></svg>");
  --icon-filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 5h16l-6 7.5V19l-4 1.5v-8z'/></svg>");

  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;

  --step--1: 0.875rem;
  --step-0: 1rem;
  --step-1: 1.25rem;
  --step-2: 1.5rem;

  --radius: 10px;
  --gutter-left: max(16px, env(safe-area-inset-left, 0px));
  --gutter-right: max(16px, env(safe-area-inset-right, 0px));
  --column: 40rem;
  /* The bar's content; its background spans the window. */
  --wide: 64rem;
  --bar-h: 60px;
  --bottom-h: 60px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Near black, the column's panel a step lighter (#170). */
    --bg: #050505;
    --surface: #121212;
    --inset: #050505;
    --sunken: #1c1c1c;
    --fg: #ededed;
    --muted: #9b9b9b;
    --line: #262626;
    --accent: #5fcabb;
    --accent-fg: #06221f;
    --accent-soft: #163631;
    --danger: #f0907f;
    --danger-soft: #3a1d1a;
    --danger-fg: #2a0f0b;
    --shadow: 0 10px 30px rgb(0 0 0 / 0.5), 0 2px 6px rgb(0 0 0 / 0.3);
    --scrim: rgb(0 0 0 / 0.55);
    --star: #f0b84a;
    --mark: #fb8a5a;
    color-scheme: dark;
  }
}

/* Base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.55;
  overflow-wrap: break-word;
}

h1,
h2 {
  line-height: 1.25;
  text-wrap: balance;
  margin: 0;
}

h2 {
  font-size: var(--step-1);
}

p {
  margin: 0;
}

a {
  color: var(--accent);
  text-underline-offset: 0.15em;
}

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

img,
video {
  max-width: 100%;
  height: auto;
}

audio {
  width: 100%;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Controls */

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--control);
  line-height: 1.4;
  white-space: nowrap;
}

button:hover:not(:disabled) {
  border-color: var(--muted);
}

button:disabled {
  cursor: default;
  opacity: 0.55;
}

button[type="submit"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
  padding-inline: 1.1rem;
}

button[type="submit"]:hover:not(:disabled) {
  border-color: var(--fg);
}

input:not([type="file"]),
select,
textarea {
  width: 100%;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--control);
}

input::placeholder,
textarea::placeholder {
  color: var(--muted);
  opacity: 1;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline-offset: 0;
  border-color: var(--accent);
}

textarea {
  min-height: 6.5rem;
  resize: vertical;
}

input[type="file"] {
  max-width: 100%;
  font-size: var(--step--1);
  color: var(--muted);
}

[role="alert"] {
  color: var(--danger);
  font-weight: 500;
}

/* Shell: the top bar, the account menu, the reading area */

/* Heights the module measures (#88), each set on one element alone (the
   root, the composer's form, the emoji grid): not inherited, so a change of
   one restyles nothing else. */
@property --search-row-h {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

@property --compose-head-h {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

@property --compose-toolbar-h {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

/* The emoji grid's, for its scroll padding (#96). */
@property --emoji-heading-h {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

/* An emoji's ring inset, set on the emoji (.emoji-choice, #117): inherited,
   for its name's padding; a value that is not a length falls back to 2px,
   not to an offset of 0 that would put the ring outside the box (#110). */
@property --emoji-ring-inset {
  syntax: "<length>";
  inherits: true;
  initial-value: 2px;
}

/* A control focused at the top of the screen (Shift+Tab, `scrollIntoView`)
   is scrolled below the sticky bar, and the search row while it shows
   (whose height the module keeps, and whose hairline lies 1px below it),
   not left under them (#88, WCAG 2.4.11), with room for its focus ring (a
   2px outline 2px off). */
html {
  scroll-padding-top: calc(var(--bar-h) + env(safe-area-inset-top, 0px) + var(--search-row-h, 0px) + min(var(--search-row-h, 0px), 1px) + 4px);
}

/* Sticky, and with nothing that would make it the containing block of the
   phone's fixed bottom bar inside it: no transform, filter, backdrop-filter,
   contain or will-change here or above. */
.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  padding-top: env(safe-area-inset-top, 0px);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.bar-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: calc(var(--bar-h) - 1px);
  max-width: calc(var(--wide) + 2 * 16px);
  margin: 0 auto;
  padding-left: var(--gutter-left);
  padding-right: var(--gutter-right);
}

/* The reading column, centred under the bar. */
#content {
  /* The room under the last thing on the page: inside the reader's panel
     when there is one (#170). */
  --content-end: 4rem;
  /* The column and its room, in rem: the panel's breakpoint below (42rem)
     follows it whatever the reader's font size (#170). */
  max-width: calc(var(--column) + 2rem);
  margin: 0 auto;
  padding: 0 var(--gutter-right) var(--content-end) var(--gutter-left);
}

/* With the reader's panel, the page is a column the panel fills to the
   window's foot, under whatever the shell shows above it (a notice). */
#content:has(main[data-module]) {
  display: flex;
  flex-direction: column;
  min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top, 0px));
  padding-bottom: 0;
}

#content:focus {
  outline: none;
}

.skip {
  position: absolute;
  top: -10rem;
  left: var(--gutter-left);
  z-index: 30;
  padding: 0.4rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.skip:focus {
  top: 0.5rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-right: 1.5rem;
}

/* Three instances and the links between them. */
.logo {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  background:
    radial-gradient(circle at 25% 30%, var(--accent) 0 18%, transparent 19%),
    radial-gradient(circle at 75% 30%, var(--accent) 0 18%, transparent 19%),
    radial-gradient(circle at 50% 78%, var(--accent) 0 18%, transparent 19%);
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px var(--accent-soft);
}

.brand h1,
h1.brand {
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Once signed in the brand is the way to the timeline (#173). */
.brand .home {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-left: -0.5rem;
  padding: 0.2rem 0.5rem;
  border-color: transparent;
  border-radius: 8px;
  background: transparent;
  line-height: inherit;
}

.brand .home:hover:not(:disabled) {
  border-color: transparent;
  background: var(--sunken);
}

/* The module's part of the bar; `Portal` wraps it in a div of its own. */
.bar-slot {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.bar-slot > div,
.menu-module > div {
  display: contents;
}

.bar-slot .view-name {
  display: none;
}

nav[aria-label="Main"] {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.bar-slot button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  height: 2rem;
  padding: 0 0.75rem;
  border-color: transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font-weight: 650;
}

.bar-slot .icon {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

.bar-slot .search-toggle { --icon: var(--icon-search); margin-left: auto; }
.bar-slot .notifications { --icon: var(--icon-bell); }
.bar-slot .write { --icon: var(--icon-edit); }

/* The laptop's bar: search and the bell are icons, the current place is tinted. */
@media (width > 40rem) {
  .bar-slot button:hover:not(:disabled) {
    border-color: transparent;
    background: var(--sunken);
  }

  .bar-slot .search-toggle,
  .bar-slot .notifications {
    width: 2.75rem;
    padding: 0;
  }

  .bar-slot .notifications[aria-current="page"],
  .bar-slot .search-toggle[aria-expanded="true"],
  .bar-slot .notifications[aria-current="page"]:hover:not(:disabled),
  .bar-slot .search-toggle[aria-expanded="true"]:hover:not(:disabled) {
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 650;
  }

  .bar-slot .write {
    margin-left: 0.5rem;
    padding: 0 1rem;
  }

  .bar-slot .search-toggle .label,
  .bar-slot .notifications .label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* The unread count: an accent pill on the bell, used for nothing else. */
.badge {
  position: absolute;
  top: -0.2rem;
  left: calc(50% + 0.15rem);
  min-width: 1.1rem;
  height: 1.15rem;
  padding: 0 0.25rem;
  border: 2px solid var(--bg);
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: calc(1.15rem - 4px);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.bar-slot .write,
.bar-slot .write:hover:not(:disabled) {
  background: var(--accent);
  color: var(--accent-fg);
}

.bar-slot .write .icon {
  width: 1rem;
  height: 1rem;
}

.account-button {
  flex: none;
  width: 2rem;
  height: 2rem;
  margin-left: 0.5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
}

.account-button[aria-expanded="true"] {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
}

/* An avatar, or the initial on a neutral disc, or a person before the account is known. */
.avatar-disc {
  position: relative;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  overflow: hidden;
  border-radius: 50%;
  background: var(--sunken);
  color: var(--muted);
  font-weight: 700;
  line-height: 1;
}

.avatar-disc::before {
  content: attr(data-initial);
}

.avatar-disc:is(:not([data-initial]), [data-initial=""])::before {
  content: "";
  width: 60%;
  height: 60%;
  background-color: currentColor;
  -webkit-mask: var(--icon-person) center / contain no-repeat;
  mask: var(--icon-person) center / contain no-repeat;
}

.avatar-disc img,
.avatar-disc canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-disc.large {
  width: 2.5rem;
  height: 2.5rem;
  font-size: var(--step-1);
}

/* Menus: the account menu here, and the status menu (#35) with the same look. */
.menu {
  position: fixed;
  inset: auto;
  top: calc(var(--bar-h) + env(safe-area-inset-top, 0px) + 6px);
  right: max(var(--gutter-right), (100vw - var(--wide)) / 2);
  width: 20rem;
  max-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top, 0px) - 12px);
  margin: 0;
  padding: 0 0 0.35rem;
  overflow-y: auto;
  background: var(--surface);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
}

.menu-account {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 0.9rem;
}

.menu-account > div {
  min-width: 0;
}

.menu-name {
  font-weight: 650;
}

.menu-line {
  color: var(--muted);
  font-size: 0.75rem;
}

.menu-group {
  padding-top: 0.35rem;
  border-top: 1px solid var(--line);
}

.menu-group:not(:has(.menu-item)) {
  display: none;
}

/* The module's entries come in sections, a line between each (#174): the
   feed choice, the content warning switch, then Your profile and Settings. */
.menu-module {
  padding-top: 0;
}

.menu-section {
  padding-top: 0.35rem;
}

.menu-section + .menu-section {
  border-top: 1px solid var(--line);
}

.menu-feeds {
  padding: 0.6rem 0.9rem;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  height: 36px;
  padding: 0 0.9rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--fg);
  font-size: var(--step--1);
  text-align: start;
}

.menu-item:hover:not(:disabled) {
  background: var(--sunken);
}

.menu-item::before {
  content: "";
  width: 1.125rem;
  height: 1.125rem;
  flex: none;
  background-color: var(--muted);
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

.menu-item.profile { --icon: var(--icon-person); }
.menu-item.sign-out { --icon: var(--icon-sign-out); }
.menu-item.copy-link { --icon: var(--icon-link); }
.menu-item.share { --icon: var(--icon-share); }
.menu-item.mention { --icon: var(--icon-at); }
.menu-item.message { --icon: var(--icon-mail); }
.menu-item.mute { --icon: var(--icon-mute); }
.menu-item.block { --icon: var(--icon-block); }
.menu-item.report { --icon: var(--icon-flag); }
.menu-item.filter { --icon: var(--icon-filter); }
.menu-item.edit-open { --icon: var(--icon-edit); }
.menu-item:is(.delete, .delete-confirm) { --icon: var(--icon-delete); }
.menu-item.keep { --icon: var(--icon-close); }

/* A status's menu opens at its `⋯`, placed by script when it opens, and
   scrolls with the page; it shows once placed. With no account line, its
   first group has no separator above it. */
.menu.status-menu {
  position: absolute;
  right: auto;
  width: 16rem;
  max-height: none;
  padding-block: 0.35rem;
}

.menu.status-menu:not([data-placed]) {
  visibility: hidden;
}

.status-menu > .menu-group:first-child {
  padding-top: 0;
  border-top: 0;
}

/* One's own Edit and Delete are in the menu only on a phone (#72); from
   40rem up they are in the footer, and a `⋯` with nothing else in its menu
   is not shown. */
.status-menu > .status-own,
article > footer .more[data-own-only] {
  display: none;
}

.menu-item.add-account { --icon: var(--icon-plus); }
.menu-item.change-module { --icon: var(--icon-apps); }

/* Another account: its avatar stands where the icon would. */
.menu-item.switch-account {
  height: auto;
  min-height: 44px;
  padding-block: 0.3rem;
}

.menu-item.switch-account::before {
  display: none;
}

.menu-item .avatar-disc {
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  font-size: var(--step--1);
}

.menu-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.menu-text > span {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The module choice, opened in the menu by "Client: … · Change". */
.module-choice {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  margin: 0.25rem 0.9rem 0.5rem;
  padding: 0.6rem 0.75rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-size: var(--step--1);
}

.module-choice[hidden] {
  display: none;
}

.module-choice legend {
  padding: 0 0.3rem;
  color: var(--muted);
}

.module-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.module-option input {
  width: auto;
  accent-color: var(--accent);
}

.module-warning {
  font-weight: 400;
  white-space: normal;
}

.module-choice .use-module {
  align-self: flex-start;
}

/* Destructive items come last, in the danger colour. */
.menu-item.sign-out,
.menu-item.sign-out::before,
.status-moderation .menu-item,
.status-moderation .menu-item::before,
.status-own .menu-item:is(.delete, .delete-confirm),
.status-own .menu-item:is(.delete, .delete-confirm)::before {
  color: var(--danger);
  background-color: transparent;
}

.menu-item.sign-out::before,
.status-moderation .menu-item::before,
.status-own .menu-item:is(.delete, .delete-confirm)::before {
  background-color: var(--danger);
}

.status-own .menu-item.delete-confirm,
.status-own .menu-item.delete-confirm:hover:not(:disabled) {
  background: var(--danger-soft);
}

.menu-item.cw { --icon: var(--icon-eye); }
.menu-item.settings { --icon: var(--icon-settings); }

.menu-label {
  flex: 1;
}

/* A switch (#49): a track with a knob, on when its button is checked. */
.switch {
  position: relative;
  flex: none;
  width: 2.125rem;
  height: 1.25rem;
  border-radius: 999px;
  background: var(--line);
}

.switch::after {
  content: "";
  position: absolute;
  top: 0.1875rem;
  left: 0.1875rem;
  width: 0.875rem;
  height: 0.875rem;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.25);
}

[aria-checked="true"] > .switch {
  background: var(--accent);
}

[aria-checked="true"] > .switch::after {
  transform: translateX(0.875rem);
}

.switch-button {
  flex: none;
  display: inline-flex;
  padding: 0.25rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
}

/* Settings: groups of rows, each a name, a hint and its control. */
.settings-view {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-block: 1.25rem 2rem;
}

.settings-view h2 {
  margin-bottom: 0.75rem;
  font-size: var(--step-2);
  font-weight: 700;
}

.settings-group {
  margin: 0.75rem 0 0;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}


.setting {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1rem;
  padding: 0.75rem 0.9rem;
  background: var(--control);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.setting-text {
  flex: 1 1 14rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}

.setting-name {
  font-weight: 600;
}

.setting-hint {
  color: var(--muted);
  font-size: 0.8125rem;
}

.setting-wide {
  flex-direction: column;
  align-items: stretch;
}

.setting-wide .setting-text {
  flex: none;
}

/* What a setting stands at, where there is nothing to change in place. */
.setting-value {
  flex: none;
  max-width: 100%;
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* The default visibility (#75): radio buttons, each with what it means. */
.setting-choices {
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.setting-choices legend {
  padding: 0;
}

.setting-choices .setting-hint {
  display: block;
  margin-top: 0.1rem;
}

.choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.choice {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
}

.choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.choice input {
  flex: none;
  width: auto;
  margin: 0.2rem 0 0;
  accent-color: var(--accent);
}

.choice-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow-wrap: anywhere;
}

.choice-name {
  font-weight: 600;
}

.choice-hint {
  color: var(--muted);
  font-size: 0.8125rem;
}

.languages {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.languages-none {
  color: var(--muted);
  font-size: var(--step--1);
}

.language {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.2rem 0.3rem 0.2rem 0.75rem;
  border-radius: 999px;
  background: var(--sunken);
  font-size: var(--step--1);
}

.language .remove {
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  background-color: transparent;
}

.language .remove::before {
  content: "";
  display: block;
  width: 0.875rem;
  height: 0.875rem;
  margin: auto;
  background-color: var(--muted);
  -webkit-mask: var(--icon-close) center / contain no-repeat;
  mask: var(--icon-close) center / contain no-repeat;
}

.language .remove:hover::before {
  background-color: var(--fg);
}

/* Every language, searched by name or code, each with an explicit action
   (#75): Use for the primary, Add for another. */
.language-list {
  max-height: 16rem;
  margin: 0;
  padding: 0.25rem;
  overflow-y: auto;
  list-style: none;
  border: 1px solid var(--line);
  border-radius: 8px;
  scrollbar-color: var(--line) transparent;
}

.language-option {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0.3rem 0.2rem 0.5rem;
  border-radius: 6px;
}

.language-option:hover {
  background: var(--sunken);
}

.language-option-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.language-option button {
  flex: none;
  min-width: 4.5rem;
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  color: var(--accent);
  font-size: var(--step--1);
  font-weight: 600;
}

.language-option button[aria-disabled="true"] {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  font-weight: 400;
  cursor: default;
}

.language-none {
  padding: 0.4rem 0.5rem;
  color: var(--muted);
  font-size: var(--step--1);
}

.settings-said {
  min-height: 1.4em;
  color: var(--muted);
  font-size: var(--step--1);
}

.notice {
  margin-top: 2rem;
  padding: 1rem 1.25rem;
  background: var(--control);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.notice + .onboarding {
  margin-top: 1rem;
}

.onboarding {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 2rem;
  padding: 1.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.onboarding label {
  font-size: var(--step-2);
  font-weight: 650;
  line-height: 1.25;
}

.onboarding .hint {
  color: var(--muted);
  margin-bottom: 0.4rem;
}

.onboarding button[type="submit"] {
  align-self: flex-start;
  padding-block: 0.45rem;
}

.onboarding .adding {
  color: var(--muted);
}

.onboarding .actions {
  display: flex;
  gap: 0.6rem;
  align-items: center;
}

.onboarding .actions button {
  padding-block: 0.45rem;
}

/* "Choose app": for advanced readers, small and closed. */
.choose-app {
  gap: 0.4rem;
}

.choose-app > summary {
  padding: 0.2rem 0.6rem;
  background: transparent;
  color: var(--muted);
  font-size: var(--step--1);
}

.choose-app[open] > summary {
  margin-bottom: 0;
}

.choose-app .hint {
  margin-bottom: 0;
  font-size: var(--step--1);
}

.choose-app select {
  width: auto;
  align-self: flex-start;
}

.unsure {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  background: var(--danger-soft);
  border-radius: 8px;
}

.unsure button {
  align-self: flex-start;
}

/* The storage the sign in lives in is refused: say so, never onboarding. */
.storage-unavailable {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 2rem;
  padding: 1.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.storage-unavailable h2 {
  font-size: var(--step-2);
  font-weight: 650;
  line-height: 1.25;
}

.storage-unavailable .detail code {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--muted);
  overflow-wrap: anywhere;
}

.storage-unavailable .hint {
  color: var(--muted);
}

.storage-unavailable .retry {
  align-self: flex-start;
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
  padding: 0.45rem 1.1rem;
}

/* Mastodon: search row, composer, feed choice */

main {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding-top: 1.25rem;
}

/* What sits on a set-in card stands out from it again (#170). */
:is(.setting, .notice, .follow-requests) * {
  --control: var(--surface);
}

/* The reader's column on a panel (#170): the surface colour, a thin border
   and rounded top corners, a step off the page and under the bar, as wide
   as the column with its room. Where the window has no room around the
   column, the panel is the whole width, with no frame. Onboarding and the
   storage notice keep their own cards on the page. */
main[data-module] {
  --panel-gap: 0.75rem;
  --panel-border: 1px;
  --control: var(--inset);
  flex: 1;
  margin: var(--panel-gap) calc(-1 * var(--gutter-right)) 0 calc(-1 * var(--gutter-left));
  padding-left: calc(var(--gutter-left) - var(--panel-border));
  padding-right: calc(var(--gutter-right) - var(--panel-border));
  padding-bottom: var(--content-end);
  background: var(--surface);
  border: var(--panel-border) solid var(--line);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
}

/* #content's widest: the column and its room (40rem + 2rem). */
@media (max-width: 42rem) {
  main[data-module] {
    --panel-gap: 0px;
    --panel-border: 0px;
    border-radius: 0;
  }
}

/* The composer, a modal dialog: a 36rem panel near the top, the whole
   screen on a phone (below). */
.compose-dialog {
  width: min(36rem, calc(100% - 2rem));
  max-width: none;
  max-height: calc(100dvh - 6rem);
  margin: 4.75rem auto auto;
  padding: 0;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow);
}

.compose-dialog::backdrop {
  background: var(--scrim);
}

.composer {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1.25rem 1.5rem 0;
}

.compose-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.compose-head h2 {
  flex: 1;
  min-width: 0;
  font-size: var(--step-1);
  overflow-wrap: anywhere;
}

/* Icon buttons in the dialog: the close button and the toolbar's. */
.compose-close,
.compose-media,
.compose-cw,
.compose-emoji {
  display: inline-grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  padding: 0;
  border-color: transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
}

.compose-close:hover:not(:disabled),
.compose-media:hover:not(:disabled),
.compose-cw:hover:not(:disabled),
.compose-emoji:hover:not(:disabled) {
  border-color: transparent;
  background: var(--sunken);
}

.compose-close { --icon: var(--icon-close); margin-right: -0.5rem; }
.compose-cw { --icon: var(--icon-warning); }
.compose-media { --icon: var(--icon-media); }
.compose-emoji { --icon: var(--icon-smile); }

.compose-cw[aria-pressed="true"],
.compose-cw[aria-pressed="true"]:hover:not(:disabled),
.compose-emoji[aria-expanded="true"],
.compose-emoji[aria-expanded="true"]:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent);
}

:is(.compose-close, .compose-media, .compose-cw, .compose-emoji, .compose-visibility) .icon {
  width: 1.25rem;
  height: 1.25rem;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

/* The status being replied to: its author and the start of its text. */
.reply-context {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem 0.75rem;
  background: var(--sunken);
  border-radius: 8px;
}

.reply-context .avatar-disc {
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.15rem;
  font-size: 0.75rem;
}

.reply-what {
  flex: 1;
  min-width: 0;
  font-size: var(--step--1);
}

.reply-who,
.reply-excerpt {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.reply-name {
  font-weight: 650;
}

.reply-warning {
  font-style: italic;
}

.reply-acct,
.reply-excerpt {
  color: var(--muted);
}

.reply-context .drop-reply {
  flex: none;
  padding: 0.1rem 0.6rem;
  font-size: var(--step--1);
}

.composer > #compose-text {
  min-height: 8rem;
  field-sizing: content;
  max-height: 50dvh;
}

/* Media, CW, [emoji], visibility, language, the count and Post, under a
   hairline across the panel. */
.compose-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0 -1.5rem;
  padding: 0.6rem 1.5rem;
  border-top: 1px solid var(--line);
}

/* The custom emoji picker (#54), right above the toolbar, the composer's
   width: a search field and the emoji by category, scrolling inside a
   fixed height. Each image has a fixed size, so nothing moves as they load. */
.emoji-picker {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.6rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
}

.emoji-grid {
  height: 15rem;
  /* A little space after the last row at the end of the list (#96). */
  padding-bottom: 4px;
  /* A focused emoji is scrolled in below its category's heading stuck at the
     top (--emoji-heading-h, measured as focus enters it) and clear of the
     bottom, with 4px of space each side (#96; its focus ring is inside its
     box since #110). */
  scroll-padding: calc(var(--emoji-heading-h, 0px) + 4px) 0 4px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-color: var(--line) transparent;
}

.emoji-group h3 {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: 0.3rem 0.25rem;
  background: var(--bg);
  color: var(--muted);
  font-size: var(--step--1);
  font-weight: 600;
}

.emoji-choices {
  display: grid;
  grid-template-columns: repeat(auto-fill, 2.5rem);
  justify-content: space-between;
  gap: 0.15rem;
  /* A little space between a category's heading and its first row (#96),
     as in .emoji-grid's scroll-padding. */
  padding-top: 4px;
}

.emoji-choice {
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border-color: transparent;
  border-radius: 8px;
  background: transparent;
  /* How far inside the emoji's border box its focus ring begins (#110), and
     the side padding of an emoji's name, so the two move together (#117). */
  --emoji-ring-inset: 2px;
}

.emoji-choice:hover:not(:disabled) {
  border-color: transparent;
  background: var(--sunken);
}

/* The focus ring inside the emoji's box (#110): the first and last columns
   touch the grid's sides, which clip what lies past them, and room there
   would cost a column at some widths. The ring (2px wide, from
   :focus-visible) ends at the inset, so its inner edge lies one inset inside
   the box, and an inset under the ring's width would push it out. */
.emoji-choice:focus-visible {
  outline-offset: calc(-1 * var(--emoji-ring-inset));
}

/* An emoji whose image the origin images setting refuses (#52): its name. */
.emoji-choice .emoji-name {
  max-width: 100%;
  /* Clear of the focus ring drawn inside the emoji's box (#110), with a
     gap (#117): the name sits inside the button's 1px border, so a padding
     equal to the ring's inset leaves that 1px between the text and the
     ring. */
  padding: 0 var(--emoji-ring-inset);
  overflow: hidden;
  color: var(--muted);
  font-size: 0.6rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.emoji-choice img.emoji,
.emoji-choice canvas.emoji {
  width: 1.75rem;
  height: 1.75rem;
  object-fit: contain;
  vertical-align: middle;
}

/* On a phone it shares what the keyboard leaves with the text. */
@media (max-width: 40rem) {
  .emoji-grid {
    height: min(15rem, calc(var(--vv-h, 100dvh) * 0.3));
  }
}

.emoji-error {
  color: var(--danger);
}

.emoji-retry {
  align-self: flex-start;
}

/* The visibility: an icon and the choice, compact. */
.compose-visibility {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: var(--muted);
  --icon: var(--icon-globe);
}

.compose-visibility[data-visibility="unlisted"] { --icon: var(--icon-unlock); }
.compose-visibility[data-visibility="private"] { --icon: var(--icon-lock); }
.compose-visibility[data-visibility="direct"] { --icon: var(--icon-at); }

.compose-visibility .icon {
  position: absolute;
  left: 0.6rem;
  width: 1rem;
  height: 1rem;
  pointer-events: none;
}

.compose-visibility select {
  width: auto;
  max-width: 10rem;
  padding: 0.3rem 0.5rem 0.3rem 2rem;
  border-radius: 8px;
  color: var(--fg);
  font-size: var(--step--1);
}

/* The language: a short button per language the reader posts in, the one
   chosen in the accent, and `⋯`, a native list of every language
   drawn as an icon button. */
.compose-language {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
}

.compose-language .language-choice {
  min-width: 2.75rem;
  height: 2rem;
  padding: 0 0.5rem;
  border-radius: 8px;
  font-size: var(--step--1);
  font-weight: 500;
}

.compose-language .language-choice[aria-pressed="true"],
.compose-language .language-choice[aria-pressed="true"]:hover:not(:disabled) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 700;
}

.language-more {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  color: var(--muted);
}

.language-more .icon {
  position: absolute;
  width: 1.25rem;
  height: 1.25rem;
  background-color: currentColor;
  -webkit-mask: var(--icon-more) center / contain no-repeat;
  mask: var(--icon-more) center / contain no-repeat;
  pointer-events: none;
}

.language-more select {
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  appearance: none;
  background: var(--surface);
  color: transparent;
  cursor: pointer;
}

.language-more select:hover {
  border-color: var(--muted);
}

.language-more option {
  color: var(--fg);
}

/* On a phone the language buttons take a row of their own. */
@media (max-width: 40rem) {
  .compose-language {
    flex-basis: 100%;
  }
}

.compose-send {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-left: auto;
}

.compose-count {
  color: var(--muted);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}

.compose-count[data-over="true"] {
  color: var(--danger);
  font-weight: 650;
}


/* Write, with a draft kept: a dot on its corner. */
.bar-slot .write .dot {
  position: absolute;
  top: -0.2rem;
  right: -0.2rem;
  width: 0.7rem;
  height: 0.7rem;
  border: 2px solid var(--bg);
  border-radius: 50%;
  background: var(--accent);
}

/* The attachments (#47): a thumbnail each, of a fixed size so nothing
   moves as the preview loads, with ALT at its foot (in the danger colour
   until described) and Remove at its corner. */
.attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.attachments:empty {
  display: none;
}

.attachment {
  position: relative;
  flex: none;
  width: 6.25rem;
  height: 4.375rem;
}

.attachment-thumb {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--sunken);
  color: var(--muted);
}

.attachment-thumb:disabled {
  opacity: 1;
}

.attachment-thumb .icon {
  width: 1.5rem;
  height: 1.5rem;
  background-color: currentColor;
  -webkit-mask: var(--icon-media) center / contain no-repeat;
  mask: var(--icon-media) center / contain no-repeat;
}

.attachment-thumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.attachment-thumb img[hidden] {
  display: none;
}

.alt-badge {
  position: absolute;
  left: 0.375rem;
  bottom: 0.375rem;
  padding: 0 0.35rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--surface);
  color: var(--danger);
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 0.875rem;
}

.alt-badge[data-described="true"] {
  color: var(--fg);
}

.attachment[data-stage="uploading"] .alt-badge {
  display: none;
}

.attachment[data-stage="failed"] .attachment-thumb {
  border-color: var(--danger);
}

.attachment-remove {
  position: absolute;
  top: 0.25rem;
  right: 0.25rem;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border-radius: 50%;
  background: var(--surface);
  color: var(--fg);
}

.attachment-remove .icon {
  width: 0.75rem;
  height: 0.75rem;
  background-color: currentColor;
  -webkit-mask: var(--icon-close) center / contain no-repeat;
  mask: var(--icon-close) center / contain no-repeat;
}

.attachment-error {
  color: var(--danger);
  font-size: var(--step--1);
  overflow-wrap: anywhere;
}

/* The description editor, under the thumbnails. */
.alt-editor {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.6rem 0.75rem;
  border-radius: 8px;
  background: var(--sunken);
}

.alt-editor label {
  font-size: var(--step--1);
  font-weight: 650;
  overflow-wrap: anywhere;
}

.alt-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

.alt-editor .alt-save {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
}

.alt-editor .alt-save:hover:not(:disabled) {
  border-color: var(--fg);
}

/* The row under the bar, sticky with it, the panel's own. Its background
   and hairline span the panel through shadows, which add nothing to the
   page's width. */
.search-row {
  position: sticky;
  top: calc(var(--bar-h) + env(safe-area-inset-top, 0px));
  z-index: 9;
  margin-top: -1.25rem;
  padding-block: 0.6rem;
  background: var(--surface);
  /* The panel's width, inside its border (#170). */
  box-shadow: 0 0 0 100vmax var(--surface);
  clip-path: inset(0 calc(var(--panel-border, 0px) - var(--gutter-right)) -1px calc(var(--panel-border, 0px) - var(--gutter-left)));
}

.search-row::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--line);
  box-shadow: 0 0 0 100vmax var(--line);
  clip-path: inset(0 calc(var(--panel-border, 0px) - var(--gutter-right)) 0 calc(var(--panel-border, 0px) - var(--gutter-left)));
}

form[role="search"] {
  position: relative;
}

form[role="search"]::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0.9rem;
  width: 1.1rem;
  height: 1.1rem;
  translate: 0 -50%;
  background-color: var(--muted);
  -webkit-mask: var(--icon-search) center / contain no-repeat;
  mask: var(--icon-search) center / contain no-repeat;
  pointer-events: none;
}

form[role="search"] input {
  padding-left: 2.6rem;
  border-width: 2px;
  border-radius: 999px;
}

/* The timeline's feed: one place, three ways of viewing it, chosen in the
   account menu (#173); its inset is the section's, `.menu-feeds`. */
.feeds {
  display: flex;
  padding: 3px;
  background: var(--sunken);
  border-radius: 999px;
}

.feeds button {
  flex: 1;
  padding: 0.2rem 0.5rem;
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  font-size: var(--step--1);
  font-weight: 500;
}

.feeds button:hover:not(:disabled) {
  border-color: transparent;
  color: var(--fg);
}

.feeds button[aria-pressed="true"],
.feeds button[aria-pressed="true"]:hover:not(:disabled) {
  background: var(--surface);
  border-color: var(--line);
  color: var(--fg);
  font-weight: 650;
}

/* Reading: timelines, threads, profiles, search, notifications */

section[data-view] {
  display: flex;
  flex-direction: column;
}

section[data-view] > p,
section[data-view] > h2 {
  padding-block: 0.75rem;
}

section[data-view] > p:not([role="alert"]) {
  color: var(--muted);
}

/* Back, Clear all, Load more */
section[data-view] > button {
  align-self: flex-start;
  margin-block: 0.5rem;
}

section[data-view] > button:last-child:not(:first-child) {
  align-self: stretch;
  margin-top: 1rem;
}

article {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-block: 1.25rem;
  border-bottom: 1px solid var(--line);
}

article > header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.5rem;
}

article time {
  margin-left: auto;
  color: var(--muted);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.author {
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: none;
  text-align: start;
  white-space: normal;
  min-width: 0;
}

.author .name,
.author > span:first-child:not(.acct) {
  font-weight: 700;
}

.author:hover .name {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.acct {
  color: var(--muted);
  font-weight: 400;
}

.boost {
  color: var(--muted);
  font-size: var(--step--1);
}

/* The author's avatar at the left of a status or a notification (#42): a
   column of its own beside the rest, under the boost line. A fixed size, so
   nothing moves as it loads. */
article:has(> .face) {
  --face: 2.75rem;
  display: grid;
  grid-template-columns: var(--face) minmax(0, 1fr);
  column-gap: 0.75rem;
  align-content: start;
}

article:has(> .face) > * {
  grid-column: 2;
}

article:has(> .face) > button:not(.face) {
  justify-self: start;
}

article > .face {
  display: block;
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
}

article:has(> .boost) > .face {
  grid-row: 2 / span 2;
}

article > .face .avatar-disc {
  width: var(--face);
  height: var(--face);
  font-size: var(--step-1);
}

/* The booster's, small, before "X boosted". */
.boost .avatar-disc {
  display: inline-grid;
  width: 1.25rem;
  height: 1.25rem;
  margin-right: 0.4rem;
  vertical-align: middle;
  font-size: 0.7rem;
}

@media (max-width: 30rem) {
  article:has(> .face) {
    --face: 2.25rem;
    column-gap: 0.6rem;
  }
}

.content {
  overflow-wrap: anywhere;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.content p {
  margin: 0;
}

/* A long link, marked up by the server (Mastodon) or by api::shorten_links:
   the scheme, `www.` and the tail are hidden but still copied with the link
   text, and what shows ends in an ellipsis. Only inside a link, so a server
   cannot hide words in the rest of a status; inside one it can, as on
   Mastodon, and the href is still the real target. */
.content a .invisible,
.note a .invisible,
.fields a .invisible {
  font-size: 0;
  line-height: 0;
  display: inline-block;
  width: 0;
  height: 0;
  position: absolute;
}

.content a .ellipsis::after,
.note a .ellipsis::after,
.fields a .ellipsis::after {
  content: "…";
}

img.emoji,
canvas.emoji {
  display: inline;
  height: 1.25em;
  width: auto;
  vertical-align: -0.25em;
}

article video {
  display: block;
  max-height: 32rem;
  border-radius: 8px;
  background: var(--sunken);
}

/* A post's pictures, as one block: one whole, two side by side, three as one
   large and two stacked, four in a square of four; each opens whole. */
.media {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  overflow: hidden;
  border-radius: 8px;
}

.media:is([data-count="2"], [data-count="3"], [data-count="4"]) {
  aspect-ratio: 16 / 9;
  grid-auto-rows: 1fr;
}

/* More than four (some servers allow it): two columns of equal cells. */
.media:not([data-count="1"], [data-count="2"], [data-count="3"], [data-count="4"]) > a {
  aspect-ratio: 4 / 3;
}

/* Alone, a picture is shown whole, as wide as it is, up to a height. */
.media[data-count="1"] {
  display: block;
  width: fit-content;
  max-width: 100%;
}

.media[data-count="3"] > :first-child {
  grid-row: span 2;
}

.media > * {
  min-width: 0;
  min-height: 0;
}

.media > a {
  display: block;
  background: var(--sunken);
}

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

.media[data-count="1"] img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 32rem;
}

details {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

summary {
  cursor: pointer;
  align-self: flex-start;
  padding: 0.35rem 0.75rem;
  border-radius: 8px;
  background: var(--sunken);
  font-weight: 500;
}

details[open] > summary {
  margin-bottom: 0.5rem;
}

.poll {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.poll li {
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
}

/* The emoji people reacted with (#53), under the content: read-only chips,
   each its emoji and count; the reader's own in the accent's colours. */
.reactions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.reactions li {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
}

.reactions .shown {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.reactions .glyph {
  display: inline-flex;
  align-items: center;
  font-size: 1rem;
}

.reactions li[data-me] {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--fg);
}

article > footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  color: var(--muted);
  font-size: var(--step--1);
}

article > footer button,
article > button {
  padding: 0.15rem 0.65rem;
  font-size: var(--step--1);
  color: var(--muted);
}

article > footer button:hover:not(:disabled) {
  color: var(--fg);
}

article > button {
  align-self: flex-start;
}

/* The post's actions are icons; the words stay for screen readers and show
   as a tooltip. Confirming a deletion keeps its words, and its red. */

article > footer :is(.thread, .reply, [data-action], .edit-open, .delete, .more) {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-width: 2.25rem;
  height: 2.25rem;
  padding: 0 0.5rem;
  border-color: transparent;
  background: transparent;
  font-size: 0;
}

article > footer :is(.thread, .reply, [data-action], .edit-open, .delete, .more)::before {
  content: "";
  width: 1.15rem;
  height: 1.15rem;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

article > footer :is(.thread, .reply, [data-action], .edit-open, .delete, .more):hover:not(:disabled),
article > footer .more[aria-expanded="true"] {
  background: var(--sunken);
  color: var(--fg);
}

article > footer .thread { --icon: var(--icon-thread); }
article > footer .reply { --icon: var(--icon-reply); }
article > footer [data-action="boost"] { --icon: var(--icon-boost); }
article > footer [data-action="favourite"] { --icon: var(--icon-star); }
article > footer [data-action="bookmark"] { --icon: var(--icon-mark); }
article > footer .edit-open { --icon: var(--icon-edit); }
article > footer .delete { --icon: var(--icon-delete); }
article > footer .more { --icon: var(--icon-more); }

/* What copying the link did, said for a moment after the menu closes;
   empty, it takes no room in the row, not even a gap. */
article > footer .copied {
  color: var(--muted);
  font-size: var(--step--1);
}

article > footer .copied:empty {
  position: absolute;
}

/* The number of replies, boosts and favourites, next to each icon, in the
   button's muted or pressed colour; none for 0. The button's name says it in
   words. */
article > footer :is(.thread, [data-action])[data-count]::after {
  content: attr(data-count);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}

article > footer :is(.thread, [data-action])[data-count="0"]::after {
  content: none;
}

article > footer [data-action][aria-pressed="true"],
article > footer [data-action][aria-pressed="true"]:hover:not(:disabled) {
  background: transparent;
}

article > footer [data-action="boost"][aria-pressed="true"] {
  color: var(--accent);
}

article > footer [data-action="favourite"][aria-pressed="true"] {
  --icon: var(--icon-star-on);
  color: var(--star);
}

article > footer [data-action="bookmark"][aria-pressed="true"] {
  --icon: var(--icon-mark-on);
  color: var(--mark);
}

article > footer .delete-confirm {
  background: var(--danger-soft);
  border-color: transparent;
  color: var(--danger);
}

.edit {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.edit > button {
  align-self: flex-start;
}

/* The status the thread was opened at. */
[data-focus] > article {
  margin-inline: -0.75rem;
  padding-inline: 0.75rem;
  background: var(--sunken);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
}

section[data-view="profile"] > header {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding-block: 0.5rem 1.25rem;
  border-bottom: 1px solid var(--line);
}

/* The header picture across the top of the full profile, and the avatar
   over its lower edge, ringed in the panel's colour (#168): a plain band
   without a header. */
section[data-view="profile"] .profile-banner {
  aspect-ratio: 3 / 1;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--sunken);
}

section[data-view="profile"] .profile-banner :is(img, canvas) {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Half the disc over the band, past the header's gap. */
section[data-view="profile"] .profile-face {
  margin: calc(-2.75rem - 0.4rem) 0 0 1rem;
}

section[data-view="profile"] .profile-face .avatar-disc {
  width: 5.5rem;
  height: 5.5rem;
  font-size: var(--step-2);
  box-shadow: 0 0 0 4px var(--surface);
}

/* The account's page on its own server, on the full profile. */
.origin {
  align-self: flex-start;
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--accent);
  font-size: var(--step--1);
  font-weight: 500;
  text-decoration: none;
}

.origin:hover {
  border-color: var(--accent);
}

/* Where the profile's posts come from: its own server, or the user's instance. */
.posts-from {
  padding-block: 0.75rem 0;
  color: var(--muted);
  font-size: var(--step--1);
}

section[data-view="profile"] h2 {
  font-size: var(--step-2);
}

.note {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* A profile's fields: name over value, a verified value marked. */
.fields {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0;
  overflow-wrap: anywhere;
}

.fields dt {
  color: var(--muted);
  font-size: var(--step--1);
}

.fields dd {
  margin: 0;
}

.fields .verified-mark {
  color: var(--accent);
  margin-inline-end: 0.3em;
}

.stats {
  color: var(--muted);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}

/* Search results: accounts and hashtags are rows. */
section[data-view="search"] > p[data-account],
section[data-view="search"] > p.tag {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding-block: 0.75rem;
  border-bottom: 1px solid var(--line);
  color: var(--fg);
}

.follow {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.hashtag {
  border: 0;
  padding: 0;
  background: none;
  color: var(--accent);
  font-weight: 600;
  white-space: normal;
}

/* A post's hashtags (#166): pills on one line, "+N" at its end for the rest,
   which then show on as many lines as they need. */
.tag-bar {
  --tag-h: 1.75rem;
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.tag-bar:not(.open) {
  max-height: var(--tag-h);
  overflow: clip;
  /* Room for a focus ring, less than the gap to a second line. */
  overflow-clip-margin: 3px;
}

.tag-bar.overflowing:not(.open) {
  padding-inline-end: 3.5rem;
}

.tag-bar :is(.tag, .tag-more) {
  height: var(--tag-h);
  padding: 0 0.7rem;
  border: 0;
  border-radius: 999px;
  background: var(--sunken);
  color: var(--accent);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: var(--tag-h);
  white-space: nowrap;
}

.tag-bar .tag-more {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
}

.tag-bar :is(.tag, .tag-more):hover {
  background: var(--accent-soft);
}

.tag-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Notifications */

section[data-view="notifications"] > .clear {
  align-self: flex-end;
}

article[data-notification] > p {
  color: var(--muted);
}

article[data-notification] .author {
  color: var(--fg);
}

article[data-notification] :is(.content, .tag-bar) {
  padding-left: 0.75rem;
  border-left: 2px solid var(--line);
}

.follow-requests {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  padding: 1rem;
  background: var(--control);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.follow-requests h2 {
  font-size: var(--step-0);
}

.follow-requests p {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.follow-requests .accept {
  margin-left: auto;
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}

/* Profile card: opened from a mention or a profile link, below it. */

/* Catches the click outside the card; it neither dims nor covers what is seen. */
.peek-backdrop {
  position: fixed;
  inset: 0;
  z-index: 20;
}

.peek {
  position: absolute;
  /* Below the link, and never past the window's edges: 100% is the page's width. */
  left: max(16px, min(var(--peek-x), 100% - min(22rem, 100vw - 32px) - 16px));
  top: var(--peek-y);
  z-index: 21;
  width: min(22rem, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* Near the bottom of the window, above the link instead. */
.peek.above {
  transform: translateY(-100%);
}

.peek:focus {
  outline: none;
}

.peek:focus-visible {
  outline: 2px solid var(--accent);
}

.peek > header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding-right: 2rem;
}

.peek > header > div {
  min-width: 0;
}

.peek h2 {
  font-size: var(--step-0);
  font-weight: 650;
}

.peek .acct {
  font-size: var(--step--1);
}

.peek > header .avatar-disc {
  width: 3rem;
  height: 3rem;
  flex: none;
  font-size: var(--step-1);
}

.peek .fields {
  max-height: 9rem;
  overflow-y: auto;
  font-size: var(--step--1);
}

.peek .note {
  max-height: 9rem;
  overflow-y: auto;
  font-size: var(--step--1);
}

.peek-close {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  font-size: var(--step-1);
  line-height: 1;
}

.peek-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* A profile's follow, mute and block (#36); mute and block in the danger
   colour until done, and what is done said above them. */
.account-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

section[data-view="profile"] .account-actions {
  margin-top: 0.75rem;
}

.standing {
  color: var(--muted);
  font-size: var(--step--1);
}

/* Busy, but still focused: not `disabled`, which would drop the focus. */
.account-actions button[aria-disabled="true"],
dialog.confirm button[aria-disabled="true"] {
  cursor: default;
  opacity: 0.55;
}

button.danger {
  color: var(--danger);
}

button.danger:hover:not(:disabled) {
  border-color: var(--danger);
}

button[type="submit"].danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-fg);
}

button[type="submit"].danger:hover:not(:disabled) {
  border-color: var(--fg);
}

/* The dialog that asks before a mute or a block. */
dialog.confirm {
  width: min(28rem, calc(100vw - var(--gutter-left) - var(--gutter-right)));
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow);
}

dialog.confirm::backdrop {
  background: rgb(14 20 22 / 0.45);
}

dialog.confirm form {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

dialog.confirm h2 {
  font-size: var(--step-1);
  font-weight: 650;
  overflow-wrap: anywhere;
}

dialog.confirm p:not([role="alert"]) {
  color: var(--muted);
  font-size: var(--step--1);
}

dialog.confirm .check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

dialog.confirm .check input {
  width: auto;
  accent-color: var(--accent);
}

dialog.confirm .field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: var(--step--1);
}

/* The report dialog (#37) and the filter dialog (#38): the longest of them,
   they scroll inside on a short screen. */
dialog:is(.report, .filter) {
  max-height: calc(100dvh - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
}

dialog:is(.report, .filter) fieldset {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

dialog:is(.report, .filter) legend {
  margin-bottom: 0.4rem;
  font-weight: 600;
}

dialog:is(.report, .filter) .option {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
}

dialog:is(.report, .filter) .option:has(input:checked) {
  border-color: var(--accent);
}

/* A filter that holds the post already cannot take it again. */
dialog.filter .option:has(input:disabled) {
  cursor: default;
  color: var(--muted);
}

dialog:is(.report, .filter) .option input {
  width: auto;
  margin-top: 0.2rem;
  accent-color: var(--accent);
}

dialog:is(.report, .filter) .option > span {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow-wrap: anywhere;
}

dialog:is(.report, .filter) .option-hint {
  color: var(--muted);
  font-size: var(--step--1);
}

dialog.report textarea {
  resize: vertical;
}

/* A status a filter collapsed (#38): its words and Show, in place of all
   the rest, across the avatar's column. */
article[data-filtered] > :not(.filtered) {
  display: none;
}

article[data-filtered] > .filtered {
  grid-column: 1 / -1;
}

.filtered {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  color: var(--muted);
  font-size: var(--step--1);
}

.filtered p {
  min-width: 0;
  overflow-wrap: anywhere;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

/* On a phone the card is a panel at the bottom of the screen, above the bottom bar. */
@media (max-width: 40rem) {
  .peek {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: calc(var(--bottom-h) + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-height: 75vh;
    overflow-y: auto;
    padding-left: var(--gutter-left);
    padding-right: var(--gutter-right);
    border-width: 1px 0;
    border-radius: var(--radius) var(--radius) 0 0;
  }

  .peek.above {
    transform: none;
  }

  .peek-close {
    right: var(--gutter-right);
  }
}

/* Phones, below 40rem: a short top bar with the view's name, Write and the
   avatar, and the same Main nav as a bottom bar within thumb reach. */
@media (max-width: 40rem) {
  :root {
    --bar-h: 52px;
  }

  /* A control focused at the foot of the screen (Tab, `scrollIntoView`)
     is scrolled above the bottom bar, not left under it (#83, WCAG 2.4.11),
     with room for its focus ring (#88); only while there is one:
     onboarding has none. */
  html:has(nav[aria-label="Main"]) {
    scroll-padding-bottom: calc(var(--bottom-h) + env(safe-area-inset-bottom, 0px) + 4px);
  }

  .bar:has(.view-name) .brand-name {
    display: none;
  }

  .brand {
    margin-right: 0.25rem;
  }

  .bar-slot .view-name:hover:not(:disabled) {
    border-color: transparent;
  }

  .bar-slot .view-name {
    display: block;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    padding: 0;
    font-size: 1.125rem;
    font-weight: 700;
    text-align: left;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  nav[aria-label="Main"] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0;
    height: calc(var(--bottom-h) + env(safe-area-inset-bottom, 0px));
    padding: 0 env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
    background: var(--bg);
    border-top: 1px solid var(--line);
  }

  .bar-slot nav[aria-label="Main"] button {
    flex-direction: column;
    gap: 0.2rem;
    height: var(--bottom-h);
    margin: 0;
    padding: 0;
    border-radius: 0;
    color: var(--muted);
    font-size: 0.75rem;
    font-weight: 500;
    outline-offset: -4px;
  }

  .bar-slot nav[aria-label="Main"] .icon {
    width: 3.5rem;
    height: 1.625rem;
    -webkit-mask-size: 1.25rem;
    mask-size: 1.25rem;
  }

  /* The current place: an accent pill behind its icon, and its label in the accent. */
  .bar-slot nav[aria-label="Main"] :is(.notifications[aria-current="page"], .search-toggle[aria-expanded="true"]) {
    color: var(--accent);
    font-weight: 650;
  }

  .bar-slot nav[aria-label="Main"] :is(.notifications[aria-current="page"], .search-toggle[aria-expanded="true"])::before {
    content: "";
    position: absolute;
    z-index: -1;
    top: calc((var(--bottom-h) - 1.625rem - 0.2rem - 0.75rem * 1.55) / 2);
    left: calc(50% - 1.75rem);
    width: 3.5rem;
    height: 1.625rem;
    border-radius: 999px;
    background: var(--accent-soft);
  }

  nav[aria-label="Main"] .badge {
    top: 0.35rem;
    left: calc(50% + 0.3rem);
  }

  .bar-slot .write {
    width: 2.5rem;
    height: 2.25rem;
    padding: 0;
  }

  .bar-slot .write .label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .bar-slot .write .icon {
    width: 1.25rem;
    height: 1.25rem;
  }

  /* The composer fills the screen, or what the on-screen keyboard leaves
     of it: the module sets --vv-top and --vv-h from visualViewport. Close
     is at the top left and Post at the top right, out of the thumb's way
     while typing; the toolbar sits at the foot, so above the keyboard, with
     the language buttons on a row of their own under it. The text takes
     the room between them and scrolls inside it. */
  .compose-dialog {
    --post-w: 4.5rem;
    top: var(--vv-top, 0px);
    bottom: auto;
    width: 100%;
    height: var(--vv-h, 100%);
    max-height: none;
    margin: 0;
    overflow: hidden;
    border: 0;
    border-radius: 0;
  }

  .compose-dialog .composer {
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* A control focused by Tab or Shift+Tab is scrolled out from under the
       sticky head and toolbar (#88), whose heights the module measures,
       with room for its focus ring. */
    scroll-padding-top: calc(var(--compose-head-h, 0px) + 4px);
    scroll-padding-bottom: calc(var(--compose-toolbar-h, 0px) + 4px);
    padding: 0 var(--gutter-right) 0 var(--gutter-left);
  }

  .compose-dialog .compose-head {
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 calc(-1 * var(--gutter-right)) 0 calc(-1 * var(--gutter-left));
    /* Room at the right for Post, placed over it. */
    padding: calc(0.6rem + env(safe-area-inset-top, 0px)) calc(var(--gutter-right) + var(--post-w) + 0.75rem) 0.6rem var(--gutter-left);
    background: var(--surface);
    border-bottom: 1px solid var(--line);
  }

  .compose-dialog .compose-close {
    order: -1;
    margin: 0 0 0 -0.5rem;
  }

  .compose-dialog .composer > #compose-text {
    flex: 1 1 8rem;
    max-height: none;
  }

  .compose-dialog .compose-toolbar {
    position: sticky;
    bottom: 0;
    z-index: 1;
    margin: auto calc(-1 * var(--gutter-right)) 0 calc(-1 * var(--gutter-left));
    padding: 0.6rem var(--gutter-right) calc(0.6rem + var(--compose-safe-bottom, env(safe-area-inset-bottom, 0px))) var(--gutter-left);
    background: var(--surface);
  }

  .compose-dialog .compose-language {
    order: 1;
  }

  /* Post, still the form's last control, at the top right of the screen. */
  .compose-dialog .compose-send button[type="submit"] {
    position: fixed;
    top: calc(var(--vv-top, 0px) + env(safe-area-inset-top, 0px) + 0.6rem);
    right: var(--gutter-right);
    z-index: 2;
    width: var(--post-w);
    height: 2.25rem;
    padding: 0;
    border-radius: 8px;
  }

  /* The last status and Load more are never under the bottom bar. */
  #content {
    --content-end: calc(var(--bottom-h) + env(safe-area-inset-bottom, 0px) + 1rem);
  }

  .menu,
  .menu.status-menu {
    left: var(--gutter-left);
    right: var(--gutter-right);
    width: auto;
  }

  /* The account menu stops above the bottom bar. */
  .menu:not(.status-menu) {
    max-height: calc(100dvh - var(--bar-h) - var(--bottom-h) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 12px);
  }

  /* The footer's icons, `⋯` included, on one row at 360 px; each keeps its
     own padding around it. */
  article > footer {
    gap: 0;
  }

  /* With their counts ("48K", "1.2K") the six of them fit 360 px only with
     less padding around each icon (#46), and in a wide sans-serif font only
     with the icons without a count no wider than the icon and its padding,
     about 28 px (over the 24 px a target needs): with DejaVu Sans, the only
     font on many Linux systems, a 2rem floor wrapped the row (#82). The
     icon and its count are centred in their button. */
  article > footer :is(.thread, .reply, [data-action], .more) {
    justify-content: center;
    min-width: 1.75rem;
    gap: 0;
    padding: 0 0.25rem;
  }

  article > footer :is(.thread, [data-action])[data-count]::after {
    margin-left: 0.15rem;
  }
}

/* Three four-character counts ("999K") are wider than the row at 360 px
   with DejaVu Sans (#84): rather than wrap, the buttons with a count give
   up part of their padding, and only as much as the row needs; the others
   keep their size, and the icon and count, which do not shrink, stay
   centred. The row then cannot wrap, so this holds only where the padding
   is enough: from 360 px and from 22.5rem (360 px at the default font
   size), with a 12 px scroll bar and DejaVu Sans, three "999K" need at
   most 5.1 px of a button's 8 px of padding, at any font size (three
   "999M" need all of it).
   Narrower, or with "Link copied" in the row, it wraps as before. Below
   40rem only, as #72's block below: at 40rem Edit and Delete are in it. */
@media (min-width: 360px) and (min-width: 22.5rem) and (width < 40rem) {
  article > footer:not(:has(.copied:not(:empty))) {
    flex-wrap: nowrap;
  }

  article > footer > button {
    flex-shrink: 0;
  }

  article > footer > :is(.thread, [data-action])[data-count]:not([data-count="0"]) {
    flex-shrink: 1;
  }

  /* Inside a button that gives up padding, the icon would shrink first. */
  article > footer > button::before,
  article > footer > button::after {
    flex-shrink: 0;
  }
}

/* Below 40rem, one's own Edit and Delete leave the footer for the menu
   (#72), so it keeps its six icons on one row; at 40rem itself they stay in
   the footer, as #72 says, though the rest of the phone layout starts there. */
@media not all and (min-width: 40rem) {
  article > footer :is(.edit-open, .delete, .delete-confirm, .keep) {
    display: none;
  }

  .status-menu > .status-own {
    display: block;
  }

  article > footer .more[data-own-only] {
    display: inline-flex;
  }
}

@media (prefers-reduced-motion: no-preference) {
  /* An attachment on its way, or being processed, breathes. */
  .attachment:is([data-stage="uploading"], [data-stage="processing"]) .attachment-thumb .icon {
    animation: breathe 1.2s ease-in-out infinite alternate;
  }

  @keyframes breathe {
    to {
      opacity: 0.35;
    }
  }

  .peek {
    animation: peek-in 120ms ease-out;
  }

  @keyframes peek-in {
    from {
      opacity: 0;
    }
  }

  button,
  summary {
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
  }

  .switch {
    transition: background-color 120ms ease;
  }

  .switch::after {
    transition: transform 120ms ease;
  }
}
