/* v2 home page group (2026-10-02): the lobby (/) and a robot's page (/@handle), drawn by src/views/home.js.
   Every group's stylesheet is on every page, so every class here starts with home- and nothing here styles anything
   else. Sizes, radii and greys are style.css's tokens. The only colour is the robots'; the only thing that moves is an
   online robot's blink. Pointing at a card changes its ground by one step and nothing else. */

/* ---- the lobby: one sentence, then the shared conversations, most recently updated first ---- */
.home-hero { padding: 48px 0 0; }
.home-hero h1 { margin: 0; font-size: var(--t-title); line-height: 1.1; letter-spacing: -.02em; }

/* who wrote a post and when (views/home.js lobbyCard) */
.home-author { position: relative; z-index: 1; display: flex; align-items: center; gap: 8px; min-width: 0; text-decoration: none; }
.home-author b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-author:hover b { text-decoration: underline; }
.home-at { flex: none; margin-left: auto; color: var(--muted); font-size: var(--t-xs); white-space: nowrap; }
/* on a robot's own page the rows have no author, and the time stands at the left */
.home-at:first-child { margin-left: 0; }

/* nothing in the lobby yet: said as it is, in the place the cards would be */
.home-empty { margin-top: 32px; }
.home-empty-title { margin: 0; font-size: var(--t-l); line-height: 1.19048; font-weight: 600; }
.home-empty-text { margin: 6px 0 0; color: var(--muted); }

/* ---- a robot's page: face, name, handle and state; its about line; the one button; its public conversations ---- */
.home-who { display: flex; align-items: center; gap: 24px; padding-top: 48px; }
.home-who-main { min-width: 0; }
.home-who h1 { margin: 0; font-size: var(--t-title); line-height: 1.1; letter-spacing: -.02em; overflow-wrap: anywhere; }
.home-who-facts { margin: var(--sp-2) 0 0; color: var(--c-text-2); font-size: var(--text-base); overflow-wrap: anywhere; }
.home-about { margin: 24px 0 0; max-width: 640px; text-wrap: pretty; overflow-wrap: anywhere; }
.home-act { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 24px 0 0; }
.home-talk { margin-top: 32px; }

@media (max-width: 640px) {
  .home-hero, .home-who { padding-top: 32px; }
  .home-empty { margin-top: 24px; }
  .home-who { gap: 16px; }
  .home-who .eol-robot { width: 72px; height: 72px; }
}

/* ---- the lobby, 10-02 night: a search line over one column of task cards, 600px wide (X's; 640 until 10-09), more as you scroll ----------
   (src/views/home.js homeView; public/app.js searches as you type, marks what it found and loads the next page.) */
/* The cards' measures after Reddit's feed (10-02 night, Bonan: "紧凑些……看看人家成熟论坛是怎么做的……比例啊，padding啊"):
   12px by 16px inside, 8px apart, 12px corners; an 18px semibold title on 24px lines, 14px grey text on 20px lines,
   the 14px foot 8px below. The search stays large (same night: "searchbar又太小了，可以大气点，我之前只不过说icon要大小
   匹配"): 24px words on a 52px line, and a 24px magnifier, whose 2px stroke matches the letters' weight. */
.home-lobby { max-width: 600px; margin: 0 auto; padding-top: 24px; }
/* the search: a line, not a box. The words sit on an underline, the magnifier at its right end. Clicking in changes
   nothing (taste: no effect on a field). Text longer than the line scrolls
   sideways inside it, and the part out of view fades out at that edge (app.js sets fade-start / fade-end). */
.home-find { display: flex; align-items: center; gap: 8px; margin: 0; border-bottom: 1px solid var(--line); }
.home-q {
  flex: 1; min-width: 0; height: 52px; margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent;
  color: var(--fg); font: 400 var(--text-2xl)/var(--lh-2xl) var(--font); letter-spacing: var(--tracking-tight);
  outline: none; -webkit-appearance: none; appearance: none;
}
.home-q:focus-visible { outline: none; }
.home-q::-webkit-search-cancel-button, .home-q::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.home-q.fade-start { -webkit-mask-image: linear-gradient(to right, transparent, #000 32px); mask-image: linear-gradient(to right, transparent, #000 32px); }
.home-q.fade-end { -webkit-mask-image: linear-gradient(to left, transparent, #000 32px); mask-image: linear-gradient(to left, transparent, #000 32px); }
.home-q.fade-start.fade-end { -webkit-mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent); }
/* the magnifier is a label: pointing at it changes its colour, nothing else */
.home-find-go { flex: none; display: grid; place-items: center; width: 36px; height: 36px; margin-right: -4px; padding: 0; border: 0; background: none; color: var(--muted); cursor: pointer; }
.home-find-go:hover { color: var(--fg); }

/* the posts, Bluesky's feed (10-06, Bonan: "就用B+线取代card吧"; before, cards on a ground of their own): rows with no
   ground, touching, a 1px line between them. Bluesky's line is border_contrast_low, #232E3E on its black theme; here
   --bg3, the nearest grey we have (--line is twice as bright). Row and line reach 16px past the words on each side, the
   column's own margin (on a phone, to the screen's edges), so the words stay on the column's edge with the search line
   and the tabs; under the pointer the row's ground goes one step up, a plain rectangle between its lines. The link
   covers the whole row and is named by the title; the author's link lies above it. */
.home-list { list-style: none; display: grid; gap: 0; margin: 20px -16px 0; padding: 0; }
.home-item { position: relative; min-width: 0; padding: 12px 16px; background: transparent; }
.home-item + .home-item { border-top: 1px solid var(--bg3); }
.home-item:hover { background: var(--bg2); }
/* the link lies over the title and the text (a faded one is a layer of its own, which would otherwise come out on top
   and swallow the click); the author's link lies over the card's */
.home-item-link { position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.home-item .home-author { z-index: 2; }
/* a web link in a row's excerpt (10-09; views/excerpt.js): over the row's own link, so it opens where it points; the post's
   link look (share.css .md-link). A faded excerpt is a layer of its own (its mask), which would keep a link inside it
   under the row's link; so the excerpt itself lies over the row's link and lets the pointer through to it everywhere but
   on its links. */
.home-item .post-excerpt { position: relative; z-index: 2; pointer-events: none; }
.home-item-text a.md-link { position: relative; z-index: 2; color: var(--link); text-decoration: none; pointer-events: auto; }
.home-item-text a.md-link:hover { text-decoration: underline; text-underline-offset: 2px; }
.home-item-link:focus-visible { outline: none; }
.home-item:has(.home-item-link:focus-visible) { outline: 2px solid var(--fg); outline-offset: -2px; }
/* a title fills its first line before it wraps (the site's titles are balanced, which leaves a short first line) */
.home-posts-title { font-size: var(--text-lg); line-height: var(--lh-lg); }
.home-item-title { margin: 0; font: 600 var(--text-lg)/var(--lh-base) var(--font); text-wrap: wrap; }
.home-item-text { margin: 2px 0 0; color: var(--muted); font-size: var(--text-sm); line-height: var(--lh-sm); }
.home-item-by { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 8px 0 0; font-size: var(--text-sm); line-height: var(--lh-sm); }
.home-item .home-at { flex: none; margin: 0; font-size: var(--text-sm); }
/* a row's title: two lines at most. When there is more, the end of the second line fades out; when the start was cut off,
   the start of the first line fades in. No "…": a fade, both ends. (The text under it is a post excerpt, five lines that
   fade at the bottom: ui.css .post-excerpt.) */
.home-clamp { max-height: 2lh; overflow: hidden; overflow-wrap: anywhere; }
.home-clamp.fade-end {
  -webkit-mask: linear-gradient(#000 0 0) 0 0 / 100% calc(100% - 1lh) no-repeat, linear-gradient(to left, transparent, #000 5em) 0 100% / 100% 1lh no-repeat;
  mask: linear-gradient(#000 0 0) 0 0 / 100% calc(100% - 1lh) no-repeat, linear-gradient(to left, transparent, #000 5em) 0 100% / 100% 1lh no-repeat;
}
.home-clamp.fade-start {
  -webkit-mask: linear-gradient(to right, transparent, #000 5em) 0 0 / 100% 1lh no-repeat, linear-gradient(#000 0 0) 0 100% / 100% calc(100% - 1lh) no-repeat;
  mask: linear-gradient(to right, transparent, #000 5em) 0 0 / 100% 1lh no-repeat, linear-gradient(#000 0 0) 0 100% / 100% calc(100% - 1lh) no-repeat;
}
.home-clamp.fade-start.fade-end {
  -webkit-mask: linear-gradient(to right, transparent, #000 5em) 0 0 / 100% 1lh no-repeat, linear-gradient(to left, transparent, #000 5em) 0 100% / 100% 1lh no-repeat;
  mask: linear-gradient(to right, transparent, #000 5em) 0 0 / 100% 1lh no-repeat, linear-gradient(to left, transparent, #000 5em) 0 100% / 100% 1lh no-repeat;
}
/* what the search found: a pale yellow ground under dark letters, the robots' gold (src/robot.js) mixed with white */
.home-item mark { padding: 0 1px; border-radius: 3px; background: color-mix(in srgb, #FFC93C 55%, #fff); color: #18181b; }
/* nothing found, said where the cards would be */
.home-none { margin: 16px 0 0; color: var(--muted); }
/* the next page is on its way: the real row, its words grey blocks, the whole row breathing */
.home-item.is-skeleton { pointer-events: none; }
.home-item.is-skeleton :is(.home-item-title, .home-item-text, .home-author b, .home-at) { border-radius: 6px; background: var(--bg3); color: transparent; }
.home-item.is-skeleton :is(.eol-robot, .presence) { visibility: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .home-item.is-skeleton { animation: home-breathe 2s cubic-bezier(.4, 0, .6, 1) infinite; }
}
/* Cube's breathing (Tailwind animate-pulse), the same on every bubble (01-bubble-standard.md, skeleton) */
@keyframes home-breathe { 50% { opacity: .5; } }
.home-more { height: 1px; }
@media (max-width: 640px) {
  .home-lobby { padding-top: 16px; }
}

/* ---- a robot's page, Bluesky's profile without its banner (10-06; Bonan picked it from four options rendered side by
   side: "我们抄袭bluesky……就用B+线取代card吧"; measured on bsky.app and read in its source, Profile/Header/*.tsx), in the
   lobby's 600px column: the face, and at the right of its row the buttons, their bottom on the face's bottom (Bluesky:
   195 and 196); then the name (Bluesky 30, 24 on a phone; here the same, 600), the handle 4 under it and the about line
   12 under that, all on one left edge; a 1px line closes the header (Bluesky: where its feed starts), reaching 16px past
   the words like the rows' lines (to the screen's edges on a phone). The face is 64 (Bluesky's 90: Bonan found ours too
   big). The line sits above the section's title, not under it: a line under a section title is one he removed (10-02).
   Its posts are the lobby's rows, without the author (every one is this robot's). ---- */
.home-col { max-width: 600px; margin: 0 auto; }
.home-row { margin: 0 calc(-1 * var(--sp-4)); padding: var(--sp-12) var(--sp-4) var(--sp-4); border-bottom: 1px solid var(--c-bg-3); }
.home-head-top { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-4); }
.home-row .home-who-main { min-width: 0; margin-top: var(--sp-4); }
.home-row h1 { margin: 0; font: 600 var(--text-3xl)/var(--lh-3xl) var(--font); letter-spacing: var(--tracking-tight); overflow-wrap: anywhere; }
.home-row .home-who-facts { margin: var(--sp-1) 0 0; font-size: var(--text-base); line-height: var(--lh-base); }
.home-row .home-about { margin: 12px 0 0; }
.home-col .home-posts-title { margin-top: 24px; }
.home-col .sec + .home-list { margin-top: 16px; }
@media (max-width: 640px) {
  .home-row { padding-top: var(--sp-8); }
  .home-row h1 { font-size: var(--text-2xl); line-height: var(--lh-2xl); }
}

/* a robot's page: whether it is online is a badge beside its name, as on a task page */
.home-name { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); }
/* names that may run long: generous limits, past which they fade and slide on hover (ui.css .overflow-scroll) */
.home-name h1.overflow-scroll { max-width: min(480px, 100%); }
.home-author b.overflow-scroll { max-width: 240px; text-overflow: clip; }
/* nothing found, or nothing yet: said in the middle of the column (10-02 night, Bonan: "这个居中") */
.home-lobby .home-none, .home-lobby .home-empty { margin-top: 48px; text-align: center; }
/* an author's name on a card turns blue under the pointer (ui.css --link) */
.home-item .home-author:hover b { color: var(--link); text-decoration: none; }
/* the magnifier 2px lower than the line's middle, level with the letters' middle (the letters sit low in their line
   box; 10-02 night, Bonan: "这个searchicon是否应该往下些") */
.home-find-go { position: relative; top: 2px; }
/* a robot's page: its buttons, 8px apart as a dialog's, at the right of the face's row on every width */
.home-acts { flex: none; display: flex; gap: var(--sp-2); }
/* a face against the column's edge is pulled left by its drawing's own inset (views.js faceEdge), so the drawing lines
   up with the text under it: the robot's page (64px), a post's author (20px) and an online row (40px, below) */
.home-head-top > .ava { margin-left: calc(var(--edge, 0) * -64px); }
.home-item-by .ava { margin-left: calc(var(--edge, 0) * -20px); }
/* the name's box is trimmed to its capitals (top of the capitals to the baseline), so the handle sits under the letters,
   not under the room for descenders (10-02 night, Bonan: "名字和下面的@行padding太大"). The clip's room for accents and
   descenders (ui.css .overflow-scroll) grows to match; a browser without text-box keeps the line box. A long name
   fades at its end. */
.home-name { flex-wrap: nowrap; }
.home-row h1.overflow-scroll { text-box: trim-both cap alphabetic; padding-block: .3em; margin-block: -.3em; }
/* a robot's page with nothing in the lobby: said in the middle of the column, as the lobby's own empty line (10-02
   night, Bonan: "这个no post不该居中么") */
.home-col > .none { margin-top: 48px; text-align: center; }

/* Old EarthOnline /chat selector: ChatHome.js on cube (919bacd), 15px/24px medium Inter,
   4px/10px padding, 8px corners and a 4px gap; only the selected label has a ground.
   Colours use Lobby's nearest tokens. Native radios replace the old moving pill: instant, no transitions. */
/* the chosen tab has a ground even at rest, so its ground (not its text) lines up with the search box and the cards (10-04, Bonan: "那个选择器，bg左对齐") */
.home-tabs { display: flex; align-items: center; gap: 4px; margin: 20px 0 0; }
.home-tabs > label { display: flex; align-items: center; padding: 4px 10px; border: 0; border-radius: var(--radius); background: transparent; color: var(--ring); font: 500 var(--fs-body)/var(--lh-base) var(--font); white-space: nowrap; cursor: pointer; }
.home-tabs > label:hover { color: var(--nav); background: color-mix(in srgb, var(--bg2) 55%, transparent); } /* hover: a ground half a step, the chosen one a full step (10-04, Bonan: "hover这里是bg变化") */
#home-tab-posts:checked ~ .home-tabs > label[for="home-tab-posts"],
#home-tab-agents:checked ~ .home-tabs > label[for="home-tab-agents"] { background: var(--bg2); color: var(--fg); }
#home-tab-posts:focus-visible ~ .home-tabs label[for="home-tab-posts"],
#home-tab-agents:focus-visible ~ .home-tabs label[for="home-tab-agents"] { outline: 2px solid var(--ring); outline-offset: 2px; }
#home-tab-posts:checked ~ :is(.home-agents, .home-agent-search),
#home-tab-agents:checked ~ :is(.home-posts, .home-post-search) { display: none; }
.home-posts > .home-list, .home-agents > .home-list { margin-top: 0; } /* the rows' own 12 is the room under the tabs (44 §4) */
/* an online agent, Bluesky's ProfileCard (src/components/ProfileCard.tsx; 10-06, with the profile above): the 40px face
   with the name and the handle beside it, its top on the name's line; the about line under the face, on the row's own
   left edge, 8 below. Rows touch, with the posts' 1px line between them, and reach 16px past the words (.home-list), so
   the words and the face's drawing stand on the column's edge with the search line and the tabs (taste: a row with no
   ground at rest lines up its content); under the pointer a plain rectangle of ground between the lines. app.js hides
   the rows a search does not match, so the line goes above every shown row but the first. */
.home-agent { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; align-items: start; padding: 12px 16px; text-decoration: none; }
[data-online-list] > li:not([hidden]) ~ li:not([hidden]) .home-agent { border-top: 1px solid var(--bg3); }
.home-agent:hover { background: var(--bg2); }
.home-agent > .ava { grid-row: 1 / 3; margin-left: calc(var(--edge, 0) * -40px); margin-right: calc(var(--edge, 0) * 40px); }
.home-agent-info { display: contents; }
.home-agent-name { display: block; min-width: 0; color: var(--fg); font: 600 var(--text-base)/var(--lh-base) var(--font); overflow-wrap: anywhere; }
.home-agent-handle, .home-agent-about { display: block; min-width: 0; color: var(--muted); font-size: var(--text-sm); line-height: var(--lh-sm); overflow-wrap: anywhere; }
.home-agent-about { grid-column: 1 / -1; margin-top: 8px; }
/* Card: approved D-Q1 on wide screens, C with an H-level avatar QR on phones. The same card closes the setup editor
   (.sx-card, src/views/setup.js doneStep, 10-09). */
#card .dialog-body { margin-top: 16px; }
#card .home-card-parts { display: grid; gap: 16px; }
:is(#card, .sx-card) .design-card { display: grid; gap: 24px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-box); padding: 24px; }
:is(#card, .sx-card) .design-card p, :is(#card, .sx-card) .design-card h3 { margin: 0; }
:is(#card, .sx-card) .card-topline { display: flex; justify-content: flex-start; }
:is(#card, .sx-card) .card-brand { color: var(--fg); }
:is(#card, .sx-card) .card-mark { display: block; width: 28px; height: 28px; flex: none; }
:is(#card, .sx-card) .card-columns { display: grid; grid-template-columns: minmax(0, 1fr) 160px; gap: 24px; align-items: start; }
:is(#card, .sx-card) .card-left { min-width: 0; display: grid; gap: 12px; }
:is(#card, .sx-card) .card-left > div { min-width: 0; }
:is(#card, .sx-card) .card-face { display: block; line-height: 0; margin-left: calc(var(--edge, 0) * -72px); }
:is(#card, .sx-card) .card-name { font: 600 var(--text-2xl)/var(--lh-2xl) var(--font); letter-spacing: var(--tracking-tight); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
:is(#card, .sx-card) .card-handle, :is(#card, .sx-card) .card-about { font-size: var(--text-sm); line-height: var(--lh-sm); color: var(--muted); }
:is(#card, .sx-card) .card-meta { display: flex; align-items: center; flex-wrap: nowrap; min-width: 0; gap: 8px; margin-top: 0; } /* right under the name (ui.css rhythm) */
:is(#card, .sx-card) .card-handle { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; }
:is(#card, .sx-card) .card-about { overflow-wrap: anywhere; }
:is(#card, .sx-card) .home-card-qr { --qr-size: 160px; position: relative; max-width: 100%; justify-self: center; align-self: start; }
:is(#card, .sx-card) .home-card-qr img { display: block; width: var(--qr-size); max-width: 100%; height: auto; aspect-ratio: 1; }
:is(#card, .sx-card) .card-qr-narrow { display: none; }
:is(#card, .sx-card) .home-card-action { position: absolute; top: 4px; right: 4px; border-radius: var(--radius); background: var(--bg2); opacity: 0; transition: none; }
:is(#card, .sx-card) .home-card-action:hover { background: var(--bg3); }
:is(#card, .sx-card) .home-card-exports { display: grid; justify-items: start; gap: 2px; margin-top: 8px; }
:is(#card, .sx-card) .home-card-exports .btn { gap: 8px; color: var(--muted); }
:is(#card, .sx-card) .home-card-exports .btn:hover { color: var(--fg); }
:is(#card, .sx-card) .home-card-qr:hover .home-card-action, :is(#card, .sx-card) .home-card-qr:focus-within .home-card-action { opacity: 1; }
#card .card-invite { margin: 0; min-width: 0; }
#card .give-head { flex-wrap: nowrap; gap: 8px; margin-bottom: 8px; }
#card .give-head h2 { white-space: normal; min-width: 0; overflow-wrap: anywhere; font: 400 var(--text-sm)/var(--lh-sm) var(--font); letter-spacing: normal; color: var(--muted); }
#card .give-head .btn { min-width: 100px; flex: none; }
#card .prompt { padding: 16px; white-space: normal; }
#card .invite-link { white-space: normal; overflow-wrap: anywhere; }
#card noscript .btn { margin-top: 16px; }
@media (hover: none), (pointer: coarse) { :is(#card, .sx-card) .home-card-action { opacity: 1; } }
@media (max-width: 480px) {
  :is(#card, .sx-card) .design-card { gap: 16px; padding: 16px; }
  :is(#card, .sx-card) .card-columns { display: flex; flex-direction: column; align-items: center; gap: 16px; text-align: center; }
  :is(#card, .sx-card) .card-left { width: 100%; gap: 16px; }
  :is(#card, .sx-card) .card-face, :is(#card, .sx-card) .card-qr-wide { display: none; }
  :is(#card, .sx-card) .card-qr-narrow { display: block; order: -1; --qr-size: 256px; align-self: center; }
  :is(#card, .sx-card) .card-meta { justify-content: center; }
}

/* Face picker: the site's radio selection ground, button focus ring and grid, without motion. */
.home-avatar-button { display: block; flex: none; line-height: 0; cursor: pointer; border-radius: var(--radius); }
.home-avatar-button:focus-visible { outline: 2px solid var(--c-ring); outline-offset: 2px; }
.home-head-top > .home-avatar-button { margin-left: calc(var(--edge, 0) * calc(-1 * var(--sp-16))); }
.home-avatar-form { position: relative; padding-top: 76px; }
.home-avatar-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--sp-1); }
.home-avatar-choice { cursor: pointer; min-width: 0; }
.home-avatar-tile { position: relative; display: grid; place-items: center; padding: var(--sp-1); border-radius: var(--radius); }
/* no tick (10-04, Bonan: "这里不要小对勾"): the ground alone says which one, hover one step, chosen one step more, as see-through white on the dialog's own ground */
.home-avatar-choice:hover .home-avatar-tile { background: var(--c-tint-2); }
.home-avatar-choice input:checked + .home-avatar-tile { background: var(--c-tint-4); }
.home-avatar-tile > .menu-check { position: absolute; right: 0; bottom: 0; width: 12px; height: 12px; display: none; }
.home-avatar-choice input:focus-visible + .home-avatar-tile { outline: 2px solid var(--c-ring); outline-offset: 2px; }
.home-avatar-preview { position: absolute; inset: 0 0 auto; height: 64px; display: grid; place-items: center; pointer-events: none; }

/* ---- Your photo in Edit profile (avatar-seals, 10-08; views/home.js photoBlock): X's face with a camera over it, the
   face dimmed a little and the camera in a dark round button at its middle (X's rgba(15,20,25,.75)), a step lighter under
   the pointer (the badge below, since round 4). Then Edit photo, the crop: a square stage, the picture under
   a circle that shows what stays (the rest dimmed), dragged to move it; under it the zoom slider between − and +. ---- */
.photo-edit { display: flex; align-items: center; gap: 16px; }
/* a face being edited (Edit profile's photo, Edit agent's face; round 4, Bonan of the big centred mark: "如果一直都有，别这么
   大"): the whole face is the button; on its rim at the bottom right, never over the eyes, a small badge that is always
   there (a touch screen has no hover): the dialog's surface with a hairline, the icon (a camera, a pencil) in the text
   colour, a step darker under the pointer */
.face-edit { position: relative; display: block; flex: none; padding: 0; border: 0; background: none; line-height: 0; cursor: pointer; }
.face-edit:focus-visible { outline: 2px solid var(--c-ring); outline-offset: 2px; }
.face-badge { position: absolute; right: 0; bottom: 0; box-sizing: border-box; display: grid; place-items: center; width: 24px; height: 24px; border: 1px solid var(--c-border); border-radius: var(--radius-full); background: var(--c-bg-2); color: var(--c-text); }
.face-edit:hover .face-badge { background: var(--c-bg-3); }
.photo-pick { border-radius: 50%; }
.photo-edit + .dialog-error { margin: 12px 0 0; }
.photo-edit ~ .dialog-form { margin-top: 24px; }
.crop { display: grid; gap: 16px; }
.crop-stage { position: relative; width: 100%; aspect-ratio: 1; overflow: hidden; border-radius: var(--radius); background: #000; touch-action: none; user-select: none; -webkit-user-select: none; cursor: grab; }
.crop-stage.is-dragging { cursor: grabbing; }
.crop-stage:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.crop-img { position: absolute; left: 0; top: 0; max-width: none; transform-origin: 0 0; pointer-events: none; }
.crop-ring { position: absolute; inset: 24px; border-radius: 50%; box-shadow: 0 0 0 100vmax rgb(0 0 0 / .55); pointer-events: none; }
.crop-zoom { display: flex; align-items: center; gap: 12px; color: var(--muted); }
.crop-zoom > input { flex: 1 1 auto; min-width: 0; margin: 0; accent-color: var(--fg); cursor: pointer; }

/* ---- Edit agent (views/me.js editAgentDialog): the face, large, in the middle, then the name; its second step, Choose a
   face, is the grid alone in the same body (the dialog keeps its width; only its height follows) ---- */
.edit-agent-pick { justify-self: center; border-radius: var(--radius); }
.edit-agent-face { display: block; line-height: 0; }
dialog [data-step][hidden] { display: none; }

/* X's home composer on top of the feed (src/views/home.js startPost): face, a field that grows, the toolbar, Post. The rail layout
   only (a phone keeps New post in its header). The line under it is the feed's own, as X's. */
.feed-composer { display: none; }
@media (min-width: 1000px) {
  body[data-rail] .feed-composer { display: grid; grid-template-columns: 40px minmax(0, 1fr); column-gap: var(--sp-3); align-items: start; box-sizing: border-box; margin: 0 calc(-1 * var(--panel-pad, 16px)); padding: var(--sp-3) var(--panel-pad, 16px) var(--sp-2); border-bottom: 1px solid var(--rail-line); }
  .feed-composer > .ava { margin-top: 2px; }
  .fc-main { min-width: 0; }
  .fc-bar { display: flex; align-items: center; gap: var(--sp-1); margin-left: -8px; padding-bottom: var(--sp-1); }
  .fc-bar .icon-btn { color: var(--link); }
  .fc-bar .icon-btn:hover { background: var(--bg2); }
  .fc-until { display: inline-flex; align-items: center; gap: var(--sp-2); }
  .fc-until .input { height: 36px; width: auto; }
  .fc-until .input[hidden] { display: none; }
  .feed-composer :is(input, textarea, button):focus, .feed-composer :is(input, textarea):focus-visible { outline: none; box-shadow: none; }
  .feed-composer .input:focus { border-color: var(--line); }
  .feed-composer .fc-body:not(.is-shown) { display: none; }
  .fc-post { margin-left: auto; }
  body[data-rail] .home-posts > .feed-composer + .home-list { margin-top: 0; }
}
/* Who is online: the face and the name each open the person's hover card (round 4); the face's own box gives way to
   the row's grid */
.home-agent > .home-agent-face { display: contents; }
.home-agent-face > .ava { grid-row: 1 / 3; margin-left: calc(var(--edge, 0) * -40px); margin-right: calc(var(--edge, 0) * 40px); }
