/* The browser panel needs real width for a page to be legible in it -- the shared
   .app-dialog cap (40rem) is right for a review list, not a browser viewport. A view turn
   goes further: the page itself scrolls inside the remote browser, so the dialog is a tall
   column whose body refuses the scroll the remote page already owns. */
.browser-panel {
  width: min(64rem, 90%);
  height: min(calc(var(--browser-visual-height, var(--vh100)) - 2rem), 60rem, var(--dialog-max-height));
  max-height: min(calc(var(--browser-visual-height, var(--vh100)) - 2rem), 60rem, var(--dialog-max-height));
}

.browser-panel .browser-panel-frame {
  display: flex;
  flex-direction: column;
  height: 100%;
  max-height: none;
}

.browser-panel-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: var(--space-r3);
  overflow: hidden;
}

.browser-panel-status {
  margin: 0;
  color: var(--muted);
}
.browser-panel-status:empty {
  display: none;
}

/* One compact header in every mode: [back][forward][reload] title … [external link] on a
   row, the status line small and single-line beneath. The nav buttons are quiet 44px icon
   buttons, not the gold primary pill. */
.browser-panel-header {
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--space-r1);
  padding: 0.35rem var(--space-r2);
}

/* App typography cannot resize text inside the rendered remote-page image; only the app's own
   title, status, address and actions here follow the text-size preset and wrap. */
.browser-panel-header h2 {
  flex: 1 1 0;
  min-width: 0;
  overflow-wrap: break-word;
  padding-left: var(--space-r1);
}

/* The page-host heading is already the page's visible title; keep this live dialog label for
   aria-labelledby and JS updates without showing the same title twice. */
.browser-page-host .browser-panel-header h2 {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.browser-nav-button {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--touch-min);
  min-width: var(--touch-min);
  height: var(--touch-min);
  min-height: var(--touch-min);
  padding: 0;
  background: transparent;
  border-color: transparent;
  border-radius: var(--radius-pill);
  color: var(--ink);
}

.browser-nav-button:hover,
.browser-nav-button:focus-visible {
  background: var(--panel-subtle);
}

.browser-nav-button[hidden] {
  display: none;
}

.browser-nav-button svg,
.browser-open-external svg {
  width: 20px;
  height: 20px;
  stroke-width: 2;
}

.browser-panel-header .browser-panel-status {
  flex: 1 0 100%;
  order: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  padding: 0 var(--space-r1) 0.15rem;
  font-size: var(--text-support);
}

.browser-open-external {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--touch-min);
  min-height: var(--touch-min);
  color: var(--muted);
}

.browser-open-external:hover,
.browser-open-external:focus-visible {
  color: var(--ink);
}

.browser-open-external[hidden],
.browser-address-form[hidden],
.browser-panel-footer[hidden] {
  display: none;
}

.browser-address-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--touch-min);
}

.browser-address-go {
  flex: none;
  min-width: var(--touch-min);
  min-height: var(--touch-min);
}

/* The key bar: an invisible input over the remote page's own field, rendered in the frame, which
   is the only visible field; it rides up with the frame when the keyboard needs the room. The
   input's 16px is on purpose: an iOS Safari input below 16px zooms the page on focus. */
.browser-key-bar {
  position: absolute;
  z-index: 2;
  box-sizing: border-box;
  min-height: 36px;
  transform: translateY(calc(-1 * var(--browser-frame-shift, 0px)));
}

.browser-key-bar[hidden] {
  display: none;
}

.browser-key-bar .browser-key-input.app-field {
  display: block;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  min-height: 36px;
  margin: 0;
  padding-block: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  background-color: transparent;
  color: transparent;
  caret-color: transparent;
  box-shadow: none;
  font: inherit;
  font-size: max(1rem, calc(1rem * var(--text-scale)));
}

.browser-key-bar .browser-key-input.app-field:focus-visible {
  border-color: transparent;
  box-shadow: none;
  outline: none;
}

.browser-job-note {
  margin: 0;
  padding: var(--space-r2) var(--space-r1);
  color: var(--ink);
  font-size: var(--text-detail-body);
  line-height: 1.4;
  white-space: pre-line;
  overflow-wrap: anywhere;
  max-height: 8.5rem;
  overflow-y: auto;
  flex: none;
}

.browser-job-note.browser-job-note-alone {
  max-height: none;
}

.browser-job-note[hidden] {
  display: none;
}

.browser-view-wrap[hidden] {
  display: none;
}

.browser-view-wrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-surface);
  background: var(--panel);
  overflow: hidden;
}

.browser-view-wrap[aria-busy="true"]::after {
  content: 'Loading page…';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel);
  color: var(--muted);
}

.browser-frame {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  transform: translateY(calc(-1 * var(--browser-frame-shift, 0px)));
  background: var(--panel-subtle);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  overscroll-behavior: none;
}

.browser-frame:not([src]) {
  visibility: hidden;
}

/* The one empty line while the wrap shows no page, centred in it; browser-panel.js un-hides it
   exactly while the frame image carries no src. The [hidden] rule is needed because the id
   selector would otherwise outrank the browser's own hidden handling. */
#browser-view-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--space-r3);
}

#browser-view-empty[hidden] {
  display: none;
}

.browser-view-working {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-r1);
  padding: 0 var(--space-r3);
  color: var(--muted);
  font-size: var(--text-support);
  pointer-events: none;
}

.browser-view-working[hidden] {
  display: none;
}

.browser-view-working[data-over] {
  z-index: 1;
  inset: auto;
  top: var(--space-r3);
  left: 50%;
  transform: translateX(-50%);
  padding: var(--space-r1) var(--space-r2);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
}

.browser-view-working[data-over] #browser-view-working-text:empty {
  display: none;
}

.browser-frame-disabled {
  pointer-events: none;
  opacity: 0.6;
}

.browser-panel-error {
  margin: 0;
  color: var(--error);
}

/* The Browser page: browser-panel.js moves the panel's frame out of its dialog into this
   host, so none of the .browser-panel rules above reach it. The pane itself neither
   scrolls nor pads for the composer -- .chat-lower already reserves that clearance -- so the
   host takes whatever height is left and the frame fills it, with only the remote page
   scrolling inside. The frame is its own opaque surface, as it is in the dialog. */
.browser-page {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-height: 0;
  padding: 0 var(--list-gutter);
  overflow: hidden;
}

.browser-page > .app-page,
.browser-page > .app-page > .app-page-body {
  flex: 1 1 0;
  min-height: 0;
}

.browser-page > .app-page > .app-page-body {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.browser-page[hidden] {
  display: none;
}

.browser-page-host {
  display: flex;
  flex: 1 1 auto;
  min-height: 45vh;
  padding-bottom: var(--space-r2);
}

.browser-page-host .browser-panel-frame {
  position: static;
  flex: 1 1 auto;
  width: 100%;
  height: 100%;
  max-height: none;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-surface);
  background: var(--panel);
  overflow: hidden;
}

/* The composer above a tall task list, or a header that wraps to three rows on a phone, can
   leave the frame almost no height. It keeps a usable minimum and the body scrolls instead. */
.browser-page-host .browser-panel-body {
  overflow-y: auto;
  overscroll-behavior: contain;
  gap: var(--rhythm-card-card);
}

.browser-page-host .browser-view-wrap {
  flex: 1 1 12rem;
  min-height: 12rem;
}

/* The page header hands the pane's inset back, as every scroller pane's does, so the title
   lands at --page-gutter like the other destinations. */
.browser-page .app-page-header {
  margin-inline: calc(var(--list-gutter) * -1);
}

@media (max-width: 47.99rem) {
  .browser-page-host .browser-panel-body {
    padding: var(--space-r2);
  }
}

/* A handoff: a paused job at a sign-in wall (browser-panel.js puts browser-panel-handoff on the
   frame, wherever it is mounted, and browser-panel-signin on the dialog when it is the modal).
   The header is one row -- site name, Check sign-in, Close -- and one line beneath; the page is
   edge to edge below it, with nothing else on screen. The page image keeps its own pixels; only
   the app's title, line and note scale. */
.browser-signin-control[hidden],
.browser-signin-line[hidden],
.browser-signin-note[hidden] {
  display: none;
}

/* Two classes, so it outranks .app-dialog-header button (44px). */
.browser-panel-header .browser-signin-control {
  flex: none;
  min-block-size: 48px;
  min-inline-size: 48px;
  padding: 0 var(--space-r3);
}

.browser-signin-line,
.browser-signin-note {
  flex: 1 0 100%;
  order: 1;
  min-width: 0;
  margin: 0;
  padding: 0 var(--space-r1) 0.15rem;
  overflow-wrap: anywhere;
  font-size: var(--text-support);
  color: var(--muted);
}

.browser-signin-note {
  color: var(--ink);
}

.browser-panel-body .browser-signin-line {
  flex: none;
  order: 0;
  padding: 0;
}

.browser-key-input.browser-key-secret {
  -webkit-text-security: disc;
}

.browser-panel:not(.browser-panel-signin) .browser-panel-handoff .browser-panel-header {
  gap: 0;
  padding: var(--space-r1) var(--space-r2);
}

.browser-panel:not(.browser-panel-signin) .browser-panel-handoff .browser-panel-header h2 {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.browser-panel:not(.browser-panel-signin) .browser-panel-handoff .browser-panel-body {
  padding: 0;
  gap: 0;
}

.browser-panel:not(.browser-panel-signin) .browser-panel-handoff .browser-view-wrap {
  border: none;
  border-radius: 0;
}

.browser-panel-handoff .browser-panel-error {
  padding: var(--space-r2);
}

/* A non-signin browser panel on a phone is full-screen. */
@media (max-width: 47.99rem) {
  .browser-panel:not(.browser-panel-signin) {
    box-sizing: border-box;
    padding: var(--fullscreen-pad);
    width: 100%;
    max-width: 100%;
    height: var(--browser-visual-height, var(--vh100));
    max-height: var(--browser-visual-height, var(--vh100));
    margin: 0;
    border: none;
    border-radius: 0;
  }
}

.browser-panel.browser-panel-signin .browser-panel-frame {
  height: auto;
  max-height: none;
}

.browser-panel.browser-panel-signin .browser-view-wrap {
  flex: none;
  block-size: min(20rem, calc(var(--vh100) * 0.32));
}

.browser-panel.browser-panel-signin #browser-signin-line {
  padding: 0;
}

/* Browser answer cards in the agent result modal: one tappable link per result, shaped like .thread-option. */
.answer-cards {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* .app-pill sets flex: none; this loads after styles.css, so a long hint wraps inside its pill instead of overflowing the row. */
.answer-hint {
  flex: 0 1 auto;
  max-width: 100%;
  text-align: left;
}

.proof-thumb {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  width: max-content;
  max-width: 9rem;
  flex: none;
  color: var(--muted);
  text-decoration: none;
}

button.proof-thumb {
  padding: 0;
  font: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

.proof-viewer-img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-control);
}

/* The session fields of a job waiting on a login; the live corner thumb beside them is a button. */
.browser-job-login {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-r2);
}

.browser-job-login > .app-row-meta {
  flex-basis: 100%;
  margin: 0;
}

.browser-job-login-field {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-r1);
}

.browser-job-login-field label {
  font-size: var(--text-support);
  color: var(--muted);
}

/* The login thumb already shows a crop around the field, so it centres the crop instead of pinning its top. */
.thread-body > .proof-thumb.browser-job-login-thumb .proof-thumb-img,
.agent-modal .app-dialog-body > .proof-thumb.browser-job-login-thumb .proof-thumb-img {
  object-position: center;
}

.thread-body > .proof-thumb ~ .browser-job-login,
.agent-modal .app-dialog-body > .proof-thumb ~ .browser-job-login {
  padding-inline-end: calc(2.75rem + var(--space-r2));
  min-height: 2.75rem;
}

.proof-thumb-img {
  display: block;
  width: 4.5rem;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: top;
  background: var(--panel-subtle);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-control);
}

.proof-thumb-domain {
  overflow: hidden;
  font-size: var(--text-detail-meta);
  color: var(--muted);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* In a thread body or an agent modal body the thumb is a small square image without its caption (its aria-label names the domain), pinned to the top inline-end corner beside the answer text; the text (or the modal's answer cards) reserves the thumb's width and height so the content below never overlaps it. An activity row shows the same small image. */
.thread-body:has(> .proof-thumb),
.agent-modal .app-dialog-body:has(> .proof-thumb) {
  position: relative;
}

.thread-body > .proof-thumb,
.agent-modal .app-dialog-body > .proof-thumb {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  width: 2.75rem;
}

/* 0.9rem matches the .app-dialog-body padding, so the thumb sits inside the modal edge. */
.agent-modal .app-dialog-body > .proof-thumb {
  inset-block-start: 0.9rem;
  inset-inline-end: 0.9rem;
}

.thread-body > .proof-thumb .proof-thumb-img,
.agent-modal .app-dialog-body > .proof-thumb .proof-thumb-img {
  width: 2.75rem;
  aspect-ratio: 1 / 1;
  object-position: top;
}

.thread-body > .proof-thumb .proof-thumb-domain,
.agent-modal .app-dialog-body > .proof-thumb .proof-thumb-domain {
  display: none;
}

.thread-body > .proof-thumb ~ .thread-reply-text,
.agent-modal .app-dialog-body > .proof-thumb ~ .thread-reply-text,
.agent-modal .app-dialog-body > .proof-thumb ~ .answer-cards {
  padding-inline-end: calc(2.75rem + var(--space-r2));
}

.thread-body > .proof-thumb ~ .thread-reply-text:first-of-type,
.agent-modal .app-dialog-body > .proof-thumb ~ .thread-reply-text:first-of-type,
.agent-modal .app-dialog-body > .proof-thumb ~ .answer-cards:first-of-type {
  min-height: 2.75rem;
}

/* The dialog header already names the page. */
.agent-page-modal .pages-card {
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
}

.activity-item > .proof-thumb {
  width: 2.25rem;
  align-self: center;
  margin-inline-end: var(--space-r2);
}

.activity-item > .proof-thumb .proof-thumb-img {
  width: 2.25rem;
  aspect-ratio: 1 / 1;
  object-position: top;
}

.activity-item > .proof-thumb .proof-thumb-domain {
  display: none;
}

.answer-card {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: var(--space-r2) 0.7rem;
  color: var(--ink);
  text-decoration: none;
  background: var(--panel-subtle);
  border: 1px solid var(--card-line);
  border-radius: var(--card-radius);
}

.answer-card:hover,
.answer-card:focus-visible {
  background: var(--panel);
}

.answer-pick-actions {
  margin-top: var(--space-xs);
}

.answer-pick-actions .app-quiet-button {
  text-decoration: none;
  align-self: flex-start;
}

.answer-card-art {
  width: 56px;
  height: 56px;
  flex: none;
  object-fit: cover;
  border-radius: var(--radius-control);
}

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

.answer-card-text > .app-tag {
  align-self: flex-start;
}

.answer-card-title {
  font-weight: var(--w-title);
}

.answer-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.6rem;
  font-size: var(--text-detail-meta);
}

.answer-card-price {
  color: var(--ink);
}

.answer-card-rating,
.answer-card-store,
.answer-card-fact {
  color: var(--muted);
  font-size: var(--text-detail-meta);
}

.agent-modal-actions {
  display: flex;
  flex: 1 1 100%;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: var(--space-r2);
}

.agent-job-modal,
.agent-reply-modal,
.app-dialog-subject,
.browser-panel.browser-panel-signin {
  position: fixed;
  /* Reserve the bar without its activity drawer, which collapses when a sheet opens. */
  inset: var(--answer-top, calc(var(--safe-top) + var(--space-r2))) 0 calc(var(--command-bar-base, var(--command-bar-space)) + var(--space-r2));
  width: min(40rem, 90%);
  margin: auto;
  z-index: 30;
  border-radius: var(--radius-overlay);
}

.agent-job-modal,
.agent-reply-modal,
.app-dialog-subject,
.browser-panel.browser-panel-signin {
  height: max-content;
  max-height: var(--answer-max, min(calc(100% - var(--command-bar-base, var(--command-bar-space)) - var(--safe-top) - var(--space-xl) * 2), 46rem));
}

.browser-panel.browser-panel-signin {
  max-width: none;
}

/* The bound is the viewport, never a percentage of the dialog, whose max-content height makes a percentage circular. */
/* An engine that resolves it to zero collapses the sheet to its border. */
.agent-job-modal .app-dialog-frame,
.agent-reply-modal .app-dialog-frame,
.browser-panel.browser-panel-signin .app-dialog-frame {
  max-height: var(--answer-max, min(calc(var(--vh100) - var(--command-bar-base, var(--command-bar-space)) - var(--safe-top) - var(--space-xl) * 2), 46rem));
}

/* The dialog's own max-height bounds the frame so its body scrolls instead of overflowing. */
.app-dialog-subject[open] {
  display: flex;
  flex-direction: column;
}

.app-dialog-subject[open] > .app-dialog-frame {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

.agent-reply-modal .app-dialog-header h2 {
  font-size: var(--text-section);
  min-width: 0;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.browser-result-pick {
  display: flex;
  align-items: center;
  gap: var(--space-r2);
}

.agent-modal-actions > a.app-primary-button {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

.browser-result-pick > .proof-thumb {
  position: static;
  width: 3.5rem;
}

.browser-result-pick > .proof-thumb .proof-thumb-img {
  width: 3.5rem;
  aspect-ratio: 1;
}

.browser-result-pick > .proof-thumb .proof-thumb-domain {
  display: none;
}

.browser-result-pick-text {
  min-width: 0;
}

.browser-result-pick .app-row-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--row-title-lines);
  line-clamp: var(--row-title-lines);
  overflow: hidden;
}

.browser-result-pick .app-row-title {
  display: block;
  overflow: visible;
}
