/* semgit — the topbar, its modes and its menu (section 5), and the dock the
   repo page keeps (5b) — #70, #71. Linked after tokens.css. */

/* ------------------------------------------------------------ 5. the topbar */

/* The stack, in one place, because this is where it goes wrong:
     1  history panel      6  menus and the search results
     2  dock, notes head   7  selection bar
     3  the Edit ribbon    10 topbar
   The topbar is a grid item with a z-index, so it makes a stacking context and
   everything inside it — the breadcrumb menus, the account menu, the search
   results — is clamped to the topbar's own level. At 2 it tied with the dock
   and lost on DOM order, which put the search results underneath the Read/Edit
   pill. At 10 it is over the ribbon (3), so the account menu opens above it. */
.topbar {
  display: flex; align-items: center; gap: var(--s3);
  padding: 0 var(--s3) 0 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  z-index: 10;
}

/* A request in flight. htmx puts .htmx-request on whatever hx-indicator names,
   and <body> names this, so every request shows here unless the element that
   made it points somewhere quieter. A hairline that travels, not a spinner: it
   says "working" without claiming any part of the page. */
.busy {
  position: absolute;
  top: var(--topbar-h); left: 0; right: 0;
  height: 2px;
  z-index: 11;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--fast) var(--ease) 120ms; /* not for the quick ones */
}
.busy::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 30%;
  background: var(--ink);
  animation: travel 1s var(--ease) infinite;
}
.busy.htmx-request { opacity: 1; }
@keyframes travel { from { left: -30%; } to { left: 100%; } }

/* Applied for one frame on load so remembered state (a pinned panel) is
   restored in place rather than animated open from its fold. */
.no-motion * { transition: none !important; animation: none !important; }

/* The mark and the wordmark. The name is Writ — in the title, in the copy —
   and the wordmark sets it lowercase, as a wordmark does; the markup keeps
   the name. */
.brand {
  display: flex; align-items: center; gap: 8px;
  margin-right: var(--s4);
  font-family: var(--ui);
  font-weight: 600; font-size: 14px;
  letter-spacing: -.01em;
  text-transform: lowercase;
  color: var(--ink);
}
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--ink);
}

/* The crumb: the repo, then the document, the name darker than the way to
   it. What it holds is the screen's (doc.html's); this is only its dress. */
#crumb { display: contents; }
.crumb {
  display: flex; align-items: center; gap: var(--s2);
  min-width: 0;
  font-family: var(--ui);
  font-size: var(--t-md);
  color: var(--ink-3);
  white-space: nowrap;
}
.crumb a { color: var(--ink-3); }
.crumb a:hover { color: var(--ink); text-decoration: none; }
.crumb-sep { color: var(--line); }
/* After the brand the gap is the separator; a slash there is a stutter. */
.crumb > .crumb-sep:first-child { display: none; }
.crumb .mono, .crumb strong, .crumb .strong {
  font-family: var(--ui); font-size: inherit;
  font-weight: 500; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis;
}
/* The ref after "@" — the reader always knows the branch (G.4) — stays
   quiet: the document's name is the thing, the branch is its address. */
.crumb .crumb-sep + .mono:last-child {
  font-family: var(--mono); font-size: var(--t-sm);
  font-weight: 400; color: var(--ink-3);
}

/* The document name in the breadcrumb is how you reach the other documents, so
   it looks pressable rather than like the path text around it. */
.crumb-doc {
  display: flex; align-items: center; gap: var(--s1);
  padding: 3px var(--s2);
  border-radius: var(--r1);
  font-weight: 550;
  color: var(--ink);
  cursor: pointer;
}
.crumb-doc:hover { background: var(--sunken); text-decoration: none; }
.crumb-doc svg { color: var(--ink-3); }

/* The modes (#71): text tabs, the current one a filled pill. This is the
   dock of #58 moved into the bar — same hooks, so modes.js is unchanged in
   what it does, only in where it looks. History is a link among them, not
   a mode: it has nothing to slide. */
.modes {
  display: flex; align-items: center; gap: 2px;
  margin-right: var(--s3);
}
.mode-tab {
  display: flex; align-items: center; gap: var(--s2);
  height: 26px;
  padding: 0 11px;
  border-radius: 13px;
  font-size: var(--t-md); font-weight: 500;
  color: var(--ink-3);
  white-space: nowrap;
}
.mode-tab:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
.mode-tab[aria-current="page"] {
  background: var(--ink); color: var(--surface); font-weight: 600;
}
.mode-tab[aria-current="page"]:hover { background: var(--accent-2); color: var(--accent-ink); }

/* The draft is alive and unwritten: the tab that leads back to it says so. */
.mode-tab[data-unsaved]::after {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* A menu in the breadcrumb — which document, which branch — and the account
   menu at the other end of the topbar. <details> rather than script: it opens
   on click and on Enter without anyone writing that. Click-away and Escape are
   the two dismissals <details> does NOT give you; shell.js adds them. */
.menu { position: relative; }
.menu > summary {
  display: flex; align-items: center; gap: var(--s1);
  padding: 3px var(--s2);
  border-radius: var(--r1);
  font-weight: 550;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover { background: var(--sunken); }
.menu > summary svg { color: var(--ink-3); }
.menu[open] > summary { background: var(--sunken); }

.menu-pop {
  position: absolute;
  top: calc(100% + var(--s2)); left: 0;
  z-index: 6;
  min-width: 260px;
  padding: var(--s1);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  box-shadow: var(--e2);
}
/* One look for every row, whether it is the menu's own item, a screen's
   topnav link rendered into it, or a legacy screen's button. */
.menu-item, .menu-pop .topnav a, .menu-pop > .btn {
  display: flex; align-items: baseline; gap: var(--s2);
  width: auto; min-height: 0;
  padding: var(--s2) var(--s3);
  border: 0;
  border-radius: var(--r2);
  background: transparent;
  font-family: var(--ui);
  font-size: var(--t-sm); font-weight: 400;
  color: var(--ink-2);
  white-space: nowrap;
}
.menu-item:hover, .menu-pop .topnav a:hover, .menu-pop > .btn:hover {
  background: var(--sunken); color: var(--ink); text-decoration: none;
}
.menu-item[aria-current="true"] { background: var(--sunken); color: var(--ink); font-weight: 600; }
.menu-item .mono { color: var(--ink-3); }
.menu-item .spacer { min-width: var(--s5); }
.menu-pop .topnav { display: contents; }
.menu-pop .topbar-sep { display: none; }
.menu-form { display: block; }
/* A group's name, in the menu's own case: not an eyebrow (UI-BRIEF §3). */
.menu-note {
  display: flex; align-items: center;
  padding: var(--s2) var(--s3) var(--s1);
  color: var(--ink-3);
  font-size: var(--t-xs); font-weight: 600;
}

/* A menu at the right-hand end of the topbar opens leftwards, or it hangs off
   the window. */
.menu.right .menu-pop { left: auto; right: 0; }

.menu-sep { height: 1px; margin: var(--s1) var(--s2); background: var(--line); }

/* A setting that is on shows a tick where a destination shows nothing, so the
   rows stay one list and the state is still readable at a glance. */
.menu-item .tick { width: 12px; color: var(--ink); visibility: hidden; }
.menu-item[aria-pressed="true"] .tick { visibility: visible; }

button.menu-item {
  align-items: center;
  width: 100%;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
}
button.menu-item[aria-pressed="true"] { color: var(--ink); font-weight: 600; }

/* The account: the avatar is the summary, and the only thing on the bar past
   the modes. Open, it is ringed rather than boxed. */
.account > summary { padding: 0; border-radius: 50%; }
.account > summary:hover, .account[open] > summary { background: transparent; }
.account > summary .avatar {
  width: 26px; height: 26px;
  background: var(--sunken);
  color: var(--ink-2);
}
.account > summary:hover .avatar, .account[open] > summary .avatar {
  color: var(--ink);
  box-shadow: 0 0 0 2px var(--line);
}
.account .menu-pop { min-width: 240px; }

kbd {
  padding: 1px 5px;
  border: 1px solid var(--line);
  border-radius: var(--r1);
  background: var(--sunken);
  font-family: var(--mono); font-size: 10px;
  color: var(--ink-3);
}

.spacer { flex: 1; }

/* Search. A button's width until it is wanted, so it does not crowd a topbar
   that already carries a path and the modes. */
.search { position: relative; display: flex; align-items: center; }
.search input {
  width: 132px;
  padding: var(--s1) var(--s2) var(--s1) 26px;
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface);
  font-size: var(--t-sm);
  color: var(--ink);
  transition: width var(--mid) var(--ease), background var(--fast) var(--ease);
}
.search input::placeholder { color: var(--ink-3); }
.search input:focus { width: 280px; background: var(--surface); }
.search svg { position: absolute; left: var(--s2); color: var(--ink-3); pointer-events: none; }

.search-pop {
  position: absolute;
  top: calc(100% + var(--s2)); right: 0;
  z-index: 6;
  width: 380px;
  max-height: 60vh; overflow-y: auto;
  padding: var(--s1);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  box-shadow: var(--e2);
}
.search:not(:focus-within) .search-pop { display: none; }

.result {
  display: grid; gap: 1px;
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  color: inherit;
}
.result:hover { background: var(--sunken); text-decoration: none; }
.result-head {
  display: flex; align-items: center; gap: var(--s2);
  font-size: var(--t-xs); color: var(--ink-3);
}
.result-title { font-size: var(--t-sm); color: var(--ink); }
.result mark { background: var(--accent-wash); color: inherit; border-radius: 2px; }

/* Leaving the document: repo-level places. On the bar only where a legacy
   screen still puts them there; the document page's sit in the account menu. */
.topnav { display: flex; align-items: center; gap: 2px; }
.topnav a {
  padding: var(--s1) var(--s2);
  border-radius: var(--r1);
  font-size: var(--t-sm);
  color: var(--ink-3);
}
.topnav a:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
.topnav a[aria-current="page"] { color: var(--ink); font-weight: 550; }

.topbar-sep { width: 1px; height: 18px; margin: 0 var(--s2); background: var(--line); }

/* Three states, not two: "follow the OS" is the default and has to stay
   reachable, or choosing once means choosing forever. Three rows in the
   account menu rather than one button that cycles: there is room to show all
   three, and no reason to make anybody guess what the next press does. */
.theme { display: block; }

/* Whether the page is still hearing from the server (G.4 "live updates"). Silent
   when it is — a green tick for the normal case is noise — and only speaks up
   when the answer is no. */
.live {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s1) var(--s2);
  border-radius: var(--r1);
  font-size: var(--t-xs);
  color: var(--ink-3);
}
.live::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ink-3);
}
.live-label { display: none; }
.live[data-state="waiting"]::before { background: var(--ink-3); animation: pulse 1.4s var(--ease) infinite; }
.live[data-state="off"]::before { background: var(--danger); }
/* Healthy, or not a live page at all: nothing to say. */
.live[data-state="live"], .live[data-state="none"] { display: none; }
.live[data-state="waiting"] .live-label,
.live[data-state="off"] .live-label { display: inline; }
@keyframes pulse { 50% { opacity: .25; } }

/* Something arrived while you were reading. It is announced, never inserted:
   the shell does not move text under a reader's eye. Clicking takes it. */
.newpill {
  display: flex; align-items: center; justify-content: center; gap: var(--s2);
  width: 100%;
  margin: var(--s1) 0 var(--s2);
  padding: var(--s2) var(--s3);
  border: 1px solid var(--ink);
  border-radius: var(--r2);
  background: var(--surface);
  font-size: var(--t-xs); font-weight: 550;
  color: var(--ink);
  cursor: pointer;
}
.newpill:hover { background: var(--sunken); text-decoration: none; }
.newpill[hidden] { display: none; }

/* A count that just changed says so by weight, not by moving: nothing the
   server did moves anything (UI-BRIEF §3). */
.dock-count.is-new { background: var(--ink); color: var(--surface); }

.avatar {
  display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent-2);
  font-family: var(--ui);
  font-size: 10px; font-weight: 650; letter-spacing: .02em;
}
/* Provenance by shape, not colour (SPEC G.4): an agent is never a round face. */
.avatar[data-kind="agent"] {
  border-radius: var(--r1);
  background: var(--sunken);
  color: var(--ink-2);
  font-family: var(--mono);
}

/* A phone's width (UI-BRIEF §5.5, 375px): the modes and the account keep
   the bar; the crumb goes first (the pagefoot still names the ref), then
   the wordmark — the mark alone is the brand. */
@media (max-width: 640px) { .topbar .crumb { display: none; } }
@media (max-width: 440px) {
  .brand > span:last-child { display: none; }
  .brand { margin-right: 0; }
  .modes { margin-right: 0; }
}

/* ----------------------------------------------------------- 5b. the dock ---

   The repo page's: Documents · Review with counts, which live.js bumps. The
   document page's modes left this for the topbar (#71, above); the styleguide
   still draws one. Sticky, so it stays reachable however far down you read. */

.dock {
  position: sticky;
  /* From the desk's content edge, so the padding the ribbon adds (#68)
     already keeps the pill under it. */
  top: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  max-width: var(--sheet-w);
  margin: 0 auto var(--s4);
  /* Only the pill takes the pointer; the desk shows through either side of it. */
  pointer-events: none;
}

.dock-bar {
  pointer-events: auto;
  display: flex; align-items: center; gap: var(--s1);
  height: var(--dock-h);
  padding: 0 var(--s1);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: calc(var(--r3) + var(--s1));
  box-shadow: var(--e2);
}

.dock-tab {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--ink-3);
  white-space: nowrap;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.dock-tab:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
.dock-tab[aria-current="page"] {
  background: var(--sunken); color: var(--ink); font-weight: 600;
}

/* A count on a mode is the reason to go there. */
.dock-count {
  min-width: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--accent-wash);
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 10px; line-height: 16px; text-align: center;
}
.dock-tab[aria-current="page"] .dock-count { background: var(--surface); }
