/* Each page scrolls inside the shell's main area on desktop and in harmony builds, and scrolls the
 * document on vanilla mobile (AppShellLayout's native scroll mode - see index.css). overscroll-behavior
 * keeps a scroll that hits the top or bottom from chaining into the document, which in the AEA app's
 * browser would collapse its address bar anyway. */
.page {
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
}
@media (max-width: 767px) {
  html:not(.harmony) .page {
    height: auto;
    overflow-y: visible;
  }
}

/* A page with a rail (e.g. FilterRail): side by side on desktop, the page alone on mobile, where
 * the rail hides itself. */
@media (min-width: 768px) {
  .page-with-rail {
    display: flex;
    height: 100%;
    overflow: hidden;
  }
  .page-with-rail-column {
    flex: 1;
    min-width: 0;
    height: 100%;
  }
}

/* Matches PageHeaderDesktop and PageHeaderMobile's own side padding, so content lines up with the
 * title above it. */
.page-content {
  padding: 16px 20px var(--stratum-app-shell-content-inset-bottom, 0px);
}
@media (min-width: 768px) {
  .page-content {
    padding: 16px 36px var(--stratum-app-shell-content-inset-bottom, 0px);
  }
}

.page-content section {
  margin-top: 24px;
}

.page-intro {
  margin: 0;
  font-size: 18px;
}

.page-label {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.page-content p {
  margin: 0 0 6px;
}
/* Title in normal case at one size, like the tool panel's (ClaudeChatDemo.css). */
.tsk-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}
.tsk-title-count {
  font-weight: 400;
  color: var(--ink-3);
}
.tsk-section {
  margin: 10px 0 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.tsk-section:first-child {
  margin-top: 0;
}

/* The task list, with launched tasks under their agent. Each row's vertical midpoint is where its
   connector meets it; nested lists make each line run from its own parent to its last child. */
.tsk-tree {
  --tsk-gap: 6px;
  --tsk-indent: 22px;
  --tsk-row-mid: 28px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding-bottom: 8px;
}
.tsk-tree > .stratum-button {
  align-self: center;
  margin-top: 6px;
}
.tsk-children {
  list-style: none;
  margin: 0;
  padding: 0;
}
.tsk-children .tsk-children {
  padding-left: var(--tsk-indent);
}
.tsk-branch {
  position: relative;
  padding-top: var(--tsk-gap);
}
.tsk-children .tsk-children > .tsk-branch::before {
  content: '';
  position: absolute;
  left: calc(var(--tsk-indent) / -2 - 1px);
  top: 0;
  bottom: 0;
  border-left: 1px solid var(--line);
}
.tsk-children .tsk-children > .tsk-branch:last-child::before {
  bottom: auto;
  height: calc(var(--tsk-gap) + var(--tsk-row-mid));
  width: calc(var(--tsk-indent) / 2 - 2px);
  border-bottom: 1px solid var(--line);
  border-bottom-left-radius: 8px;
}
.tsk-children .tsk-children > .tsk-branch:not(:last-child)::after {
  content: '';
  position: absolute;
  left: calc(var(--tsk-indent) / -2 - 1px);
  top: calc(var(--tsk-gap) + var(--tsk-row-mid));
  width: calc(var(--tsk-indent) / 2 - 2px);
  border-top: 1px solid var(--line);
}

.tsk-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: calc(var(--tsk-row-mid, 28px) * 2);
  box-sizing: border-box;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.tsk-row:active {
  background: var(--surface-2);
}
.tsk-chevron {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  color: var(--ink-4);
  /* The sprite's chevron points down. */
  transform: rotate(-90deg);
}
.tsk-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tsk-name,
.tsk-facts {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tsk-name {
  font-size: 14.5px;
  font-weight: 500;
}
.tsk-facts {
  font-size: 12.5px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* A task's details. */
.tsk-detail {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 8px;
}
.tsk-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  font-size: 13px;
  color: var(--ink-3);
}
.tsk-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* The session header's "2 running": plain header text, tappable. */
.session-running {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.session-running:hover {
  text-decoration: underline;
}

/* Stop, in a task's status line: plain text, tappable, like the session header's items. */
.tsk-link {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.tsk-link:hover {
  text-decoration: underline;
}
/* The thread scrolls in its own element with the bottom bar pinned below it — not the document
 * scroll other vanilla pages use on mobile. */
.session-page {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
}
/* Mobile: the shell's main area is unbounded in native-scroll mode, so bound to the viewport. */
@media (max-width: 767px) {
  .session-page {
    height: calc(var(--vh, 1vh) * 100);
    overflow: hidden;
  }
}

/* Always scrolls itself. It keeps the shared .page class (desktop wheel forwarding finds it), so
 * this must out-rank .page's mobile document-scroll rule, `html:not(.harmony) .page`. */
.session-page > .session-scroll.page {
  flex: 1;
  min-height: 0;
  height: auto;
  overflow-y: auto;
  overscroll-behavior-y: contain;
}

/* Capped and centered on desktop, like the sessions list; 20px gutters on mobile. */
.session-thread,
.session-bar > * {
  max-width: 760px;
}
.session-thread {
  box-sizing: content-box;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 8px 20px 24px;
}
@media (min-width: 768px) {
  .session-thread {
    padding: 8px 36px 24px;
  }
  .session-thread,
  .session-bar > * {
    margin-inline: auto;
  }
}

.session-loading {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-top: 8px;
}

.session-earlier {
  margin: 0;
  text-align: center;
  font-size: 13px;
  color: var(--ink-3);
}

.session-attachments {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  color: var(--ink-3);
}

.session-bar {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 20px 16px;
}
.session-bar > * {
  width: 100%;
  box-sizing: border-box;
}
@media (min-width: 768px) {
  .session-bar {
    padding: 8px 36px 20px;
  }
}
/* Mobile: just above the pinned bottom nav (fixed chrome, so its exact height). */
@media (max-width: 767px) {
  .session-bar {
    padding-bottom: calc(10px + var(--stratum-app-shell-nav-height, 0px));
  }
}

/* Tool details panel (claude/Thread.tsx's ToolPanel). */
.tool-panel-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 8px;
}

/* Desktop: dock the tool panel to this page, not the viewport, so it lines up with the thread
 * rather than centering across the nav rail too, and give it the thread's outer width (760px
 * content + 36px padding each side). The same approach as media's ReadPage. Mobile keeps
 * BottomPanel's viewport-wide default. The panel sits inside the thread's scroller, but its
 * containing block is this page, so it neither scrolls nor gets clipped with the thread. */
@media (min-width: 768px) {
  .session-page .stratum-bottom-panel {
    position: absolute;
    max-width: calc(760px + 2 * 36px);
  }
}

/* Tool panel title: "Bash  Show the deploy result" in normal case, one size, like the tool rows
 * in the thread. The panel's usual small uppercase label doesn't work for a sentence: capitals look
 * bigger than lowercase at the same size, so an uppercase name never matches its description.
 * BottomPanel's header leaves room for the close button; the summary ellipsizes before it. */
.tool-panel-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}
.tool-panel-summary {
  /* One line that scrolls sideways (swipe or trackpad) to show the rest, rather than an ellipsis;
     no visible scrollbar. */
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
  font-weight: 400;
  color: var(--ink-2);
}
.tool-panel-summary::-webkit-scrollbar {
  display: none;
}

/* The model and the actions menu in the header subtitle: plain header text over a native <select>
   (SelectOverlay), like media's read-page actions. */
.session-model-trigger,
.session-actions-trigger {
  cursor: pointer;
}
.session-model:hover .session-model-trigger,
.session-actions:hover .session-actions-trigger {
  text-decoration: underline;
}

/* An Agent tool call's details (claude/AgentDetails.tsx) in the tool panel. */
.agent-details {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.agent-facts,
.agent-note {
  margin: 0;
  font-size: 13px;
  color: var(--ink-3);
}
.agent-loading {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.agent-thread {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* A task notification in the thread that opens its task: the note's own text, tappable. */
.session-note-link {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
}
.session-note-link:hover {
  text-decoration: underline;
}

/* Find in session: every occurrence of the query in the thread, the current match's stronger. */
::highlight(session-match) {
  background-color: color-mix(in srgb, var(--accent-alt) 28%, transparent);
}
::highlight(session-match-active) {
  background-color: color-mix(in srgb, var(--accent-alt) 60%, transparent);
}

/* Above the composer: the query, its matches, and the way back to the live end. */
.session-find {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px 4px 4px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  font-size: 13px;
  color: var(--ink-2);
}
.session-find-input {
  flex: 1;
  min-width: 0;
  padding: 6px 0;
  border: none;
  outline: none;
  background: transparent;
  font: inherit;
  /* 16px: iOS zooms the page into smaller inputs on focus. */
  font-size: 16px;
  color: var(--ink);
}
.session-find-input::placeholder {
  color: var(--ink-4);
}
.session-find-count {
  flex-shrink: 0;
  padding: 0 6px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.session-find-btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
}
.session-find-btn:hover:not(:disabled) {
  background: var(--surface-2);
}
.session-find-btn:disabled {
  color: var(--ink-4);
  cursor: default;
}
.session-find-btn svg {
  width: 16px;
  height: 16px;
  /* Icons that leave their weight to the caller (i-x) match the chevrons' 2px. */
  stroke-width: 2;
}
.session-find-btn--up svg {
  transform: rotate(180deg);
}
.session-find-note {
  flex: 1;
  min-width: 0;
  padding: 6px 0;
  color: var(--ink-3);
}
/* On desktop the list centers in a readable column, like the session thread; the header title
 * stays left. */
.sessions-content {
  max-width: 760px;
  display: flex;
  flex-direction: column;
}
@media (min-width: 768px) {
  .sessions-content {
    margin-inline: auto;
  }
}

.sessions-host {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.sessions-skeleton-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
}
.sessions-skeleton-row + .sessions-skeleton-row {
  border-top: 1px solid var(--line);
}

/* Filters and Select, in the header's subtitle: plain text, tappable. */
.sessions-subtitle-link {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.sessions-subtitle-link:hover {
  text-decoration: underline;
}

.sessions-filter-count {
  color: var(--ink-4);
}
.sessions-mark {
  border-radius: 3px;
  background: color-mix(in srgb, var(--accent-alt) 28%, transparent);
  color: inherit;
}
/* Under the lists: a section's distance from them, not hugging the last row. */
.sessions-searching {
  margin: 20px 4px 0;
  font-size: 13px;
  color: var(--ink-3);
}

/* Active filters as removable pills. */
.sessions-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}
.sessions-pill {
  padding: 4px 10px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--surface);
  font: inherit;
  font-size: 12.5px;
  color: var(--ink-2);
  cursor: pointer;
}
.sessions-pill--clear {
  border-color: transparent;
  background: none;
  color: var(--accent);
}

/* Select mode: a band under the desktop header, a bar at the bottom on mobile (media's Library). */
.sessions-edit-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 36px;
  background: var(--accent-soft);
  border-bottom: 1px solid var(--line);
}
.sessions-edit-bar-mobile {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 18px calc(6px + var(--safe-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--line);
}
@media (min-width: 768px) {
  .sessions-edit-bar-mobile {
    display: none;
  }
}
.sessions-count-label {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.sessions-spacer {
  flex: 1;
}
.settings {
  max-width: 620px;
  margin: 0 auto;
}
.viewport-debug {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 8px);
  right: 8px;
  z-index: 1000;
  margin: 0;
  padding: 8px 10px;
  font: 11px/1.4 ui-monospace, Menlo, monospace;
  color: #fff;
  background: rgba(0, 0, 0, 0.75);
  border-radius: 8px;
  pointer-events: none;
}

/* Invisible elements whose measured heights read out CSS viewport units and the safe-area inset. */
.viewport-debug-probes {
  position: fixed;
  top: 0;
  left: -10px;
  width: 1px;
  visibility: hidden;
  pointer-events: none;
}
.viewport-debug-probes > div {
  position: absolute;
  top: 0;
  width: 1px;
}
.viewport-debug-safe {
  height: env(safe-area-inset-bottom, 0px);
}
:root {
  /* Extra bottom clearance stratum-ui's AppShellLayout adds under the installed PWA's bottom nav. */
  --pwa-nav-pad: 24px;
}

* {
  box-sizing: border-box;
}

/* --vh (index.tsx), not 100% or 100vh: iOS Safari can leave a CSS viewport height stale across
 * client-side route changes, leaving the page shorter than the screen. */
html,
body {
  margin: 0;
  padding: 0;
  height: calc(var(--vh, 1vh) * 100);
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden;
}

/* Vanilla mobile pages scroll the document (AppShellLayout's native scroll mode), which keeps iOS
 * Safari's text selection working. Desktop scrolls inside the shell instead.
 *
 * Harmony keeps the document still on mobile too: the AEA app's browser collapses its address bar into
 * a floating pill whenever the document scrolls, covering the bottom nav, and it reports no viewport
 * change that the page could reliably lift the nav by. A document that never scrolls keeps the bar
 * expanded. .harmony is added only by harmony builds (see index.tsx). */
@media (max-width: 767px) {
  html:not(.harmony) body {
    overflow: visible;
  }
}

#root {
  height: 100%;
}
