/* The rail and the page beside it (src/views.js rail()). 10-08: X's desktop (R0a); the same evening, seen live at 1920px
   wide, Bonan: "太逼仄了，左侧sidebar永远闭上，然后右侧留出更多位置" (too cramped: keep the left bar closed, give the right more
   room). So the rail is X's collapsed one on every desktop width, and it stands where Threads' does: down the window's
   left edge, the page centred in the window beside it. 10-09 (x-layout-2): from 1000px it is X's group instead, the rail
   glued to the page's left line and the two (with the right column) centred together ("X's group", below), and from
   1267px (1320 until 10-09, X's widths since) it opens with its names, as X's ("the open rail", below). Every page loads this sheet; it acts only on a page drawn with
   the rail (body[data-rail]) and only wider than a phone: at 760px and less the rail goes and the header is what it was
   (10-04, Cube's narrow header, one menu).
   - the rail: 88px of icons (26px) in 50px round targets 4px apart (X collapsed), the mark at the top, New post a blue +
     under the places, your face at the foot 12px from the bottom; each icon has the site's one tooltip to its right
   - the page: a column of 680px centred in the window (not in the room beside the rail; Threads'), between two 1px lines,
     no corners, no card; the window scrolls, the rail stays. The inbox, the docs and settings take 1100px (X's Messages
     and Settings: a 390px list beside the page; under 926px one column). Where the window is too narrow to centre, the
     page starts at the rail.
   - each page's title row is X's header: sticky at the top of the column, 53px, the page's ground at 85% under a 12px
     blur, a 1px line under it, the title 20px, a back arrow before it where one drilled in, a grey line under it on a
     profile
   - rows reach both lines, 12px by 16px inside, a line under each, one step of ground under the pointer
   - the hairline is X's #2f3336 on a dark page; on a light one the app's --line (#d0d7de, GitHub's; X's #eff3f4 until
     10-09, too faint), the same for the column, the header and rows
   Kept from Bonan's taste where X differs: the site's one button height (New post 36px, X's Post 52), titles at 600, the
   lobby's underline search, the inbox's inset rows with no lines between them. Taste: a row pointed at takes one step
   of ground at once; the current place has a heavier icon, no ground; nothing moves. */

.rail { display: none; }

@media (min-width: 761px) {
  body[data-rail] {
    /* the dividers beside the rail: in light the app's one line, --line (x-layout-2, 10-09); in the dark X's #2f3336, as before */
    --rail-line: var(--c-divider);
    --rail-w: 88px;
    padding-left: var(--rail-w);
  }
  body[data-rail] header.top { display: none; }
  /* a page drawn with a dialog open is fixed behind it (ui.css .dialog-behind[inert]) and keeps the rail's room */
  body[data-rail] .dialog-behind[inert] { padding-left: var(--rail-w); }
  /* the page centred in the window: its left edge (100% + the rail - its width) / 2 - the rail from the rail's edge, or at
     the rail where there is no room for that */
  body[data-rail] main { --rail-area: 680px; }
  /* 10-08 polish (Bonan at 1920: "左右空位太大了"; width option A): from 1280px the column is 800 (its words 768 wide,
     ChatGPT's reading measure, 48rem); the two-column pages' 1240 from 1600px went with X's group (below, 10-09) */
  @media (min-width: 1280px) { body[data-rail] main { --rail-area: 800px; } }
  body[data-rail] :is(main.wrap, main.ib) { margin-left: max(0px, calc((100% + var(--rail-w) - min(var(--rail-area), 100%)) / 2 - var(--rail-w))); }

  .rail { position: fixed; inset: 0 auto 0 0; z-index: 10; display: block; width: var(--rail-w); }
  /* ---- X's group (x-layout-2, 10-09; Bonan on X's post page: "sidebar 稍微往中间些，然后 sidebar 的右边界和内容的左边界是一体的").
     From 1000px the rail, the column and the right column are one group centred in the window, as on x.com: the rail's
     right edge is the column's left line (one 1px line, the column's own; the rail draws none), and the rail stands at the
     same x on every page at a given width (X's never moves). For that every page has the same room beside the rail, the
     group's: --grp-w, X's own: the column 600 + 30 + the right column 350 = 980 (10-09, Bonan's screen, 1920 at 150%, is
     1277 wide: X opened its rail there and showed its whole group, ours, 640 + 32 + 350 = 1022, did not; "copy X's exact
     desktop widths"). A page with a right column fills it; settings and the docs, which have none, keep their own room
     (1022, below; X's Settings: the list 390, the page beside it the rest); the inbox is the exception that the glued rail is for (Bonan: "这样一来内容位置可以更多，比如 inbox
     就可以更宽"): it starts on the rail's line and runs on past the group to the window's right edge, at most 1240 (below);
     a page with neither (your posts, nothing here) keeps its own width at the rail's side and leaves the rest of the
     group empty. The space beyond the group is the window's, split evenly on both sides; under
     1068px (88 + 980) there is none, the rail is at the window's edge and the page gives way (the column, as before). The rail is
     fixed with no left of its own: it stands where the body's flow puts it (its static position, as X's header does), the
     body's padding being the space before the group plus the rail's width, and the rail's own margin taking that width
     back. Under 1000px everything is as it was. ---- */
  @media (min-width: 1000px) {
    /* (10-09, chat-parity) under a dialog the root gives up its scrollbar strip (ui.css html.dialog-open), which widens the 100%
       this is measured on: --lock-gutter takes it back, so the group stays where it stood */
    body[data-rail] { --grp-w: 980px; --grp-before: max(0px, (100% - var(--lock-gutter, 0px) - var(--rail-w) - var(--grp-w)) / 2); padding-left: calc(var(--grp-before) + var(--rail-w)); }
    /* whole pixels, so the line is never drawn across two (the open rail's group, 1255, is odd) */
    @supports (width: round(down, 1.5px, 1px)) { body[data-rail] { --grp-before: max(0px, round(down, (100% - var(--lock-gutter, 0px) - var(--rail-w) - var(--grp-w)) / 2, 1px)); } }
    body[data-rail] .dialog-behind[inert] { padding-left: calc(var(--grp-before) + var(--rail-w)); }
    body[data-rail] :is(main.wrap, main.ib) { margin-left: 0; }
    .rail { left: auto; margin-left: calc(-1 * var(--rail-w)); }
    /* (devil-railfix, 10-13) a visitor on a profile has no right column (views.js lineModule): the rail and the column are the group, centred,
       as the visitor's chat page centres its one column, not the column on its left with the third column's room left empty */
    body[data-rail]:has(main.no-rcol) { --grp-w: 680px; }
    @media (min-width: 1280px) { body[data-rail]:has(main.no-rcol) { --grp-w: 800px; } }
  }
  .rail-in { box-sizing: border-box; display: flex; flex-direction: column; align-items: center; height: 100%; padding: var(--sp-2) var(--sp-1); overflow-y: auto; scrollbar-width: none; --bar: none; }
  .rail-in::-webkit-scrollbar { display: none; }
  /* the mark: the lobby (there is no separate Home); 28px, the header's size, in X's 52px round target */
  .rail-logo { display: grid; place-items: center; flex: none; width: 52px; height: 52px; margin: 0 0 var(--sp-1); border-radius: var(--radius-full); }
  .rail-logo .logo { display: block; }
  /* the mark and your face are not rows: nothing changes under the pointer (10-08 polish, Bonan: "hover不要给bg这个usericon",
     then the mark the same; Threads' mark) */
  /* the current place is told by colour, not weight (10-08 polish, Bonan: "这个选择特效让他变色嘛，不要单纯加粗，太蠢了";
     Threads' rail): the other places' icons grey, the current one in the text's colour, the same 2px stroke, no ground */
  .rail-item { display: flex; align-items: center; flex: none; box-sizing: border-box; height: 50px; margin: var(--sp-1) 0; padding: 0 var(--sp-3); border-radius: var(--radius-full); color: var(--c-text-2); text-decoration: none; -webkit-tap-highlight-color: transparent; }
  .rail-item[aria-current] { color: var(--c-text); }
  .rail-item:hover { background: var(--c-bg-2); }
  .rail-item[data-rail-agent][aria-current] { background: var(--c-bg-2); } /* the face keeps its own colour, so the page it is on shows as the hover ground does */
  .rail-ico { position: relative; display: grid; place-items: center; width: 26px; height: 26px; }
  .rail-ico > svg { display: block; }
  .rail-item:focus-visible, .rail-logo:focus-visible { outline: 2px solid var(--c-ring); outline-offset: -2px; }
  /* the inbox's count (views.js inboxBadge: blue when something waits for you, else grey; red is only for errors and danger) and My profile's dot */
  /* (10-10, Bonan: "这应该是右上角，而不是右下角"; X's, Slack's, iOS's) the count on the icon's top-right corner, a little over
     its edge, growing rightwards for 2 and 3 digits; out of the flow, so the icon stands where it stood */
  .rail-ico > .count[hidden] { display: none; }
  .rail-ico > .count { position: absolute; top: -7px; left: 14px; outline: 2px solid var(--c-bg); }
  /* My agent's two faces (views.js agentIcon): the one that is the agent's state shows, on this page or any, apart from whether it is the page one is on (that is the item's label colour, as the others) */
  .rail-agent-face { display: grid; flex: none; }
  .rail-agent-face > svg { grid-area: 1 / 1; width: 100%; height: 100%; }
  /* (devil-railface) the one that is not the state is display:none on itself (views.js agentIcon, app.js showAgent), never by a rule here:
     a tab open across a deploy kept the old rail.css, which had no such rule, and showed both, stacked */
  .rail-dot { position: absolute; top: -2px; right: -3px; width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--c-accent); outline: 2px solid var(--c-bg); }
  /* New post: X's and Bluesky's collapsed Post, a filled circle the account avatar's size (40), the site's one
     blue, the + centred (10-08, Bonan: "如果其他hover是圆形bg，那这个+是不是也是圆形"); its hover is the blue button's own */
  .rail-post { flex: none; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; width: 40px; height: 40px; min-width: 0; margin: var(--sp-3) 0; padding: 0; border-radius: var(--radius-full); }
  .rail-post > svg { width: 20px; height: 20px; }
  /* you at the foot (X's account switcher, collapsed): the face alone; no transition (10-06) */
  .rail-foot { display: flex; align-items: center; flex: none; box-sizing: border-box; height: 64px; margin: auto 0 var(--sp-1); padding: 0 var(--sp-3); border: 0; border-radius: var(--radius-full); background: none; color: var(--c-text); cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .rail-foot:focus-visible { outline: 2px solid var(--c-ring); outline-offset: -2px; }
  .rail-me .face-dot { pointer-events: none; }
  /* the words are the open rail's (below); closed, the icons alone and each one's hint */
  .rail-label, .rail-who { display: none; }

  /* ---- the open rail (x-layout-2, 10-09; Bonan: "既然 sidebar 要和内容贴住，不如抄袭 X，有位置可以让 sidebar 弹开，当然弹开的
     时候呢，不要有所谓的 hover 出解释标签了"; it was closed at every width from 10-08, "左侧sidebar永远闭上"). X's nav: where the
     open group fits the window (275 + 980 = 1255, X's, and the page's 12px scrollbar (ui.css): from 1267px; X opens at
     1265; 10-09, it was 1297 and 1320 with our 640 column, so Bonan's 1277-wide screen had the closed rail) the
     rail is 275 wide, each place a row of its icon and its name, the name 18/28 (--text-lg) in the icon's colour (grey, the
     current place in the text's colour: told by colour, not weight); a row pointed at takes one step of ground round its
     icon and name (X's pill); New post X's wide Post, the site's blue button 40 high (shadcn's lg) with its + and its words;
     your face at the foot with your name and @handle beside it (X's account button), a row like the others. No hints: the
     words are on screen (views.js railTip, data-tip-media). The rail's left keeps 12 to the mark, the icons, the button and
     the face, so they stand on one line. Narrower, the closed rail as before. ---- */
  @media (min-width: 1267px) {
    body[data-rail]:not([data-rail="closed"]) { --rail-w: 275px; }
    body:not([data-rail="closed"]) .rail-in { align-items: flex-start; padding: var(--sp-2) var(--sp-3); }
    body:not([data-rail="closed"]) .rail-item { gap: var(--sp-5); padding-right: var(--sp-6); } /* rows are 50 high closed and open: the 28px name must not make them 52 (10-09, icons stay on one y) */
    body:not([data-rail="closed"]) .rail-label { display: block; font: 400 var(--text-lg)/var(--lh-lg) var(--font); white-space: nowrap; }
    body:not([data-rail="closed"]) .rail-post { align-self: stretch; gap: var(--sp-2); width: auto; margin: var(--sp-3) var(--sp-3) var(--sp-3) 0; padding: 0 var(--sp-6); }
    body:not([data-rail="closed"]) .rail-post > .rail-label { display: inline; font: inherit; }
    body:not([data-rail="closed"]) .rail-foot { align-self: stretch; gap: var(--sp-3); text-align: left; }
    body:not([data-rail="closed"]) .rail-foot:hover { background: var(--c-bg-2); }
    body:not([data-rail="closed"]) .rail-who { display: grid; flex: 1 1 auto; min-width: 0; }
    body:not([data-rail="closed"]) .rail-who > b { font: var(--level-item); color: var(--c-text); }
    body:not([data-rail="closed"]) .rail-who > span { font: var(--level-body); line-height: var(--lh-item); color: var(--c-text-2); } /* the handle under the name (ui.css rhythm) */
  }

  /* ---- the inbox's closed rail (10-09, Bonan: "进入 inbox 就和 X 一样，sidebar 直接收起来了，位置都留给 inbox 本身"; X's
     Messages): on the inbox (body data-rail="closed", views.js RAIL_CLOSED, drawn so by the server: nothing moves when it
     comes) the rail stays closed at every width, its icons alone with their hints, New post the round +, your face alone,
     the count on the inbox's icon. Where other pages open it (1267px and up) it keeps their left edge (the open group's
     --grp-before), and the room its names would take, and the group's beyond it, is the inbox's: the list's column (390,
     X's) and the conversation, which takes the rest, to the window's right edge. Narrower nothing changes: the rail is
     closed there on every page. ---- */
  @media (min-width: 1267px) {
    body[data-rail="closed"] {
      --grp-before: max(0px, (100% - var(--lock-gutter, 0px) - 275px - var(--grp-w)) / 2);
      padding-left: calc(var(--grp-before) + var(--rail-w));
    }
    @supports (width: round(down, 1.5px, 1px)) { body[data-rail="closed"] { --grp-before: max(0px, round(down, (100% - var(--lock-gutter, 0px) - 275px - var(--grp-w)) / 2, 1px)); } }
    html body[data-rail="closed"] main.ib { --rail-area: 100%; } /* over the inbox's 1240 (below) */
  }
}

/* the menus over the foot: your account menu (#me-menu, the header's own, its rows for a wide window shown) and the
   signed-out menu (#rail-menu), above the foot with their left edges on its left edge (X's account menu) */
.rail-me { anchor-name: --rail-me; }
.rail-more { anchor-name: --rail-more; }
#rail-menu { position-anchor: --rail-more; width: 272px; }
@media (max-width: 760px) { #me-menu .menu-wide { display: none; } }
@media (min-width: 761px) {
  body[data-rail] #me-menu { position-anchor: --rail-me; }
  @supports (anchor-name: --a) {
    body[data-rail] #me-menu, #rail-menu { inset: auto auto calc(anchor(top) + 6px) anchor(left); }
  }
}
/* My agents' dot in the phone's menu */
.menu-dot { flex: none; width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--c-accent); }

/* ---- the page: a 680px column between two lines (the inbox, the docs and settings: 1100px from 926px) ---- */
@media (min-width: 761px) {
  body[data-rail] main.wrap {
    --panel-pad: 16px;
    position: relative; box-sizing: border-box; width: min(var(--rail-area), 100%); max-width: none; min-width: 0; min-height: 100vh; min-height: 100dvh;
    margin-top: 0; margin-bottom: 0; padding: 0 var(--panel-pad) var(--sp-16);
    border: solid var(--c-divider); border-width: 0 1px; background: var(--c-bg);
  }
  /* the title row (10-08 polish, Bonan: "我们的胶囊设计是可以拿回来的，没必要什么都硬抄袭X"): the column's first row, 56px, the
     title 20/24 bold (ui.css --fs-title), no line under it (taste: no line under a title); it scrolls away with the page and
     the title floats in our pill, 12px under the window's top, centred over the column (.panel-pill, below; app.js) */
  body[data-rail] main.wrap > .panel-band { position: relative; box-sizing: border-box; height: 56px; min-height: 0; margin: 0; padding: 0; }
  body[data-rail] .panel-band h1 { font: 700 var(--text-xl)/var(--lh-xl) var(--font); letter-spacing: normal; }
  body[data-rail] .panel-band > .panel-back { margin-right: var(--sp-1); }
  /* a page without a title (nothing here, an error, your posts): no empty row */
  body[data-rail] main.wrap > .panel-band:empty { display: none; }
  /* New post is the rail's (X's Post); the pill keeps its small blue + */
  body[data-rail] main > .panel-band .btn-post { display: none; }
  body[data-rail] .panel-pill-at { top: 12px; }

  /* the lobby and a profile: rows from line to line, 12px by 16px inside, a line under each (X's cells) */
  body[data-rail] main.wrap:has(> :is(.home-lobby, .home-col)) { padding-bottom: 0; }
  body[data-rail] :is(.home-lobby, .home-col) { max-width: none; margin: 0; padding: 0; }
  body[data-rail] .home-lobby > .home-find { margin-top: 4px; border-bottom-color: var(--rail-line); }
  body[data-rail] :is(.home-lobby, .home-col) .home-list { margin: 0 calc(-1 * var(--panel-pad)); }
  body[data-rail] :is(.home-lobby, .home-col) .home-item { padding: var(--sp-3) var(--panel-pad); border-bottom: 1px solid var(--rail-line); }
  body[data-rail] :is(.home-lobby, .home-col) .home-item + .home-item { border-top: 0; }
  body[data-rail] .home-lobby .home-agent { padding: 12px var(--panel-pad); }
  body[data-rail] .home-lobby [data-online-list] > li:not([hidden]) .home-agent { border-bottom: 1px solid var(--rail-line); }
  /* one line between two people: the phone's line over each row (home.css) goes, as the posts' does (x-layout-2: it drew
     two lines, --bg3 over --rail-line) */
  body[data-rail] .home-lobby [data-online-list] > li:not([hidden]) ~ li:not([hidden]) .home-agent { border-top: 0; }
  body[data-rail] :is(.home-lobby, .home-col) :is(.home-none, .home-empty, > .none) { margin-bottom: 48px; }
  /* a profile's head (Bluesky's, 10-06), then X's tabs: as wide as the column, 53px, the chosen one bold with a 4px bar under
     its middle, a cell pointed at one step of ground; someone else's Posts heading is the same row with its one tab */
  body[data-rail] .home-col .home-row { margin: 0 calc(-1 * var(--panel-pad)); padding: var(--sp-6) var(--panel-pad) var(--sp-4); border-bottom: 0; }
  /* 10-08 polish (Bonan: My profile looked messy; X's and Bluesky's profile): the head is the page's title, so no title row
     over it; the pill shows the title once the name has scrolled away (views/home.js data-pill-watch). The face (64) and
     its button on one row, the button's foot on the face's foot (taste, Bluesky); the name 12 under the face, 20/24 bold;
     the handle right under it and the about line 12 under that, 15/20 */
  body[data-rail] main.wrap:has(> .home-col) > .panel-band { display: none; }
  body[data-rail] .home-row .home-who-main { margin-top: var(--sp-3); }
  body[data-rail] .home-col .sec + .home-list, body[data-rail] .prof-body[data-tab="posts"] .home-list { margin-top: 0; }
  body[data-rail] .prof-body[data-tab="posts"] { padding-bottom: 0; }
  /* sections inside a page (a profile's Agents and Front desk, settings): their title on the scale, the name's 20/24 bold;
     a list in them is rows that reach the column's lines with a line between them (X's cells), not a box inside the
     column's box (10-08 polish) */
  body[data-rail] .me-box { margin: var(--sp-3) calc(-1 * var(--panel-pad)) 0; border: solid var(--rail-line); border-width: 1px 0; border-radius: 0; }
  body[data-rail] .me-box > li + li { border-top-color: var(--rail-line); }
  body[data-rail] .me-box .row { padding: var(--sp-3) var(--panel-pad); }
  body[data-rail] .prof-body > .me-sec { margin-top: var(--sp-6); }
  /* a post: its own room under the header; the line between its turns */
  body[data-rail] .sp { padding-top: 16px; }
  body[data-rail] .sp-a + .sp-q { border-top-color: var(--rail-line); }
  /* settings' first visit, your posts, an error: their own room at the top */
  body[data-rail] .me-head { padding-top: 24px; }
  body[data-rail] .empty { padding-top: 24px; }
  /* nothing here: said in the middle of the column */
  body[data-rail] main.wrap:has(> .nf-option) { padding: 24px; }
}

/* ---- the docs and settings (X's Settings): from 926px the guides or the sections are a 390px column with the title row
   over it, and the page beside it with its own title in its header; under 926px one column, the list a row of tabs
   under the header that scrolls sideways (the phone's, me.css) ---- */
@media (min-width: 761px) {
  body[data-rail] :is(.docs, .me-page) .me-layout { margin-top: 0; }
  body[data-rail] .docs { padding: 0; }
  body[data-rail] main.wrap.wide .me-nav a { margin: 0; }
}
@media (min-width: 761px) and (max-width: 925px) {
  body[data-rail] main.wrap.wide :is(.docs, .me-page) { padding-top: 12px; }
  body[data-rail] main.wrap.wide .me-layout { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  body[data-rail] main.wrap.wide .me-nav {
    position: static; flex-direction: row; overflow-x: auto; gap: 4px; scrollbar-width: none; --bar: none; overscroll-behavior-x: contain;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--nav-fade-start), #000 calc(100% - var(--nav-fade-end)), transparent);
    mask-image: linear-gradient(to right, transparent, #000 var(--nav-fade-start), #000 calc(100% - var(--nav-fade-end)), transparent);
  }
  body[data-rail] main.wrap.wide .me-nav::-webkit-scrollbar { display: none; }
  body[data-rail] main.wrap.wide .me-nav a { flex: none; }
  @supports (animation-timeline: scroll()) { body[data-rail] main.wrap.wide .me-nav { animation: nav-fade linear both; animation-timeline: scroll(self inline); } }
  body[data-rail] main.wrap.wide .me-nav.fade-start { --nav-fade-start: 32px; }
  body[data-rail] main.wrap.wide .me-nav.fade-end { --nav-fade-end: 32px; }
}
@media (min-width: 926px) {
  body[data-rail] main:is(.wide, .ib) { --rail-area: 1100px; }
  /* X's group (above): from 1000px settings and the docs take 1022, their own room (the group's until 10-09, when the group
     became X's 980 and they kept theirs: wider, a guide's lines ran past 100 letters and a key's Revoke stood far from its
     key); the inbox starts on the rail's line like every page and reaches
     on to the window's right edge, at most 1240 (Bonan: "这样一来内容位置可以更多，比如 inbox 就可以更宽") */
  @media (min-width: 1000px) {
    body[data-rail] main.wide { --rail-area: 1022px; }
    body[data-rail] main.ib { --rail-area: 1240px; }
  }
  body[data-rail] main.wrap.wide:has(> :is(.docs, .me-page)) { display: grid; grid-template-columns: 390px minmax(0, 1fr); grid-template-rows: auto 1fr; align-items: start; padding: 0; }
  body[data-rail] main.wrap.wide:has(> :is(.docs, .me-page)) > .panel-band { grid-column: 1; grid-row: 1; margin: 0; padding: 0 16px; }
  /* both columns are on screen: no way back to the list */
  body[data-rail] main.wrap.wide:has(> .docs) > .panel-band > .panel-back { display: none; }
  body[data-rail] main.wrap.wide :is(.docs, .me-page), body[data-rail] main.wrap.wide :is(.docs, .me-page) > .me-layout { display: contents; }
  body[data-rail] main.wrap.wide .me-nav { grid-column: 1; grid-row: 2; position: sticky; top: 0; gap: 0; }
  body[data-rail] main.wrap.wide .me-nav a { height: 52px; padding: 0 16px; border-radius: 0; color: var(--fg); font: var(--level-body); }
  body[data-rail] main.wrap.wide .me-nav a:hover { background: var(--bg2); }
  /* chosen: one step past the hover, nothing else (no bar, no weight: taste "选中态再深一档", "不要单纯加粗"; 44 §3) */
  body[data-rail] main.wrap.wide .me-nav a[aria-current] { background: var(--bg3); font-weight: 400; }
  body[data-rail] main.wrap.wide .me-sections { grid-column: 2; grid-row: 1 / 3; align-self: stretch; min-width: 0; min-height: 100vh; min-height: 100dvh; padding: 0 16px 64px; border-left: 1px solid var(--rail-line); }
  /* the page's title (a guide's; the shown section's) heads its column as the title row heads the list's: 56px, 20/24 bold,
     no line, scrolling with the page (10-08 polish: no X header bars; the pill carries the page's title) */
  body[data-rail] main.wrap.wide .me-sections :is(.me-sec-head, .me-sec > .me-sec-title:first-child) {
    display: flex; align-items: center; box-sizing: border-box; height: 56px; min-height: 0; margin: 0; padding: 0; border: 0;
  }
  body[data-rail] main.wrap.wide .me-sections .me-sec-title { font: 700 var(--fs-title)/var(--lh-title) var(--font); letter-spacing: normal; }
  body[data-rail] main.wrap.wide .me-sections .me-sec-head .me-sec-title { padding: 0; border: 0; }
  body[data-rail] .docs-body { margin-top: var(--sp-2); }
}

/* ---- the inbox: X's Messages, never a page that scrolls (release-3, Bonan). The list's column and the conversation's
   stand from the window's top to its foot between straight lines, each scrolling by itself and handing nothing on to the
   page (overscroll-behavior: contain). "Inbox" and its unread count stay at the top of the list's column while its rows
   scroll under them; the conversation keeps its header row (back, the name pill, Full view and ⋯; inbox.css). Under 926px
   one of the two at a time, as before. Window height: 100dvh, 100vh where dvh is unknown (app.js --chat-viewport follows
   the visual viewport). ---- */
@media (min-width: 761px) {
  body[data-rail] main.ib {
    --panel-pad: 40px; --ib-edge: var(--panel-pad); --ib-side-w: 390px;
    position: relative; box-sizing: border-box; width: min(var(--rail-area), 100%); max-width: none; min-width: 0;
    height: 100vh; height: var(--chat-viewport, 100dvh); margin-top: 0; margin-bottom: 0; padding: 0;
    border: solid var(--c-divider); border-width: 0 1px; background: var(--c-bg);
  }
  html:has(body[data-rail] > main.ib), body[data-rail]:has(> main.ib) { overflow: hidden; overscroll-behavior: none; }
  /* the conversation pages turn the window's scrollbar strip off (inbox.css); beside the rail it stays, so the rail stands
     where it stands on every other page */
  html:has(body[data-rail] > main.ib[data-view="thread"]) { scrollbar-gutter: stable; }
  body[data-rail] main.ib .ib-head { min-height: 0; height: 56px; padding: 0 var(--panel-pad); }
  body[data-rail] main.ib .ib-head h1 { font: 700 var(--text-xl)/var(--lh-xl) var(--font); letter-spacing: normal; }
  /* Requests keeps its back arrow in that row; the inbox's own title is the list's (below) */
  body[data-rail] main.ib:is([data-view="list"], [data-view="thread"]) .ib-head:not(:has(.ib-back)) { display: none; }
  /* "Inbox" and its unread count head the list and scroll with it; once gone, the pill shows "Inbox" centred over the list
     (hotfix-8's, brought back 10-08 polish, Bonan: "inbox往下滚变成胶囊") */
  body[data-rail] main.ib .ib-title { display: flex; align-items: center; gap: var(--sp-2); box-sizing: border-box; height: 56px; padding: 0 var(--panel-pad); }
  body[data-rail] main.ib .ib-title h1 { margin: 0; font: 700 var(--text-xl)/var(--lh-xl) var(--font); letter-spacing: normal; }
  body[data-rail] main.ib .ib-title-n { color: var(--c-text-2); font: 400 var(--text-xl)/var(--lh-xl) var(--font); font-variant-numeric: tabular-nums; }
  body[data-rail] main.ib .ib-scroll > .panel-pill-at { top: 12px; z-index: 6; }
  body[data-rail] main.ib :is(.ib-side, .ib-scroll, .th-scroll) { overscroll-behavior: contain; }
  body[data-rail] main.ib .ib-scroll { padding-bottom: 0; }
  body[data-rail] main.ib .th-scroll { box-sizing: border-box; }
}
@media (min-width: 926px) {
  body[data-rail] main.ib .ib-side { display: flex; flex-direction: column; overflow: hidden; scrollbar-gutter: auto; border-right: 1px solid var(--c-divider); }
  body[data-rail] main.ib .ib-side::after { display: none; }
  body[data-rail] main.ib .ib-side > .ib-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
  body[data-rail] main.ib .ib-list { padding-top: 0; }
}
@media (max-width: 760px) { .th-full { display: none; } }

/* ---- the title row on a phone: a plain line over the column (no rail, the header above it) ---- */
.panel-band { display: flex; align-items: center; gap: var(--sp-2); }
.panel-band h1 { flex: 1 1 auto; min-width: 0; margin: 0; overflow: hidden; font: 600 var(--text-lg)/var(--lh-lg) var(--font); letter-spacing: var(--tracking-tight); text-overflow: ellipsis; white-space: nowrap; }
.panel-band-acts { flex: none; margin-left: auto; display: flex; align-items: center; gap: 8px; }
.panel-back { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 50%; color: var(--fg); }
/* a back arrow's drawn left edge on the title's line, not its round button's: the title row's arrow is 20px in a 36px
   button (8px each side) drawn from x=4 of 24 with its stroke (views.js panelBand); the inbox's chevron is 24px (6px each
   side) drawn from x=8 of 24 (views/inbox.js ICON_BACK) */
.panel-back { margin-left: calc(-8px - 20px * 4 / 24); }
.ib-head .ib-back { margin-left: calc(-6px - 8px); }
.panel-back:hover { background: var(--bg2); }
@media (max-width: 760px) {
  .panel-band { min-height: 56px; margin: var(--sp-1) 0 0; }
  .panel-band:empty { display: none; }
}

/* ---- the title's pill on a phone (hotfix-ui, 10-07, Bonan: "My profile", "Posts" … must not stay as a full-width bar
   pinned across the top; once the page scrolls the title is a small, centred, see-through pill floating at the top):
   iOS 26's navigation bar once its large title has scrolled away, the title and its buttons on glass and no bar behind
   them. 36px high, the site's one button height; frosted glass (ui.css --glass-*, Bonan 10-08: "胶囊应该是半透明磨砂玻璃……何必有框呢"), no edge, no shadow; the title 15px semibold. It floats 8px under the
   header; it is there only while public/app.js says the row has scrolled away (main[data-collapsed]), at once, no fade.
   Beside the rail it floats 12px under the window's top (above).
   The floating row (10-09, Bonan: "同理，post 胶囊也是，post 在中间，然后 return 独立的圆在左边。inbox 那个，inbox 胶囊也在中
   间吧"; before, the back arrow and the action sat inside the pill): the pill holds the title alone, centred over the
   column; back is a round glass button of its own at the row's left, the page's action (Posts' New post, the inbox's
   search) one at its right, each the pill's glass, 36 high, fully round, no edge, no shadow, all on one line (views.js
   panelBand, panelPillCircle). The circles stand on the column's content edges (E1: the page's 16; the inbox's own,
   --pill-row-start / --pill-row-end), so the pill keeps a circle's width and a gap clear on each side. The same moment
   shows the pill and its circles (main[data-collapsed]), so they come and go as one row. ---- */
.panel-pill-at { position: sticky; top: calc(var(--top-h) + 8px); z-index: 6; display: flex; justify-content: center; height: 0; pointer-events: none; }
.panel-pill {
  visibility: hidden; display: inline-flex; align-items: center; gap: var(--sp-2); box-sizing: border-box; max-width: min(420px, calc(100% - 2 * (36px + 8px))); height: 36px; padding: 0 var(--sp-4);
  border: 0; border-radius: var(--radius-full); color: var(--c-text);
  background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  font: 600 var(--fs-body)/var(--lh-item) var(--font); letter-spacing: var(--tracking-tight); white-space: nowrap; pointer-events: auto;
}
main[data-collapsed] :is(.panel-pill, .panel-pill-circle) { visibility: visible; }
/* the inbox's pill carries the head's unread count, the head's own look: grey, regular weight, 8 after the title */
.panel-pill:has(> .panel-pill-n) { gap: var(--sp-2); }
.panel-pill-n { flex: none; color: var(--c-text-2); font-weight: 400; font-variant-numeric: tabular-nums; }
.panel-pill-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* a circle of the row: the pill's glass and height, an icon of 20 (44 §6: an icon alone in a round button); under the
   pointer one step of ground through the glass (the conversation's glass buttons, inbox.css) */
.panel-pill-circle {
  visibility: hidden; position: absolute; top: 0; display: grid; place-items: center; box-sizing: border-box; width: 36px; height: 36px; margin: 0; padding: 0;
  border: 0; border-radius: var(--radius-full); color: var(--c-text); text-decoration: none; cursor: pointer; pointer-events: auto;
  background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.panel-pill-circle.is-start { left: var(--pill-row-start, 0px); }
.panel-pill-circle.is-end { right: var(--pill-row-end, 0px); }
.panel-pill-circle > svg { width: 20px; height: 20px; }
.panel-pill-circle:hover { background: color-mix(in srgb, var(--c-bg-3) 88%, transparent); }
/* New post's + keeps the site's blue (the one coloured action), on the same glass */
.panel-pill-new { color: var(--link); }
/* 44 to press on a phone, 32 beside the rail (44 §8): the circle itself stays 36 */
.panel-pill-circle::after { content: ""; position: absolute; inset: -4px; border-radius: inherit; }

/* ---- the lobby's two lists are two places now (Posts, Online agents): the selector between them is gone ---- */
.home-lobby:not([data-place="search"]) > .home-tabs { display: none; }
/* ---- Search (10-08 polish): the box at the top of its own view, then Posts | Online agents (the old EOL selector, the
   chosen one's ground on the box's left edge), then the rows ---- */

/* ---- every tab bar of a profile (Posts | Agents | Front desk, someone's one Posts tab), at every width: Bluesky's (round 2,
   10-08, Bonan's pick T1 after "看看业界成熟标准"; 10-08 polish had a step of ground under the chosen one): left-aligned, each
   tab as wide as its label (not X's equal cells, "他们分得太散了"), its words starting on the content's edge; the chosen one
   bold in the text's colour with a short 3px bar under its words; the others grey and bold, a step of ground under the
   pointer; one thin line under the whole row and none over it. With one tab it stands where the first of three does. ---- */
.prof-tabs, .home-col > .home-posts-title {
  display: flex; align-items: stretch; gap: 0; height: auto; margin: 0 calc(-1 * var(--panel-pad, var(--sp-4))); padding: 0 calc(var(--panel-pad, var(--sp-4)) - var(--sp-3));
  border: 0; border-bottom: 1px solid var(--c-divider, var(--c-bg-3));
}
.prof-tab, .home-posts-title > .prof-tab-in {
  position: relative; flex: none; display: flex; align-items: center; height: auto; min-width: 0; padding: var(--sp-4) var(--sp-3); border-radius: 0;
  background: transparent; color: var(--c-text-2); font: 600 var(--fs-body)/var(--lh-base) var(--font); letter-spacing: normal; text-decoration: none; white-space: nowrap;
}
.prof-tab:hover { color: var(--c-text); background: var(--c-bg-2); }
.prof-tab[aria-current], .home-posts-title > .prof-tab-in { background: transparent; color: var(--c-text); font-weight: 700; }
.prof-tab[aria-current]::after, .home-posts-title > .prof-tab-in::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 0; height: 3px; border-radius: var(--radius-full); background: var(--c-text); }
.prof-tab-in { display: contents; }
.home-posts-title > .prof-tab-in { display: flex; }
.prof-body { padding: 0 0 var(--sp-6); }
.prof-body > .me-sec { margin-top: 24px; }
.prof-body[data-tab="posts"] .home-list { margin-top: 0; }
.prof-card .me-sec-title { border-bottom: 0; padding-bottom: 0; }

/* ---- the phone's menu: the current place told by colour, as on the rail (10-08 polish, Bonan: "这个选择特效让他变色嘛"): the
   places' icons grey, the current place's icon in the text's colour; no ground, no weight ---- */
.nav-menu .menu-place > svg:first-child { color: var(--c-text-2); }
.nav-menu .menu-place[aria-current] > svg:first-child { color: var(--c-text); }

/* ---- the hierarchy (10-08 polish; Bonan: "缺乏视觉层级是一个通病，解决它"): every view's words on the four levels written
   once in ui.css (title, item, body, meta) and its three colours (fg, muted, subtle), at every width. A row leads with its
   item title; what it says is body, grey; when and how many is meta, the faintest. Conversations keep ChatGPT's words
   (--chat-text), buttons shadcn's, dialogs shadcn's head (taste), the lobby's search its underline (taste). ---- */
/* titles: a page's, a profile's name, a section's, a post's, the conversation's head */
.home-row h1, .me-sec-title, .sp-title, .ib-title h1, .ib .ib-head h1, .ib[data-view] .ib-head h1, .panel-band h1 { font: var(--level-title); letter-spacing: normal; }
@media (max-width: 640px) { .home-row h1 { font: var(--level-title); } }
/* a line under a section's title is one Bonan removed (taste, 10-02): space alone */
.me-sec-title, .me-sec-head { padding-bottom: 0; border-bottom: 0; }
/* rows: the lobby's and a profile's posts */
.home-item-title { font: var(--level-item); }
.home-item-text { margin-top: var(--sp-1); font: var(--level-body); color: var(--muted); }
.home-item-by { margin-top: var(--sp-2); font: var(--level-meta); }
.home-item .home-at, .home-at { font: var(--level-meta); color: var(--subtle); }
.home-item .home-author b { font: var(--level-meta); color: var(--muted); }
/* a profile's head: the name a title; the handle 4 under it, the about line 12 under that */
.home-row .home-who-facts { margin: var(--sp-1) 0 0; font: var(--level-body); color: var(--c-text-2); }
.home-row .home-about { margin: var(--sp-3) 0 0; font: var(--level-body); }
/* online agents and people: the name an item, the handle grey, the about line body (X's who-to-follow) */
.home-agent-name { font: var(--level-item); }
.home-agent-handle { font: var(--level-body); line-height: var(--lh-item); color: var(--muted); }
.home-agent-about { font: var(--level-body); color: var(--fg); }
/* a post: the author an item, @handle and when meta; the opening's state a meta chip; the asker's turn the conversation's
   size, its weight telling it from the answer */
.sp-name { font: 700 var(--fs-meta)/var(--lh-meta) var(--font); } /* the byline (round 4): the meta row, the name at the item weight */
.sp-facts, .sp-time { font: var(--level-meta); color: var(--subtle); }
.sp-q { font: 600 var(--chat-text)/var(--chat-lh) var(--font); letter-spacing: normal; }
/* the inbox: a conversation's name an item, its last line body grey, its time meta; the list's group labels meta */
.ib-chat-name { font: var(--level-item); }
.ib-chat-text { font: var(--level-meta); }
.ib-chat-at { font: var(--level-meta); color: var(--c-text-3); }
.th-status { font: var(--level-meta); color: var(--subtle); }
/* settings, Agents and Front desk: what a row explains is body grey; the list beside them body */
.me-sec-lead, .me-sec .note, .me-sec .none { font: var(--level-body); color: var(--muted); }
.me-box .row h3 { font: var(--level-item); }
/* the one settings-row name, every tab of the Agent page, the dialogs and Settings: regular; a row that is a vendor's app (its logo) 500 */
.me-app-name, .me-sec .field { font: var(--level-row); }
.me-app:has(> .me-app-logo:not(.ag-icon-tile)) .me-app-name { font: var(--level-row-app); }
.me-app-line, .me-resp { font: var(--level-body); color: var(--muted); }
.me-nav a { font: var(--level-body); }
.me-nav a[aria-current] { font-weight: 700; }
/* the head's own line is the tabs' (above): none under the head too, at any width (it drew two lines on a phone) */
.home-col .home-row { border-bottom: 0; }
/* the lists open on their rows (10-08 polish: the box went to Search): no room left where it stood, at any width; the
   first row's own 12px is the room under the title, as on every list */
.home-lobby:not([data-place="search"]) { padding-top: 0; }
.home-lobby:not([data-place="search"]) .home-list { margin-top: 0; }
/* a profile's head under its title row on a phone: 16 (it was 32, a gap that read as a missing part) */
@media (max-width: 760px) { .home-col .home-row { padding-top: var(--sp-4); } }

/* ---- Search, a page of its own (10-08 polish; Bonan: "真就给 search 搞成一个真的页就行了", X's Explore as the reference):
   X's field at the top, staying there as the page scrolls: a pill with a 1px edge on the page's own ground, the magnifier
   inside at its left and "Search" grey, 15/20 words, 44 high, as wide as the column; nothing changes when it takes the
   keys (taste: an input has no focus effect). Typing opens a few quick matches under it (X's typeahead; public/app.js):
   an item list on a raised surface, inset rows, the one the keys are on a step of ground; it appears at once. ---- */
.search-pill { position: sticky; top: var(--top-h, 0px); z-index: 6; margin: 0 calc(-1 * var(--panel-pad, 16px)); padding: var(--sp-3) var(--panel-pad, 16px) var(--sp-2); background: var(--bg); }
@media (min-width: 761px) { body[data-rail] .search-pill { top: 0; } }
.search-pill-box { display: flex; align-items: center; gap: var(--sp-3); box-sizing: border-box; height: 44px; padding: 0 var(--sp-4); border: 1px solid var(--c-border); border-radius: var(--radius-full); background: transparent; color: var(--c-text-2); cursor: text; }
.search-pill-box > svg { flex: none; width: 20px; height: 20px; }
.search-pill-box > input { flex: 1 1 auto; min-width: 0; height: 100%; margin: 0; padding: 0; border: 0; outline: 0; background: transparent; color: var(--c-text); font: var(--level-body); -webkit-appearance: none; appearance: none; }
.search-pill-box > input::placeholder { color: var(--c-text-2); opacity: 1; }
.search-pill-box > input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
.search-suggest { position: absolute; left: var(--panel-pad, 16px); right: var(--panel-pad, 16px); top: calc(100% - 4px); z-index: 7; box-sizing: border-box; max-height: min(420px, 70vh); overflow-y: auto; padding: 4px; border: 1px solid var(--glass-edge); border-radius: var(--radius-box); background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); }
.search-suggest[hidden] { display: none; }
.search-suggest-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) 12px; border-radius: var(--radius); color: var(--fg); text-decoration: none; font: var(--level-body); cursor: pointer; }
/* on glass the row under the pointer or the keys takes a see-through step (taste: a mark on a surface is a relative colour) */
.search-suggest-row:hover, .search-suggest-row[aria-selected="true"] { background: var(--chip); }
.search-suggest-row > svg { flex: none; width: 20px; height: 20px; margin: 0 10px; color: var(--muted); }
.search-suggest-for { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* what was typed: one line, cut */
.search-suggest-who { display: grid; row-gap: 0; min-width: 0; } /* the name and its handle touch (ui.css rhythm) */
.search-suggest-who > b { overflow: hidden; font: var(--level-item); text-overflow: ellipsis; white-space: nowrap; }
.search-suggest-who > span { overflow: hidden; color: var(--muted); line-height: var(--lh-item); text-overflow: ellipsis; white-space: nowrap; }

/* ---- the online agents' row, X's People row (10-08 polish, Bonan: "在线的人用 X 这种布局"), on Online agents and in Search:
   the face 40 at the left, its top on the name's; the name (item) and @handle (body, grey) beside it; Chat at the right,
   centred on those two lines (the site's blue button: our own, not X's white Follow pill); the about line (body, the text's
   colour, whole) under them on the name's left edge; 12 by 16 inside; under the pointer the row one step of ground ---- */
[data-online-list] > li { position: relative; }
.home-agent { grid-template-columns: 40px minmax(0, 1fr); gap: 0 var(--sp-3); } /* the name and its handle touch (ui.css rhythm) */
.home-agent > .ava { grid-row: 1 / 3; }
.home-agent-about { grid-column: 2; margin-top: var(--sp-2); } /* 8 under the handle, as before the rows' 4 went */
[data-online-list] > li:hover > .home-agent { background: var(--bg2); }
.home-agent-chat { position: absolute; top: calc(var(--sp-3) + 20px); right: var(--panel-pad, 16px); z-index: 1; transform: translateY(-50%); }
[data-online-list] > li:has(> .home-agent-chat) :is(.home-agent-name, .home-agent-handle) { margin-right: 88px; }
/* the field takes the keys with no ring (taste: an input has no focus effect; the lobby's own field the same, home.css .home-q) */
.search-pill-box > input:focus-visible { outline: none; }

/* ---- the inbox's list column (10-08 polish, Bonan: "inbox 左栏这里，线上版本太窄了，左右两边都是这么大的 padding，没意义吧";
   Messenger's, Slack's, X's DMs; 10-09 Cube's decision queue rows, inbox.css): a row is a band the column's whole width,
   from its line to the scrollbar's lane. Its face starts 24 from the column's line, and "Inbox" with it: the 16 of 10-08
   and 8 more for the unread dot's gutter (10-09, Bonan: "那个蓝点……一出来会挤压别人"; iMessage's dot sits left of the face):
   the dot 10 wide, 8 from the line, 6 clear of the face, on every row the same, read or not. A face is drawn 40 in its 48
   box (4 each side), so a row's own inside is 20 at the left. The times and counts end 20 from the other side (--ib-row-r):
   the scrollbar is drawn over the rows' last 12 (inbox.css, the list's scrollbar), and 8 more keep them clear of it, where
   they stood on 10-08 beside the rail; a phone the same. ---- */
.ib-side { --panel-pad: 24px; --ib-edge: 24px; --ib-row-r: 20px; }
.ib-side .ib-list { padding: 0; }
.ib-side .ib-chat > a { padding: var(--sp-3) var(--ib-row-r) var(--sp-3) var(--sp-5); }

/* ---- the right column (rightcol-study, 10-08; Bonan: "应该是我的 online agent，cloud agent……这是个快捷方式"; then X's right
   column as the model, modules to come): X's, 350 wide, 30 right of the column (32 until 10-09), from the column's top, and it stays put while the
   centre scrolls, as X's does (.rcol spans main.wrap's height; .rcol-stick inside it is position:sticky; top:0, so no ancestor
   up to the page scroller may be overflow hidden/clip/auto). X sticks a column taller than the window by its bottom edge: a
   later step, we have one short module; a stack of modules 16 apart (views.js rcolModule), each X's shell: a 1px edge (--line), 16px corners
   and 16 inside, no ground, its title at the title level (20/24 bold); a module's rows reach its edges (its words keep
   the 16) and take one step of ground under the pointer. With it the column is X's, 600 (its words 568; 640 until 10-09),
   and the three (the rail, the column, this) are one group centred in the window (X's group, at the top). Under 1000px wide (and on a phone) it is not drawn; between 1000 and the
   pair's own width the column gives way. ---- */
.rcol { display: none; }
@media (min-width: 1000px) {
  body[data-rail]:has(main > .rcol) { --rcol-w: 350px; --rcol-gap: 30px; }
  body[data-rail] main.wrap:has(> .rcol) {
    --rail-area: 600px;
    width: min(var(--rail-area), 100% - var(--rcol-w) - var(--rcol-gap));
  }
  .rcol { position: absolute; top: 0; bottom: 0; left: calc(100% + 1px + var(--rcol-gap)); display: block; box-sizing: border-box; width: var(--rcol-w); }
  .rcol-stick { position: sticky; top: 0; display: flex; flex-direction: column; gap: var(--sp-4); padding-top: var(--sp-3); }
  .rcol-mod { overflow: clip; padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-box); }
  .rcol-title { margin: 0; font: var(--level-title); letter-spacing: normal; }
  .rcol-list { list-style: none; margin: var(--sp-2) calc(-1 * var(--sp-4)) 0; padding: 0; }
  .rcol-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); color: var(--fg); text-decoration: none; }
  a.rcol-row:hover { background: var(--bg2); }
  .rcol-row > .ava { flex: none; }
  .rcol-who { display: grid; row-gap: var(--sp-1); flex: 1 1 auto; min-width: 0; }
  .rcol-who > b { overflow: hidden; font: var(--level-item); text-overflow: ellipsis; white-space: nowrap; }
  .rcol-who > span { color: var(--muted); font: var(--level-body); }
  .rcol-line { margin: var(--sp-1) 0 var(--sp-3); color: var(--muted); font: var(--level-body); }
  .rcol-acts { display: flex; align-items: center; gap: var(--sp-4); }
  /* a text link in a module (Connect cloud agent, Manage): the site's link colour, no underline until pointed at */
  .rcol-link { color: var(--link); font: var(--level-body); text-decoration: none; }
  .rcol-link:hover { text-decoration: underline; }
  .rcol-more { display: inline-block; margin-top: var(--sp-2); padding-block: 4px; } /* 32 to press, its words where they were */
  /* My agents with none yet, or signed out (round 2, Bonan: "应该有个小动画，类似那个 404 页面，下面是 connect……或者
     signin"): the 404's robot at 96 in the module's middle, its one button under it, nothing else */
  .rcol-empty { display: grid; justify-items: center; gap: var(--sp-3); padding: var(--sp-2) 0 var(--sp-1); }
  .rcol-empty .nf-art { width: 96px; height: 96px; }
}
/* the module's quiet second way (Connect cloud agent under Host your agent, X's Premium module): small and grey, its own line */
@media (min-width: 1000px) {
  .rcol-join > .btn { display: inline-flex; }
  .rcol-quiet { display: block; width: fit-content; margin-top: var(--sp-3); color: var(--muted); font: var(--level-meta); }
}

/* ---- empty lists say so in the middle (round 2, Bonan: "这种 no post yet 不应该居中么"; Bluesky, X and Threads): the same
   words, size and colour, centred, with 48 of room above them; no box, no second line. My profile's tabs, someone's
   posts, Search with nothing found, Online agents with nobody, the settings' lists, the inbox's requests. ---- */
:is(.prof-body, .home-col) > .none, .prof-body .me-sec .none, .me-sec .none, .home-lobby .home-none, .home-lobby .home-empty, .ib-side .ib-note {
  margin: 0; padding: 48px 16px 0; border: 0; border-radius: 0; text-align: center;
}

/* ---- the Agents tab (round 2, Bonan: "这已经选中了 Agents，还要显示 Cloud agents 么？……不能孤零零一个 button"): no title over
   the list, which starts under the tabs; its add row is a row like the others (Slack's Add channels, Telegram's New Contact,
   Discord's Add a Server): a grey circle with + in the face's place, the words beside it, one step of ground under the
   pointer ---- */
.prof-body > .me-sec-bare, body[data-rail] .prof-body > .me-sec-bare { margin-top: 0; }
.me-sec-bare > .me-agents, body[data-rail] .me-sec-bare > .me-agents { margin-top: 0; border-top: 0; }
.me-add { display: flex; align-items: center; gap: 12px; color: var(--fg); text-decoration: none; }
.me-add:hover { background: var(--bg2); }
.me-add-face { display: grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: var(--radius-full); background: light-dark(rgb(0 0 0 / .055), rgb(255 255 255 / .07)); color: var(--muted); }
.me-add:hover .me-add-face { color: var(--fg); }
.me-add-words { font: var(--level-row); }

/* ---- your agent's green dot (round 3, Bonan: "就是那个绿点回来"): the embed pet's (views/embed.js pet-dot), 8px, centred at
   81.25% of the face, with its white rim; only while the agent can answer ---- */
.agent-face { position: relative; }
.rcol-who > span.rcol-needs { color: var(--unread); font-weight: 600; } /* blue means it needs you (devil-blueonly) */
.agent-dot { position: absolute; left: calc(81.25% - 4px); top: calc(81.25% - 4px); width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--c-online); box-shadow: 0 0 0 1.5px var(--online-rim); }

/* ---- the search page's Posts | People (or Agents) is the profiles' tab bar too (round 3, Bonan: "这个选择器是不是也要改成我们之前
   说的那个"): Bluesky's, left-aligned and content-width, the chosen one bold with a short bar, a line under the row ---- */
#home-tab-posts:checked ~ .home-tabs > label[for="home-tab-posts"], #home-tab-agents:checked ~ .home-tabs > label[for="home-tab-agents"] { color: var(--fg); font-weight: 700; background: transparent; }
#home-tab-posts:checked ~ .home-tabs > label[for="home-tab-posts"]::after, #home-tab-agents:checked ~ .home-tabs > label[for="home-tab-agents"]::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 0; height: 3px; border-radius: 2px; background: var(--fg); }

/* ---- every other tab bar is the profiles' too (round 3, Bonan: one tab style app-wide): the settings' and the docs' sections
   where they are a row (under 926px), and the embed guide's ways to embed. Pickers of an option (the guide's size and
   theme) and menus stay as they are. ---- */
@media (max-width: 925px) {
  body main .me-nav { gap: 0; margin-inline: -16px; padding: 0 4px; border-bottom: 1px solid var(--rail-line, var(--bg3)); }
  body main .me-nav a { position: relative; height: auto; margin: 0; padding: 14px 12px; border-radius: 0; background: transparent; color: var(--muted); font: 600 var(--fs-body)/var(--lh-base) var(--font); }
  body main .me-nav a:hover { background: var(--bg2); color: var(--fg); }
  body main .me-nav a[aria-current] { background: transparent; color: var(--fg); font-weight: 700; }
  body main .me-nav a[aria-current]::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 0; height: 3px; border-radius: 2px; background: var(--fg); }
}
.eg-modes:not(.eg-sizes, .eg-themes) { gap: 0; margin-inline: -12px; border-bottom: 1px solid var(--rail-line, var(--bg3)); }
.eg-modes:not(.eg-sizes, .eg-themes) > a { position: relative; padding: 14px 12px; border-radius: 0; background: transparent; color: var(--muted); font: 600 var(--fs-body)/var(--lh-base) var(--font); }
.eg-modes:not(.eg-sizes, .eg-themes) > a:hover { background: var(--bg2); color: var(--fg); }
.eg-modes:not(.eg-sizes, .eg-themes) > a[aria-current] { background: transparent; color: var(--fg); font-weight: 700; }
.eg-modes:not(.eg-sizes, .eg-themes) > a[aria-current]::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 0; height: 3px; border-radius: 2px; background: var(--fg); }

/* ---- the detail standards (10-09, design/44-detail-standards.md) ---------------------------------------------------- */
/* the title row's back (36 round) is 44 to press (44 §8) */
.panel-back { position: relative; }
.panel-back::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; }
/* lists with lines reach the screen's edges on a phone too, their words on its 16 (taste: "B+线取代card", "手机顶到屏幕边";
   44 §3): your posts, keys, apps; no box in the column */
@media (max-width: 760px) {
  .me-box { margin-inline: -16px; border-width: 1px 0; border-radius: 0; }
  .me-box .row { padding-inline: 16px; }
}

/* ---- the right column is your line with your agent (10-09 night, Bonan: "右边的这个东西就得给我改成主线的对话"; views.js
   lineModule, views/inbox.js railLine; eol_research/right-rail-2026-10-09): Copilot's chat beside the page. X's slot (350
   wide, a 1px edge, the modules' corners) as a panel the window's height, stuck while the page scrolls; inside it the
   conversation pane of /inbox/agent, its box at the foot. A page's own module (a long post's contents) stacks over it
   and keeps its own height (its list scrolls in at most 40% of the window); the line takes the rest, so the box is
   always in view ("委屈一下这个chat，让他变低（比如flex-1）在下面就行了呗"). Who it is floats at its top in the glass of the
   title pill, the messages scrolling under it (taste: no opaque header, only what must stay, sticky, in glass). ---- */
@media (min-width: 1000px) {
  .rcol-stick.has-line { height: 100vh; height: 100dvh; box-sizing: border-box; padding: var(--sp-3) 0; }
  .rcol-stick.has-line > :not(.rr-panel) { flex: none; }
  .rcol-stick.has-line .rcol-toc .toc-scroll { max-height: 40vh; }
  .rr-panel { position: relative; flex: 1 1 0; min-height: 240px; display: flex; flex-direction: column; border: 1px solid var(--c-border); border-radius: var(--radius-box); overflow: clip; background: var(--c-bg); }
  /* Minimize (10-11, Bonan: "右边栏上应该有个最小化……缩成一张卡片，卡片上是你的agent，可以有动画"; Intercom's and LinkedIn's message
     window): html[data-rail-min] (public/app.js railMinimize, kept in the browser) takes the panel out of sight (it stays in
     the page, so its line keeps listening and the card can count what came) and shows one card in its place at the column's
     top; the column keeps its width. Both ways switch at once, no scaling or fading. The card's only motion is the
     face's slow bob and one wave when something new comes: transform only, so it costs the main thread nothing. */
  .rr-min { position: absolute; z-index: 5; top: var(--sp-3); right: var(--sp-3); display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: var(--radius-full); background: none; color: var(--c-text-2); cursor: pointer; }
  .rr-min:hover { background: var(--c-bg-3); color: var(--c-text); }
  .rr-card { display: none; position: relative; box-sizing: border-box; width: 100%; grid-template-columns: 1fr auto auto; align-items: center; column-gap: var(--sp-2); justify-items: center; row-gap: var(--sp-2); padding: var(--sp-3) var(--sp-4) var(--sp-4); border: 1px solid var(--c-border); border-radius: var(--radius-box); background: var(--c-bg); color: var(--c-text); font: inherit; text-align: center; cursor: pointer; }
  .rr-card:hover { background: var(--c-bg-2); }
  .rr-card .rr-who { display: contents; }
  .rr-card .rr-who > b { grid-area: 1 / 1; justify-self: start; font: var(--level-title); letter-spacing: normal; } /* the title, as the empty card's */
  .rr-card .rr-who > span { grid-area: 3 / 1 / 4 / -1; color: var(--c-text-2); font: var(--level-body); }
  .rr-card .rr-who > span[data-online] { display: none; } /* online is the green dot on the pet; only what needs you is said in words (Bonan: "需要online几个字么？") */
  .rr-card-face { display: none; }
  .rr-card-pet { grid-area: 2 / 1 / 3 / -1; margin-bottom: calc(-1 * var(--sp-1)); display: block; width: 84px; height: 74px; color: var(--c-text); }
  .rr-card-pet svg { display: block; width: 100%; height: 100%; overflow: visible; }
  .rr-card-count { grid-area: 1 / 2; }
  .rr-card-count[hidden] { display: none; }
  .rr-card-open { grid-area: 1 / 3; margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) 0; display: grid; place-items: center; width: 32px; height: 32px; color: var(--c-text-2); }
  html[data-rail-min] .rcol-stick.has-line { height: auto; }
  html[data-rail-min] .rr-panel { position: absolute; visibility: hidden; pointer-events: none; height: 0; min-height: 0; }
  html[data-rail-min] .rr-card { display: grid; }
  html[data-rail-min] [data-rail-slot] { display: none; }
  /* the thin strip, to compare: its small face, the name and status, the count, the arrow */
  html[data-rail-min="strip"] .rr-card { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); text-align: left; }
  html[data-rail-min="strip"] .rr-card .rr-who { display: grid; row-gap: 2px; flex: 1 1 auto; min-width: 0; }
  html[data-rail-min="strip"] .rr-card .rr-who > b { font: var(--level-item); }
  html[data-rail-min="strip"] .rr-card .rr-who > span { display: block; font: var(--level-meta); }
  html[data-rail-min="strip"] .rr-card-face { display: block; flex: none; transform-origin: 50% 90%; }
  html[data-rail-min="strip"] .rr-card-pet { display: none; }
  html[data-rail-min="strip"] .rr-card-count, html[data-rail-min="strip"] .rr-card-open { flex: none; margin: 0; }
  @media (prefers-reduced-motion: no-preference) {
    html[data-rail-min="strip"] .rr-card-face { animation: rr-bob 6s ease-in-out infinite; }
    html[data-rail-min="strip"] .rr-card.is-waving .rr-card-face { animation: rr-wave .9s ease-in-out 1; }
  }
  @keyframes rr-bob { 0%, 80%, 100% { transform: translateY(0); } 88% { transform: translateY(-3px); } 94% { transform: translateY(0); } }
  @keyframes rr-wave { 0%, 100% { transform: rotate(0); } 15% { transform: rotate(-14deg) translateY(-2px); } 35% { transform: rotate(12deg) translateY(-2px); } 55% { transform: rotate(-10deg); } 75% { transform: rotate(6deg); } }
  .rr-head { position: absolute; z-index: 4; inset: 0 0 auto 0; display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); color: var(--c-text); text-decoration: none; }
  a.rr-head:hover { background: var(--c-bg-2); }
  .rr-head > .rr-unread { position: static; margin-left: auto; flex: none; outline: 0; }
  .rr-head > .rr-unread[hidden] { display: none; }
  .rr-head > .ava { flex: none; }
  .rr-who { display: grid; row-gap: var(--sp-1); min-width: 0; }
  .rr-who > b { overflow: hidden; font: var(--level-item); text-overflow: ellipsis; white-space: nowrap; }
  .rr-who > span { color: var(--c-text-2); font: var(--level-meta); }
  .rr-who > span.rcol-needs { color: var(--unread); font-weight: 600; }
  /* the pane: the inbox's own, its column the panel's width; the head's 56 over its top, the box at its foot */
  .rr-panel > .ib-pane.th { flex: 1 1 auto; min-height: 0; }
  /* (scrollbar-unify, 10-10) its thumb is drawn over its edge (ui.css "every box's bar"), its track under the head */
  /* the head's 68 is the box's own top padding (not the body's): the app's pin puts a question 16 under where the padding ends (app.js fitRoom), so it clears the head */
  .th-rail .th-scroll { --bar-top: 56px; padding-top: 68px; }
  .th-rail .th-body { max-width: none; padding: 0 var(--sp-4) calc(var(--sp-6) + var(--sp-4)); }
  .th-rail :is(.th-row, .th-approval, .th-quote) { max-width: 86%; }
  /* an ask's answers in the column's narrow width: the decision first (Deny, Approve together), Open conversation after */
  .th-rail .th-approval { max-width: 100%; }
  .th-rail .th-actions > a.btn { order: 1; }
  .th-rail .th-compose.chatbox { width: calc(100% - 24px); max-width: none; margin: 0 auto var(--sp-3); }
  .th-rail :is(.th-dock-note, .th-compose-error) { max-width: calc(100% - 24px); }
  /* the page it is beside, over the box: a small outlined chip with an eye and a way to take it off (Copilot's) */
  .rr-ctx { padding: 10px 12px 0; }
  .rr-ctx[hidden] { display: none; }
  .rr-chip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; box-sizing: border-box; height: 28px; padding: 0 4px 0 10px; border: 1px solid var(--line); border-radius: var(--radius-full); color: var(--muted); font: var(--level-meta); line-height: 1; white-space: nowrap; }
  .rr-chip > svg { flex: none; }
  .rr-chip-text { overflow: hidden; min-width: 0; color: var(--fg); text-overflow: ellipsis; }
  .rr-chip-x { flex: none; display: grid; place-items: center; width: 20px; height: 20px; padding: 0; border: 0; border-radius: var(--radius-full); background: none; color: var(--muted); cursor: pointer; }
  .rr-chip-x:hover { background: var(--bg3); color: var(--fg); }
  /* a page's copy while the next one comes (views/skeletons.js): the line's own shape, grey, until app.js puts the line in */
  .rr-slot .rr-slot-face { width: 32px; height: 32px; border-radius: 50%; background: var(--bg3); }
  .rr-slot .rr-who > * { border-radius: 6px; background: var(--bg3); color: transparent; }
  .rr-slot-body { flex: 1 1 auto; }
  .rr-slot-box { flex: none; height: 92px; margin: 0 12px 12px; border-radius: 16px; background: var(--bg2); }
}

/* ---- the profile is X's (10-09 night): the head, the person's homepage as their introduction, Posts ---- */
.prof-intro { margin-top: var(--sp-4); }
.prof-intro .markdown > :first-child { margin-top: 0; }
.prof-intro .markdown > :last-child { margin-bottom: 0; }
.home-col > .prof-intro + .home-posts-title { margin-top: var(--sp-6); }

/* ---- your agent's own page, /agent (10-09 night, views/me.js agentPageView): the profile's head, then its sections ---- */
.ag-face .ava { --size: 64px; }
.ag-body > .me-sec:first-child { margin-top: var(--sp-6); }
.ag-body .me-sec-head + .me-seals { margin-top: var(--sp-2); }
/* Instructions, and Embed on your site's "Only on these sites" (10-10): as wide as the copy boxes beside them */
.me-sec .form.ag-rules, .me-sec .form.ag-sites { max-width: none; }
.ag-rules-text { width: 100%; box-sizing: border-box; }

/* ---- the find box in the title row (devil-search 10-12; Reddit's and X's phone apps): the title and a magnifier; asked (the
   page's frame holds [data-find-on], views/home.js), the row is a back arrow and the field. The shared .icon-btn, the shared
   field. The list is a Turbo Frame; while it loads its rows are the grey blocks of a skeleton. (devil-freeze2, 10-13) The
   marker is looked for where it is, a child of the frame, never anywhere under main: with "main:has([data-find-on])" every
   node put in or taken out anywhere on a page (a word of a reply being written, a row of the inbox) restyled the whole
   page, 1,800 elements and 40 ms each time on the owner's line with its cards: what a :has() rule hides is named
   (.find-open, .btn-post: the magnifier and New post, home.js), as ":not(.find-form)" named nothing and Chrome restyled
   every element under any :has() anchor whenever one was looked at again. ---- */
turbo-frame { display: block; }
.find-form { display: none; }
main:has(> .home-lobby > turbo-frame > [data-find-on]) .panel-band > h1 { display: none; }
main:has(> .home-lobby > turbo-frame > [data-find-on]) .panel-band > .panel-band-acts { flex: 1 1 auto; min-width: 0; margin-left: 0; }
main:has(> .home-lobby > turbo-frame > [data-find-on]) .panel-band-acts > :is(.find-open, .btn-post) { display: none; }
main:has(> .home-lobby > turbo-frame > [data-find-on]) .find-form { display: flex; flex: 1 1 auto; align-items: center; gap: var(--sp-2); min-width: 0; margin: 0; }
.find-form .search-pill-box { flex: 1 1 auto; min-width: 0; }
.home-lobby[data-place="agents"] .home-posts, .home-lobby[data-place="posts"] .home-agents { display: none; }
turbo-frame[busy] .home-list { pointer-events: none; }
turbo-frame[busy] :is(.home-item-title, .home-item-text, .home-author b, .home-at, .home-agent-name, .home-agent-handle, .home-agent-about) { border-radius: 6px; background: var(--bg3); color: transparent; }
turbo-frame[busy] :is(.eol-robot, .presence, .ava, .home-agent-chat) { visibility: hidden; }
@media (prefers-reduced-motion: no-preference) { turbo-frame[busy] .home-list { animation: home-breathe 2s cubic-bezier(.4, 0, .6, 1) infinite; } }
