/* ==========================================================================
   Browsa dashboard additions (app-ds.css)
   The dashboard is built from ds.css. This file holds only what the system
   does not have yet, written with the system's tokens (no literal colours,
   sizes or radii). Every class is prefixed app-. Each block says why it
   exists; when ds.css grows the same piece, delete the block here.

   1 form messages  2 option rows and folds  3 popovers  4 settings layout
   5 auth  6 run view  7 step timeline  8 result tree  9 usage chart
   10 live-view dialog  11 small fixes
   ========================================================================== */

/* 1. FORM MESSAGES ---------------------------------------------------------- */
/* A message under a form that can hold links (ds-error is a flex row for one line of text). */
.app-msg { font-size: var(--ds-text-sm); line-height: 1.45; color: var(--ds-ink-2); }
.app-msg[data-tone="error"] { color: var(--ds-red-ink); }
.app-msg[data-tone="warning"] { color: var(--ds-amber-ink); }
.app-msg a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
/* "Or use your email": words on a rule. */
.app-or { display: flex; align-items: center; gap: var(--ds-space-3); font-size: var(--ds-text-xs); color: var(--ds-ink-3); }
.app-or::before, .app-or::after { content: ""; flex: 1; height: 1px; background: var(--ds-line); }

/* 2. OPTION ROWS AND FOLDS -------------------------------------------------- */
/* A ruled list of settings: label (and its "?") on the left, control on the right. ds-kv is for values, not controls. */
.app-rows { display: grid; }
.app-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--ds-space-2) var(--ds-space-4); min-height: 2.75rem; padding-block: var(--ds-space-2); border-bottom: var(--ds-border); }
.app-row__label { display: flex; align-items: center; gap: var(--ds-space-1); min-width: 0; }
.app-row__full { grid-column: 1 / -1; }
.app-row--stack { grid-template-columns: minmax(0, 1fr); }
.app-row--stack > .ds-select { justify-self: start; }
.app-w-num { width: 6.5rem; }
/* A section that opens in place (details). The chevron turns; the summary on the right says what is set. */
.app-fold { border-bottom: var(--ds-border); }
.app-fold > summary { display: flex; align-items: center; gap: var(--ds-space-2); min-height: 2.75rem; cursor: pointer; list-style: none; font: 500 var(--ds-text-sm)/1.3 var(--ds-font-text); color: var(--ds-ink); }
.app-fold > summary::-webkit-details-marker { display: none; }
.app-fold > summary .ds-icon { color: var(--ds-ink-3); transition: transform var(--ds-dur-2) var(--ds-ease-out); }
.app-fold[open] > summary .ds-icon { transform: rotate(90deg); }
.app-fold > summary:hover .ds-icon { color: var(--ds-ink); }
.app-fold__name { flex: none; }
.app-fold__sum { margin-inline-start: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; color: var(--ds-ink-3); }
.app-fold__body { padding-block: var(--ds-space-2) var(--ds-space-5); }
.app-toolbar { padding-bottom: var(--ds-space-4); }

/* 3. POPOVERS --------------------------------------------------------------- */
/* "?" help: a ds-menu whose panel holds one sentence instead of items. */
.app-q { display: inline-flex; }
.app-help { padding: var(--ds-space-3); width: max-content; max-width: min(18rem, calc(100vw - 2rem)); font: 400 var(--ds-text-sm)/1.45 var(--ds-font-text); color: var(--ds-ink-2); white-space: normal; }
.app-help .ds-field + * { margin-top: var(--ds-space-3); }
/* A panel that stays open while you work in it (model picker): ds-menu closes on every item click. */
.app-popwrap { position: relative; display: inline-flex; min-width: 0; }
.app-pop { position: absolute; z-index: var(--ds-z-pop); top: calc(100% + 0.375rem); left: 0; width: min(24rem, calc(100vw - 2rem)); max-height: min(32rem, 70dvh); overflow: auto; padding: var(--ds-space-1); border-radius: var(--ds-radius-md); background: var(--ds-raised); box-shadow: var(--ds-shadow-pop); animation: ds-pop var(--ds-dur-2) var(--ds-ease-out); transform-origin: top left; scrollbar-width: thin; }
.app-pop .ds-menu__item { align-items: flex-start; flex-direction: column; gap: 0.125rem; padding-block: 0.375rem; }
.app-pop .ds-menu__item small { color: var(--ds-ink-3); font-size: var(--ds-text-xs); }
.app-pop .ds-menu__item[aria-checked="true"]::after { position: absolute; right: 0.75rem; margin: 0.25rem 0 0; }
.app-pop .ds-menu__item { position: relative; padding-inline-end: 2rem; }
.app-pop__detail { display: grid; gap: var(--ds-space-3); padding: var(--ds-space-3) var(--ds-space-2) var(--ds-space-2); border-top: var(--ds-border); margin-top: var(--ds-space-1); }
.app-pop details > summary { cursor: pointer; list-style: none; }
.app-pop details > summary::-webkit-details-marker { display: none; }

/* 4. SETTINGS LAYOUT -------------------------------------------------------- */
/* Side tabs on the desk, joined to the sheet on their right. Under 56rem the side tabs become a strip. */
.app-settings { display: grid; grid-template-columns: minmax(0, 1fr); min-height: 100%; }
.app-settings__nav { display: none; }
.app-settings__tabs { padding-inline: var(--ds-gutter); padding-top: var(--ds-space-2); background: var(--ds-desk); }
.app-settings__body { padding-inline: var(--ds-gutter); min-width: 0; }
@media (min-width: 56rem) {
  .app-settings { grid-template-columns: 15rem minmax(0, 1fr); }
  .app-settings__nav { display: grid; padding-inline-start: var(--ds-gutter); background: var(--ds-desk); }
  .app-settings__tabs { display: none; }
  .app-settings__body { max-width: 64rem; padding-inline: var(--ds-space-10) var(--ds-gutter); }
}
.ds-app__main:has(> .app-settings:not([hidden])) { display: flex; flex-direction: column; }
.ds-app__main > .app-settings { flex: 1; }
.app-narrow { max-width: 34rem; }

/* 5. AUTH ------------------------------------------------------------------- */
.app-auth__form { max-width: 26rem; }
.app-auth__form .ds-pagehead { padding-top: var(--ds-space-10); }
.app-auth__foot { margin-block: var(--ds-space-5) var(--ds-space-2); }
.app-auth__aside { padding-top: var(--ds-space-10); }
@container (max-width: 56rem) { .app-auth__aside { display: none; } }
.app-code-input { letter-spacing: 0.3em; text-transform: uppercase; }

/* 6. RUN VIEW --------------------------------------------------------------- */
/* Facts strip: ID, address, status, time and credits in one ruled line, each with a copy button. */
.app-facts dd { display: flex; align-items: center; gap: var(--ds-space-1); min-width: 0; font-size: var(--ds-text-md); }
.app-facts dd > :first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.app-facts > div { min-width: 0; }
/* Chat on the left, browser, files and recording on the right. The panel is a sheet under its own tabs. */
.app-run { display: grid; grid-template-columns: minmax(0, 1fr); min-height: calc(100dvh - 5.75rem); }
.app-run__chat { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.app-run__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-2) var(--ds-space-3); padding: var(--ds-space-4) var(--ds-gutter) var(--ds-space-3); border-bottom: var(--ds-border); }
.app-run__title { flex: 1 1 12rem; min-width: 0; font: 600 var(--ds-text-base)/1.3 var(--ds-font-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-run__scroll { flex: 1; min-height: 12rem; overflow: auto; padding: var(--ds-space-5) var(--ds-gutter); scrollbar-width: thin; scrollbar-color: var(--ds-line-2) transparent; }
.app-run__thread { display: grid; gap: var(--ds-space-8); max-width: 46rem; margin-inline: auto; }
.app-run__compose { padding: var(--ds-space-3) var(--ds-gutter) var(--ds-space-4); }
.app-run__compose > * { max-width: 46rem; margin-inline: auto; }
.app-run__panel { display: none; flex-direction: column; min-width: 0; background: var(--ds-desk); border-top: 1px solid var(--ds-line-2); }
.app-run[data-panel="open"] .app-run__panel { display: flex; }
.app-run__phead { display: flex; align-items: flex-end; gap: var(--ds-space-2); padding: var(--ds-space-2) var(--ds-space-3) 0; box-shadow: inset 0 -1px 0 var(--ds-line-2); }
.app-run__phead .ds-tabs { flex: 1; box-shadow: none; }
.app-run__pacts { display: flex; align-items: center; gap: var(--ds-space-1); padding-bottom: 0.25rem; }
.app-run__pbody { flex: 1; min-height: 20rem; padding: var(--ds-space-4); background: var(--ds-sheet); overflow: auto; }
@media (min-width: 56rem) {
  .app-run { height: calc(100dvh - 5.75rem); min-height: 0; }
  .app-run[data-panel="open"] { grid-template-columns: minmax(22rem, 2fr) minmax(0, 3fr); }
  .app-run[data-panel="open"][data-expanded] { grid-template-columns: minmax(0, 1fr); }
  .app-run[data-panel="open"][data-expanded] .app-run__chat { display: none; }
  .app-run__panel { border-top: 0; border-inline-start: 1px solid var(--ds-line-2); min-height: 0; }
}
.app-turn { display: grid; gap: var(--ds-space-3); }
/* What you asked: a quiet block on the right edge of the thread. */
.app-bubble { justify-self: end; max-width: 85%; padding: var(--ds-space-3) var(--ds-space-4); border-radius: var(--ds-radius-md); background: var(--ds-sunken); box-shadow: inset 0 0 0 1px var(--ds-line); color: var(--ds-ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.app-answer { display: grid; gap: var(--ds-space-3); min-width: 0; }
.app-answer p { color: var(--ds-ink); line-height: var(--ds-leading-prose); overflow-wrap: anywhere; }
.app-answer p + p { margin-top: 0.75em; }
.app-answer a { color: inherit; text-decoration: underline; text-decoration-color: var(--ds-line-control); text-underline-offset: 3px; }
/* The live browser: the page area of a ds-window, at a screen's shape. */
.app-viewport { position: relative; display: grid; place-items: center; aspect-ratio: 16 / 10; min-height: 14rem; background: var(--ds-sunken); }
.app-viewport iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: var(--ds-sunken); }
.app-viewport__cover { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; place-content: center; gap: var(--ds-space-2); background: var(--ds-sunken); color: var(--ds-ink-3); font-size: var(--ds-text-sm); }
.app-viewport .ds-empty { padding: var(--ds-space-6); justify-items: center; text-align: center; }
.app-media { display: block; max-width: 100%; height: auto; border-radius: var(--ds-radius-sm); box-shadow: 0 0 0 1px var(--ds-line-2); }
.app-pad { padding: var(--ds-space-5); min-width: 0; }
.app-scrape-result { align-self: start; }
.app-scrape-result .ds-code { border: 0; border-radius: 0; }
.app-scrape-result pre, .app-clip pre { max-height: 34rem; overflow: auto; }

/* 7. STEP TIMELINE ---------------------------------------------------------- */
/* ds-trace rows that open (details) to show the page, output and raw step. */
.app-trace { padding: 0; }
.app-trace > li { display: block; padding: 0; border-bottom: var(--ds-border); }
.app-trace > li::before { content: none; }
.app-trace > li:last-child { border-bottom: 0; }
.app-step > summary, .app-step__row { display: grid; grid-template-columns: 1rem minmax(0, 1fr) auto auto; gap: var(--ds-space-2); align-items: baseline; padding-block: 0.5rem; list-style: none; }
.app-step > summary { cursor: pointer; }
.app-step > summary::-webkit-details-marker { display: none; }
.app-step > summary > .ds-icon, .app-step__row > .ds-icon { align-self: center; color: var(--ds-ink-3); }
.app-step > summary > .ds-icon:last-child { transition: transform var(--ds-dur-2) var(--ds-ease-out); }
.app-step[open] > summary > .ds-icon:last-child { transform: rotate(90deg); }
.app-step__label { color: var(--ds-ink); min-width: 0; overflow-wrap: anywhere; }
.app-step__sub { display: block; color: var(--ds-ink-3); font-size: var(--ds-text-xs); }
.app-step__time { color: var(--ds-ink-3); font-size: var(--ds-text-xs); white-space: nowrap; }
.app-step[data-tone="error"] .app-step__label, .app-step__row[data-tone="error"] .app-step__label { color: var(--ds-red-ink); }
.app-step[data-tone="warning"] .app-step__label { color: var(--ds-amber-ink); }
.app-step__detail { display: grid; gap: var(--ds-space-3); padding: 0 0 var(--ds-space-4) 1.5rem; min-width: 0; }
.app-step__think { padding-inline-start: 1.5rem; color: var(--ds-ink-3); font-size: var(--ds-text-sm); }
.app-step__think > summary { cursor: pointer; list-style: none; padding-block: 0.25rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-step__think > summary::-webkit-details-marker { display: none; }
.app-step__think[open] > summary { white-space: normal; }
.app-step__think p { padding-bottom: var(--ds-space-2); white-space: pre-wrap; color: var(--ds-ink-2); }
.app-trace-head { display: flex; align-items: center; gap: var(--ds-space-2); width: 100%; min-height: var(--ds-h-md); padding: 0; border: 0; border-bottom: 1px solid var(--ds-line-2); background: none; color: var(--ds-ink); font: 500 var(--ds-text-sm)/1.3 var(--ds-font-text); text-align: start; cursor: pointer; }
.app-trace-head .ds-icon { margin-inline-start: auto; color: var(--ds-ink-3); transition: transform var(--ds-dur-2) var(--ds-ease-out); }
.app-trace-head[aria-expanded="true"] .ds-icon { transform: rotate(90deg); }
.app-trace-head small { color: var(--ds-ink-3); font-weight: 400; font-size: inherit; }
/* Step timeline with an evidence pane (when the API has /steps). */
.app-evidence { display: grid; gap: var(--ds-space-5); }
@container (min-width: 52rem) { .app-evidence { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; } .app-evidence__pane { position: sticky; top: var(--ds-space-4); } }
.app-evidence__list button { display: grid; grid-template-columns: 1.5rem minmax(0, 1fr) auto; gap: var(--ds-space-2); width: 100%; padding: 0.5rem; border: 0; border-bottom: var(--ds-border); background: none; color: var(--ds-ink-2); font: inherit; font-size: var(--ds-text-sm); text-align: start; cursor: pointer; }
.app-evidence__list button:hover, .app-evidence__list button[aria-pressed="true"] { background: var(--ds-hover); color: var(--ds-ink); }

/* 8. RESULT TREE ------------------------------------------------------------ */
/* A JSON value as a tree that opens branch by branch. */
.app-tree { font: 400 var(--ds-text-xs)/1.7 var(--ds-font-code); color: var(--ds-ink-2); overflow-wrap: anywhere; }
.app-tree details { padding-inline-start: var(--ds-space-4); }
.app-tree > details { padding-inline-start: 0; }
.app-tree summary { cursor: pointer; list-style: none; margin-inline-start: calc(-1 * var(--ds-space-4)); padding-inline-start: var(--ds-space-4); position: relative; }
.app-tree > details > summary { margin-inline-start: 0; }
.app-tree summary::-webkit-details-marker { display: none; }
.app-tree summary::before { content: ""; position: absolute; left: 0.25rem; top: 0.55em; width: 0.3rem; height: 0.3rem; border-right: 1.5px solid var(--ds-ink-3); border-bottom: 1.5px solid var(--ds-ink-3); transform: rotate(-45deg); transition: transform var(--ds-dur-1); }
.app-tree details[open] > summary::before { transform: rotate(45deg); }
.app-tree__leaf { padding-inline-start: var(--ds-space-4); }
.app-tree__k { color: var(--ds-ink); }
.app-tree__n { color: var(--ds-ink-3); }

/* 9. USAGE CHART ------------------------------------------------------------ */
/* The one chart: ink columns on hairline gridlines with tabular axis labels (usageDrawChart). */
.app-chart { position: relative; outline-offset: 2px; }
.app-chart svg { display: block; }
.app-chart .usage-grid { stroke: var(--ds-line); stroke-width: 1; shape-rendering: crispEdges; }
.app-chart .usage-grid.is-zero { stroke: var(--ds-line-2); }
.app-chart .usage-axis { fill: var(--ds-ink-3); font: 400 var(--ds-text-2xs)/1 var(--ds-font-text); font-variant-numeric: tabular-nums; }
.app-chart .usage-hit { fill: transparent; }
.app-chart .usage-hit.is-active { fill: var(--ds-hover); }
.app-chart .uv-col { fill: var(--ds-ink); }
.app-chart .uv-col.is-neg { fill: var(--ds-ink-3); }
.app-chart .usage-tip { position: absolute; z-index: var(--ds-z-raised); min-width: 11rem; padding: var(--ds-space-2) var(--ds-space-3); border-radius: var(--ds-radius-sm); background: var(--ds-primary); color: var(--ds-on-primary); font-size: var(--ds-text-xs); pointer-events: none; box-shadow: var(--ds-shadow-pop); }
.app-chart .usage-tip-val { font-weight: 600; font-size: var(--ds-text-sm); }
.app-chart .usage-tip-per { color: var(--ds-on-primary-2); margin-bottom: var(--ds-space-1); }
.app-chart .usage-tip-row { display: flex; justify-content: space-between; gap: var(--ds-space-4); color: var(--ds-on-primary-2); }
.app-chart .usage-tip-row span:last-child { color: var(--ds-on-primary); }
.app-dim { opacity: 0.55; transition: opacity var(--ds-dur-2); }

/* 10. LIVE-VIEW DIALOG ------------------------------------------------------ */
/* "Log in once" holds a live browser: wider and taller than ds-dialog--wide. */
.app-dialog-live { width: min(72rem, calc(100vw - 2rem)); max-height: calc(100dvh - 2rem); }
.app-dialog-live[data-compact] { width: min(34rem, calc(100vw - 2rem)); }
.app-dialog-live .ds-dialog__body { display: flex; flex-direction: column; gap: var(--ds-space-3); }
.app-dialog-live .app-viewport { aspect-ratio: auto; height: min(60dvh, 44rem); border-radius: var(--ds-radius-sm); box-shadow: 0 0 0 1px var(--ds-line-2); overflow: hidden; }
.ds-dialog__foot.app-foot-split { justify-content: space-between; align-items: center; flex-wrap: wrap; }
.ds-drawer.app-drawer-wide { width: min(44rem, 100vw); }

/* 11. SMALL FIXES ----------------------------------------------------------- */
/* --gap is inherited, so a stack inside a split with a wide gap would take that gap too. A layout
   helper that does not set its own --gap gets the system default back. */
.ds-stack:not([style*="--gap"]), .ds-cluster:not([style*="--gap"]), .ds-grid:not([style*="--gap"]), .ds-split:not([style*="--gap"]) { --gap: initial; }
/* Copy buttons outside a code block show the same copied state as ds.css gives [data-ds-copy]. */
[data-copy][data-copied], [data-code-copy][data-copied], [data-result-act][data-copied] { color: var(--ds-green-ink); }
/* Closed step details must not widen the page with their code blocks. */
.app-step:not([open]) > .app-step__detail, .app-fold:not([open]) > .app-fold__body { display: none; }
/* A tooltip (data-tip) near the right edge is wider than its button; it must not make the page scroll sideways. */
body.ds { overflow-x: clip; }
/* Touch: the brand mark, text buttons and small summaries get a 44px target. */
.ds-topbar > .ds-brand { min-width: var(--ds-h-md); min-height: var(--ds-h-md); justify-content: center; }
@media (pointer: coarse), (max-width: 640px) {
  .app-linkbtn, .ds-cluster > a.ds-link, .ds-row__trail > a.ds-link, .ds-dialog__foot a.ds-link, .ds-sechead__action { display: inline-flex; align-items: center; min-height: 2.75rem; }
  .app-step__think > summary, .app-pop details > summary { display: flex; align-items: center; min-height: 2.75rem; }
  .ds-toast__close { width: 2.75rem; height: 2.75rem; }
}
/* A field with a button inside it must not run its text under the button. */
.ds-inputgroup:has(> .ds-inputgroup__end) > .ds-input { padding-inline-end: 4.25rem; }
/* The age-gate checkbox can be invalid; ds-check has no invalid state. */
.ds-check input[aria-invalid="true"] { border-color: var(--ds-red-ink); box-shadow: 0 0 0 1px var(--ds-red-ink); }
/* A slim banner (Reconnecting). */
.ds-callout.app-slim { padding-block: var(--ds-space-2); align-items: center; font-size: var(--ds-text-sm); }
.ds-callout.app-slim > .ds-spinner { border-color: var(--ds-amber-ink); border-inline-end-color: transparent; }
/* A link-looking button. */
.app-linkbtn { padding: 0; border: 0; background: none; font: inherit; font-size: var(--ds-text-sm); }
/* The aside on Home starts level with the first section under the title. */
@container (min-width: 56rem) { .app-aside { padding-top: var(--ds-space-8); } }
/* A key cap on a solid button keeps the cap readable. */
.ds-btn > .ds-kbd { margin-inline-start: var(--ds-space-1); }
.ds-btn--primary > .ds-kbd { background: color-mix(in oklab, var(--ds-on-primary) 16%, transparent); color: var(--ds-on-primary); box-shadow: none; }
@media (pointer: coarse), (max-width: 640px) { .ds-btn > .ds-kbd { display: none; } }
/* A live tab in the strip keeps its close button reachable; rows in the More drawer show the same dot. */
.ds-tab--live .ds-tab__close { margin-inline-start: 0.125rem; }
/* Long values in a table cell wrap instead of pushing the table wide. */
.app-wrap { white-space: normal !important; overflow-wrap: anywhere; }
/* Secrets rows: three fields and a remove button. */
.app-secret { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) auto; gap: var(--ds-space-2); align-items: center; }
@container (max-width: 30rem) { .app-secret { grid-template-columns: minmax(0, 1fr) auto; } .app-secret > input { grid-column: 1; } .app-secret > button { grid-row: 1; grid-column: 2; } }
/* A group of checkboxes with a legend (webhook events): a field without the fieldset's own frame. */
.app-fieldset { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.app-fieldset > legend { padding: 0; margin-bottom: var(--ds-space-2); }
/* A sentence under a status in a table (how a run or a browser ended): it wraps inside a column of readable width. */
.app-outcome { white-space: normal; overflow-wrap: anywhere; min-inline-size: 11rem; max-inline-size: 22rem; }
@media (max-width: 40rem) { .app-outcome { min-inline-size: 0; max-inline-size: none; } }
