/* Jaybird Digital — customer portal (login, set-password, dashboard, request).
   Shares the marketing token block verbatim: minimal, matte, metallic.
   Portal controls are crisp (10px radius) rather than pill-shaped — the app
   surface reads as precise, the marketing surface as expressive.
   Every class name here is referenced by the portal JS/HTML; none renamed. */

:root {
  color-scheme: light;

  /* Cool blue-tinted neutrals, matched to the Jaybird brand navy */
  --bg: #e9edf1;
  --bg-top: #f3f5f8;
  --surface: #ffffff;
  --surface-2: #f7f9fb;
  --surface-3: #eff2f6;

  --ink: #17202b;
  --ink-2: #39434f;
  --muted: #6d7683;

  --line: rgba(20, 32, 50, 0.10);
  --line-2: rgba(20, 32, 50, 0.16);
  --sheen: rgba(255, 255, 255, 0.85);

  /* Jaybird brand navy — the single point of colour */
  --metal: #144570;
  --metal-hi: #1f5885;
  --metal-lo: #0d3352;
  --metal-ink: #f2f7fb;

  --radius: 14px;
  --radius-sm: 10px;
  --shadow-sm: 0 1px 2px rgba(18, 28, 42, 0.05);
  --shadow: 0 12px 34px rgba(18, 28, 42, 0.07);

  --ok: #4f7a5e;
  --ok-bg: #e8f0ea;
  --warn: #a8763a;
  --err: #a5453d;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body.portal-body {
  margin: 0;
  color: var(--ink);
  font-family: var(--font);
  background:
    radial-gradient(120% 55% at 50% -10%, rgba(255, 255, 255, 0.9), transparent 60%),
    linear-gradient(180deg, var(--bg-top) 0%, var(--bg) 100%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p { margin-top: 0; }

/* ---- Shell ------------------------------------------------------------- */

.portal-shell {
  width: min(1080px, calc(100% - 40px));
  margin: 0 auto;
  padding: 48px 0 72px;
}

/* The conversation pages are a workspace filling the window, not an article on
   a page, so the 120px of vertical padding that suits the dashboard is 120px
   taken off the thread here. */
.portal-shell.request-shell {
  padding: 16px 0 20px;
}

.portal-shell.narrow { width: min(440px, calc(100% - 28px)); padding-top: 88px; }
.portal-shell.request-shell { width: min(1200px, calc(100% - 32px)); }
/* A single column of conversation does not want to be 1200px wide. */
.portal-shell.request-shell:not(.build-shell) {
  width: min(860px, calc(100% - 32px));
  height: 100vh;
  height: 100dvh;
  padding: 24px 0;
}

.portal-hero { display: grid; gap: 14px; margin-bottom: 28px; }

.portal-eyebrow {
  margin: 0;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.portal-hero h1 {
  max-width: 18ch;
  margin: 0;
  font-size: clamp(2rem, 4.5vw, 3.4rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
}

.portal-copy, .portal-small { color: var(--muted); line-height: 1.65; }
.portal-small { font-size: 0.85rem; }

/* ---- Buttons ----------------------------------------------------------- */

.portal-actions { display: flex; flex-wrap: wrap; gap: 10px; }

.portal-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  color: var(--ink);
  background: linear-gradient(180deg, #ffffff 0%, var(--surface-2) 100%);
  box-shadow: inset 0 1px 0 var(--sheen), var(--shadow-sm);
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}

.portal-button:hover { transform: translateY(-1px); }

.portal-button.primary {
  color: var(--metal-ink);
  border-color: var(--metal-lo);
  background: linear-gradient(180deg, var(--metal-hi) 0%, var(--metal) 55%, var(--metal-lo) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), var(--shadow-sm);
}

.portal-button.primary:hover {
  background: linear-gradient(180deg, #56606b 0%, #3f4853 55%, var(--metal-lo) 100%);
}

.portal-button:disabled { cursor: not-allowed; opacity: 0.55; transform: none; }

.portal-link-button {
  width: fit-content;
  margin-top: 4px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  font: inherit;
  font-size: 0.88rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-2);
}

.portal-link-button:hover { color: var(--ink); }
.portal-link-button.danger { color: var(--err); }

/* ---- Cards & fields ---------------------------------------------------- */

.portal-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.portal-card {
  padding: 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(180deg, #ffffff 0%, var(--surface-2) 100%);
  box-shadow: inset 0 1px 0 var(--sheen), var(--shadow);
}

.portal-card h1 {
  margin: 6px 0 10px;
  font-size: 1.55rem;
  letter-spacing: -0.02em;
}

.portal-card h2 {
  margin-top: 0;
  margin-bottom: 14px;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
}

/* Wordmark above the auth cards. The logo image replaced the text wordmark, so
   the gradient-text properties below are inert for current pages but kept in
   case a text brandmark returns. */
.auth-brand {
  display: block;
  margin: 0 0 18px;
  text-align: center;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: linear-gradient(180deg, #1f5885, #0d3352);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The brand logo image replaces the text wordmark. Transparent PNG served
   from the marketing bucket; dimensions in the markup prevent layout shift,
   so these rules only set the display height. */
.auth-brand img {
  display: inline-block;
  height: 32px;
  width: auto;
}
.dash-brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.dash-brand img {
  display: block;
  height: 40px;
  width: auto;
}

.portal-field {
  display: grid;
  gap: 7px;
  margin: 14px 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-2);
}

.portal-field input,
.portal-field select,
.portal-field textarea {
  width: 100%;
  padding: 12px 13px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: #fff;
  box-shadow: inset 0 1px 2px rgba(18, 28, 42, 0.04);
  color: var(--ink);
  font: inherit;
  font-weight: 400;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.portal-field input:focus,
.portal-field select:focus,
.portal-field textarea:focus {
  outline: none;
  border-color: var(--metal);
  box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14);
}

.portal-field textarea { min-height: 150px; resize: vertical; }

.instagram-admin { margin-bottom: 20px; padding: 20px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.instagram-settings { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.instagram-admin .portal-button, .instagram-admin .portal-link-button { margin-right: 8px; margin-bottom: 8px; }

.portal-agreement {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 16px 0;
  color: var(--ink-2);
  font-size: 0.84rem;
  line-height: 1.5;
}

.portal-agreement input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  accent-color: var(--metal);
}

.portal-agreement a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

.terms-gate { max-width: 640px; margin: 0 auto 24px; }

/* ---- Lists (sites, requests) ------------------------------------------- */

.portal-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 14px; }

.portal-list li {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  line-height: 1.55;
}

.portal-list li strong { font-weight: 650; letter-spacing: -0.005em; }
.portal-list a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-2); }
.portal-list a:hover { color: var(--ink); }
.portal-list .portal-small { margin-top: 6px; }

/* ---- Status ------------------------------------------------------------ */

.portal-status { min-height: 1.2rem; font-size: 0.88rem; font-weight: 600; }

.portal-status.success,
.portal-status.error {
  margin-top: 16px;
  padding: 11px 13px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.portal-status.success { color: var(--ok); border-color: rgba(79, 122, 94, 0.4); }
.portal-status.error { color: var(--err); border-color: rgba(165, 69, 61, 0.4); }

/* ---- Dashboard --------------------------------------------------------- */

.dash-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 26px;
}

.dash-brand {
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: linear-gradient(180deg, #1f5885, #0d3352);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.dash-top-actions { display: flex; gap: 10px; }

/* ---- User menu (profile under the icon, not a full card) --------------- */

.user-menu { position: relative; }

.user-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.user-menu-toggle:hover { color: var(--ink); border-color: var(--metal-lo); }
.user-menu-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.16);
}

.user-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 10px);
  width: 300px;
  max-width: calc(100vw - 32px);
  max-height: min(70vh, 560px);
  overflow-y: auto;
  padding: 18px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  z-index: 30;
}

.user-menu-id { margin-bottom: 12px; }
.user-menu-id p { margin: 0; }
.user-menu-id strong {
  display: block;
  font-size: 1.15rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}
.user-menu-id .portal-small { margin-top: 2px; }

.user-menu-details {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.user-menu-details p { margin: 0; font-size: 0.86rem; color: var(--ink-2); overflow-wrap: anywhere; }
.user-menu-details p + p { margin-top: 3px; }

.user-menu-panel .details-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.user-menu-panel .portal-button { width: 100%; margin-top: 4px; }

.dash-identity {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 18px;
}

#profile p { margin: 0; }
#profile strong {
  font-size: 1.6rem;
  font-weight: 650;
  letter-spacing: -0.02em;
}
#profile .portal-small { margin-top: 4px; }

.dash-stats { display: flex; gap: 14px; flex-wrap: wrap; }

.stat {
  min-width: 132px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  box-shadow: inset 0 1px 0 var(--sheen);
}

.stat-label {
  margin: 0 0 6px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.stat p { margin: 0; }
.stat strong { font-size: 1.05rem; font-weight: 650; }

.dash-section { margin-top: 18px; }

/* Dashboard site list — one clean card per site, links to its own page. */
.site-cards { display: grid; gap: 10px; }

.site-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 15px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: linear-gradient(180deg, #ffffff, var(--surface-2));
  box-shadow: inset 0 1px 0 var(--sheen), var(--shadow-sm);
  color: var(--ink);
  text-decoration: none;
  transition: transform 0.12s ease, border-color 0.12s ease;
}

.site-card:hover { transform: translateY(-1px); border-color: var(--line-2); }
.site-card-main { display: flex; align-items: center; gap: 12px; min-width: 0; }
.site-card-name { font-weight: 650; letter-spacing: -0.01em; }

.site-card-role {
  padding: 2px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.site-card-chevron { color: var(--muted); font-size: 1.5rem; line-height: 1; }

/* Per-site page */
.site-hero {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

.site-hero h1 { margin: 6px 0 0; font-size: clamp(1.6rem, 3.5vw, 2.4rem); letter-spacing: -0.025em; }
.site-links { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 12px; }
.site-links a { color: var(--ink-2); font-size: 0.9rem; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-2); }
.site-links a:hover { color: var(--ink); }

.site-danger h2 { color: var(--err); }
.danger-button { border-color: rgba(165, 69, 61, 0.4); color: var(--err); }
.danger-button:hover { background: #fff0ef; }

/* ---- Request console --------------------------------------------------- */

/* A workspace, not a document. The height is DEFINITE - height, not
   min-height - because that is the whole fix: `1fr` in a grid whose container
   has no definite height resolves to max-content, so the message row grew with
   the transcript and overflow-y had nothing to overflow. The page crept
   downwards for ever and the composer walked off the bottom of the screen.
   min-height: 78vh was a floor where a ceiling was needed.

   clamp so it adapts without going silly: never shorter than 420px, never
   taller than 1100px, and otherwise the viewport less the page header and the
   shell's own padding.
   
   THE CEILING AND THE ALLOWANCE ARE BOTH SIZED FROM THE PROGRESS CARD. While a
   build runs, the thread contains a card with the stepper, the current activity
   line, the activity list and the preview link - measured at 446px with the
   list open. At the first numbers here the thread was 303px on a 1440x900
   screen and 205px on 1280x800, so the thing the customer most wants to look at
   was the thing that would not fit. */
.request-console {
  display: grid;
  grid-template-columns: 292px minmax(0, 1fr);
  gap: 0;
  padding: 0;
  overflow: hidden;
  height: clamp(420px, calc(100vh - 120px), 1100px);
}

/* One column, because there is one conversation.
   The sidebar existed to list past changes and let you pick one. Once the
   thread became continuous there was nothing left to put in it but the site
   switcher, and a near-empty 292px column reads as a filing cabinet somebody
   forgot to remove. Scoped away from .build-shell, which shares this class and
   still has a real list of websites in its sidebar. */
.request-shell:not(.build-shell) .request-console {
  grid-template-columns: minmax(0, 1fr);
  height: 100%;
  min-height: 0;
}

.request-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.request-header .site-switcher { flex: 0 0 auto; }
.request-header .request-back { margin-top: 2px; }

.request-sidebar {
  display: grid;
  gap: 10px;
  align-content: start;
  padding: 22px 20px;
  border-right: 1px solid var(--line);
  background: linear-gradient(180deg, var(--surface-2), var(--surface-3));
  /* Bounded like the chat is, for the same reason: the console no longer grows,
     so a customer with twenty websites needs this column to scroll rather than
     to overflow a container that clips. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.request-sidebar h2 { margin: 0; font-size: 1.02rem; }

/* Site switcher — the clear "which website am I working in" control. */
.site-switcher {
  padding: 13px 14px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: inset 0 1px 0 var(--sheen), var(--shadow-sm);
}

.site-switcher-label {
  display: block;
  margin: 0 0 7px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.site-switcher select {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  padding: 11px 34px 11px 13px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background-color: #fff;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5 6 6.5 11 1.5' stroke='%236d727a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 13px center;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.site-switcher select:focus {
  outline: none;
  border-color: var(--metal);
  box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14);
}

/* When locked to the current conversation's site, still read clearly. */
.site-switcher select:disabled {
  opacity: 1;
  cursor: default;
  color: var(--ink);
  background-color: var(--surface-2);
}

.conversation-list { display: grid; gap: 8px; }

.conversation-item {
  display: grid;
  gap: 4px;
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.conversation-item:hover { border-color: var(--line-2); }
.conversation-item strong { font-weight: 600; letter-spacing: -0.005em; }
.conversation-item span { display: flex; align-items: center; font-size: 0.78rem; color: var(--muted); }

.conversation-item.active {
  border-color: var(--metal);
  background: #fff;
  box-shadow: 0 0 0 1px var(--metal);
}

/* A site-scoped edit link already tells us which website owns this thread. */
.scoped-site-conversation .site-switcher { display: none; }

.request-main {
  display: grid;
  /* minmax(0, ...), not minmax(320px, ...): with the console's height now
     definite, a 320px floor on this row overflows a short window - and
     .request-console clips, so what gets cut off is the composer. The messages
     scroll instead, which is what they are for. */
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  gap: 10px;
  min-width: 0;
  min-height: 0;
  padding: 18px 20px;
}

.request-shell:not(.build-shell) .request-main { overflow: hidden; }

.request-header h1 { margin: 0 0 6px; font-size: clamp(1.35rem, 2.2vw, 1.9rem); letter-spacing: -0.02em; }

/* ---- Chat -------------------------------------------------------------- */

.portal-chat {
  margin: 0;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-3);
  max-height: 340px;
  overflow: auto;
}

.portal-chat.console {
  min-height: 0;
  max-height: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}

/* A column with a gap rather than margins on the children. A reply is a stack
   of pieces now - a sentence, a list, a verification line, sometimes a preview
   link and a button - and spacing them with margins meant every new kind of
   piece had to add its own, while `> p { margin: 0 }` quietly out-specified the
   general rule and closed the gaps again. */
.portal-chat-message {
  margin: 0;
  padding: 12px 14px;
  border-radius: 12px;
  font-size: 0.94rem;
  line-height: 1.5;
  max-width: 82%;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.portal-chat-message > p { margin: 0; white-space: pre-wrap; }
.portal-chat-message + .portal-chat-message { margin-top: 12px; }

/* The planner replies in a shape - a sentence, the changes as a list, a
   verification line - and the list is the part being scanned. Unstyled it
   inherited the browser's default indent and sat hard against the text above
   it, which is most of why a structured reply still read as a wall. */
.portal-chat-message ul.chat-list,
.portal-chat-message ol.chat-list {
  margin: 0;
  padding-left: 1.15em;
  display: grid;
  gap: 6px;
}
.portal-chat-message .chat-list li { margin: 0; }
.portal-chat-message .chat-list li::marker { color: var(--muted); }
.portal-chat-message strong { font-weight: 640; }

/* Sending should look like the message moving into the thread rather than
   appearing there between frames. */
@keyframes chat-message-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.portal-chat-message { animation: chat-message-in 180ms ease-out both; }

/* "Looking at deniz-12.jpg." - the assistant going and checking something,
   which is neither a message nor a status line. */
.chat-note {
  margin: 4px 0 4px 2px;
  font-size: 0.82rem;
  color: var(--muted);
  font-style: italic;
  animation: chat-message-in 180ms ease-out both;
}
.chat-note + .chat-note { margin-top: 0; }

/* The preview and the one control that publishes it. */
.chat-preview-link {
  align-self: flex-start;
  color: var(--ink-2);
  font-size: 0.88rem;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-2);
}
.chat-preview-link:hover { color: var(--ink); }
.chat-approve { align-self: flex-start; margin-top: 2px; }

.portal-chat-message.user {
  margin-left: auto;
  color: var(--metal-ink);
  border: 1px solid var(--metal-lo);
  background: linear-gradient(180deg, var(--metal-hi), var(--metal));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.portal-chat-message.assistant {
  margin-right: auto;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #ffffff, var(--surface-2));
  box-shadow: inset 0 1px 0 var(--sheen), var(--shadow-sm);
}

/* "Assistant is working" indicator — three pulsing dots in an assistant bubble. */
/* The bubble is a column; these three dots are the one thing in it that runs
   across. Without the reset they stack vertically. */
.portal-chat-message.chat-typing {
  display: inline-flex;
  flex-direction: row;
  gap: 5px;
  align-items: center;
  width: auto;
}
.chat-typing span {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted);
  animation: chat-typing-bounce 1.2s infinite ease-in-out;
}
.chat-typing span:nth-child(2) { animation-delay: 0.15s; }
.chat-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-typing-bounce {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .chat-typing span { animation: none; opacity: 0.6; }
  .portal-chat-message { animation: none; }
}

.portal-chat-reasoning {
  margin: 10px 0 0;
  padding: 9px 12px;
  border: 1px dashed var(--line-2);
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  color: var(--muted);
  font-size: 0.83rem;
}

.portal-chat-reasoning summary { cursor: pointer; font-weight: 600; color: var(--ink-2); }
.portal-chat-reasoning p { margin: 8px 0 0; white-space: pre-wrap; }

.request-compose { display: grid; gap: 10px; }

.request-compose textarea {
  width: 100%;
  min-height: 96px;
  padding: 13px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: #fff;
  box-shadow: inset 0 1px 2px rgba(18, 28, 42, 0.04);
  color: inherit;
  font: inherit;
  resize: vertical;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.request-compose textarea:focus {
  outline: none;
  border-color: var(--metal);
  box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14);
}

/* ---- Receipts ---------------------------------------------------------- */

.chat-receipts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

.chat-receipts-label {
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.chat-receipts-label::before { content: "\21A9"; margin-right: 4px; }

.chat-receipt {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  padding: 3px 9px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 0.77rem;
}

.chat-receipt-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 30ch;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
}

.chat-receipt.linked .chat-receipt-text { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 2px; }
.chat-receipt.linked:hover { border-color: var(--metal); }
.chat-receipt.forgotten { opacity: 0.5; text-decoration: line-through; }

.chat-receipt-forget { padding: 0 2px; border: 0; background: transparent; color: var(--muted); cursor: pointer; font: inherit; line-height: 1; }
.chat-receipt-forget:hover { color: var(--err); }
.chat-receipt-forget:disabled { cursor: wait; opacity: 0.5; }

/* ---- Threads ----------------------------------------------------------- */

.thread-group {
  margin: 4px 0 2px;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.thread-status-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--muted);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}

.thread-status-dot.designing { background: #6b7f96; }
.thread-status-dot.submitted { background: #5f8069; }
.thread-status-dot.revising { background: #b07d3c; }
.thread-status-dot.delivered { background: #9aa0a8; }

.thread-delivered { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }
.thread-delivered summary { cursor: pointer; color: var(--muted); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.04em; }

.thread-search {
  width: 100%;
  margin: 10px 0;
  padding: 9px 11px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: #fff;
  color: inherit;
  font: inherit;
  font-size: 0.85rem;
}

.thread-search:focus { outline: none; border-color: var(--metal); box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14); }

/* ---- Revision ---------------------------------------------------------- */

.request-actions { margin-top: 12px; }
.revise-panel { display: grid; gap: 8px; margin-top: 12px; }

.revise-note {
  width: 100%;
  min-height: 74px;
  padding: 11px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: #fff;
  color: inherit;
  font: inherit;
  resize: vertical;
}

.revise-note:focus { outline: none; border-color: var(--metal); box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14); }

/* ---- Responsive -------------------------------------------------------- */

@media (max-width: 980px) {
  /* Stacked, and still a bounded workspace. Letting the height go auto here and
     capping the chat on its own kept the transcript from growing but left the
     page 1182px tall against an 800px viewport, with the composer below the
     fold - because the website list now sits above the chat and adds its own
     height. So the console keeps its definite height from the base rule and
     divides it between the two: the list gets what it needs up to a third of
     the viewport and scrolls past that, the chat gets the rest. */
  .request-console { grid-template-columns: 1fr; }
  /* Rows only where there is a second thing in the column. The edit chat has no
     website list, so giving its console two rows put .request-main in the
     auto-sized one and it grew with the transcript again - the same bug, one
     breakpoint over. */
  .build-shell .request-console { grid-template-rows: auto minmax(0, 1fr); }
  .request-sidebar {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    /* A short strip, not a third of the screen. At 30vh the list took 240px of
       a 590px console and left 59px of visible chat, which is a scrollbar with
       a hint of text in it. 14vh leaves room for the progress card, which is
       305px with its activity list closed and is the thing a customer watching
       a build is actually looking at. */
    max-height: 14vh;
    padding: 12px 16px;
  }
  /* The padding and the height come from the base rules now - they were
     duplicated here while the desktop page still had 120px of vertical
     padding to reclaim. */
  /* The explanatory line is for a first visit on a roomy screen. Here it costs
     60px of a conversation that had 159px, so it goes - the same call the phone
     layout already makes. */
  .request-header .portal-copy { display: none; }
}

@media (max-width: 760px) {
  .portal-shell { width: min(100% - 24px, 1080px); padding-top: 28px; }
  .portal-grid { grid-template-columns: 1fr; }
  .dash-identity { flex-direction: column; align-items: flex-start; }
  .portal-chat-message { max-width: 92%; }
}

/* Edit chat: the conversation is a contained workspace on every screen. The
   header and composer stay put while only the messages scroll, so a long
   history does not turn the entire page into an ever-growing transcript. */
@media (max-width: 760px) {
  .portal-shell.request-shell:not(.build-shell) {
    width: 100%;
    max-width: none;
    height: 100vh;
    height: 100dvh;
    padding: 0;
  }

  .request-shell:not(.build-shell) .request-console {
    border: 0;
    border-radius: 0;
  }

  .request-shell:not(.build-shell) .request-main {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 0;
    gap: 0;
  }

  .request-shell:not(.build-shell) .request-header { padding: 12px 14px 8px; }
  .request-shell:not(.build-shell) .request-header .portal-copy { display: none; }
  .request-shell:not(.build-shell) .request-heading { align-items: center; }
  .request-shell:not(.build-shell) .site-switcher { padding: 8px 9px 7px; }
  .request-shell:not(.build-shell) .site-switcher-label { margin-bottom: 3px; }
  .request-shell:not(.build-shell) .site-switcher select { padding-block: 7px; }
  .request-shell:not(.build-shell) .portal-chat.console {
    flex: 1 1 auto;
    min-height: 0;
    padding: 10px 12px;
  }
  .request-shell:not(.build-shell) .portal-status { margin: 0; padding: 0 12px; }
}

/* ---- Mobile chat: clean, texting-app feel ------------------------------ */
/* Shared on phones for both the build and edit chats: iMessage-style bubbles
   and a compact pill composer, with the "card in a card" chrome removed. */
@media (max-width: 760px) {
  .portal-chat-message {
    max-width: 82%;
    padding: 9px 13px;
    border-radius: 20px;
    font-size: 0.95rem;
    line-height: 1.4;
  }
  .portal-chat-message + .portal-chat-message { margin-top: 6px; }
  .portal-chat-message.user { border-bottom-right-radius: 6px; }
  .portal-chat-message.assistant { border-bottom-left-radius: 6px; }

  /* max-height: none, because the 980px rule above matches here too and its
     cap would fight the flex chain the mobile layout already gets right: the
     shell is 100dvh, the console and .request-main both flex: 1 1 auto with
     min-height: 0, and the messages are the only scroller. */
  .portal-chat.console { border: 0; background: transparent; max-height: none; }

  .request-compose {
    gap: 8px;
    padding: 8px 12px calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--line);
    background: var(--surface-2);
  }
  .request-compose textarea {
    min-height: 44px;
    max-height: 38vh;
    padding: 11px 15px;
    border-radius: 20px;
    resize: none;
  }
  .request-compose .portal-actions { gap: 8px; }
  .request-compose .portal-button { flex: 1 1 auto; height: 42px; border-radius: 21px; }
}

/* Build chat only: a true full-screen texting view. The shell fills the
   viewport, the message thread is the ONLY scroller, the composer stays pinned
   at the bottom, and the website list is hidden (switch/start builds from the
   dashboard). This fixes the cramped layout where the plan summary and the
   Build button were clipped or pushed off-screen. */
@media (max-width: 760px) {
  .portal-shell.build-shell {
    width: 100%;
    max-width: none;
    padding: 0;
    /* height, not min-height. Everything below this is a correct flex chain -
       the console and .request-main are both flex: 1 1 auto with min-height: 0,
       and the messages are the only scroller - but it had nothing bounded to
       divide up. Measured with a 25-message transcript at 580px wide: this
       element's min-height was 968px and its actual height 3002px, so the
       console faithfully distributed 3002px and the composer sat 2000px below
       the fold. The edit chat above already does it this way. */
    height: 100vh;
    height: 100dvh;
    display: flex;
    flex-direction: column;
  }
  .build-shell .dash-top { padding: 10px 14px; margin: 0; }

  .build-shell .request-console {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    overflow: hidden;
  }

  /* The chat owns the screen — no side list competing for space. */
  .build-shell .request-sidebar { display: none; }

  .build-shell .request-main {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    padding: 0;
    gap: 0;
  }
  .build-shell .request-header { padding: 10px 16px 6px; }
  .build-shell .request-header .portal-copy { display: none; }
  .build-shell .request-header h1 { margin: 0; font-size: 1.15rem; }

  .build-shell .portal-chat.console {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    overflow-y: auto;
    padding: 10px 12px;
  }

  .build-shell #build-status { margin: 0; padding: 2px 14px 8px; }
}

/* ---- Confirmation dialog -------------------------------------------------
   Replaces window.confirm, which a browser is allowed to stop showing - and
   when it does, it returns false silently, so every destructive button in the
   portal quietly stopped working. See confirmAction in conversation.js. */
.portal-confirm {
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: 22px 24px 18px;
  max-width: 420px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 18px 48px rgba(20, 32, 50, 0.22);
}
.portal-confirm::backdrop { background: rgba(20, 32, 50, 0.42); }
.portal-confirm h2 { margin: 0 0 8px; font-size: 1.05rem; line-height: 1.35; }
.portal-confirm p { margin: 0 0 18px; color: var(--ink-2); line-height: 1.5; }
.portal-confirm-actions { display: flex; justify-content: flex-end; gap: 10px; }
/* The destructive choice reads as destructive, and is never the focused one. */
.portal-button-danger { color: var(--err); border-color: rgba(165, 69, 61, 0.4); }
.portal-button-danger:hover { background: #fff0ef; border-color: rgba(165, 69, 61, 0.6); }

/* ---- The admin console ---------------------------------------------------
   The everyday things an owner changes themselves. Laid out as a form rather
   than a dashboard: the whole point is that a phone number takes one field and
   one button, not a screen to navigate. */
.content-heading {
  margin: 22px 0 4px;
  font-size: 0.95rem;
  font-weight: 640;
  letter-spacing: 0.01em;
}
.content-heading:first-child { margin-top: 0; }

.content-fields { display: grid; gap: 14px; margin: 12px 0 14px; }

/* A page at a time, closed. A five-page site declares about 170 editable
   things; all of them at once is a wall, six under a heading you recognise is
   a console. */
.content-page {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 0 12px;
}
.content-page > summary {
  cursor: pointer;
  padding: 11px 2px;
  font-weight: 600;
  font-size: 0.92rem;
  list-style-position: inside;
}
.content-page[open] > summary { border-bottom: 1px solid var(--line); margin-bottom: 10px; }
.content-group { display: grid; gap: 14px; margin: 0 0 16px; }
.content-group-name {
  margin: 4px 0 0;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.62;
}
.content-suggest { justify-self: start; font-size: 0.82rem; }

/* The owner's real page, live, with the slot outlined by the site's own
   Worker. Tall enough to recognise a place, short enough to sit in a form. */
.content-preview { display: grid; gap: 6px; justify-items: start; }
.content-preview-frame {
  width: 100%;
  height: 300px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.content-preview-frame[hidden] { display: none; }
.content-field { display: grid; gap: 5px; }
/* `hidden` comes from the active Text/Images view. Keep this explicit because
   the grid declaration above otherwise wins in some embedded portal styles. */
.content-field[hidden],
.content-group[hidden],
.content-page[hidden] { display: none !important; }
.content-label { font-size: 0.9rem; font-weight: 600; }
.content-field input,
.content-field textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  font: inherit;
}
.content-field textarea { min-height: 76px; resize: vertical; }
.content-image-crop { display: grid; gap: 9px; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--surface) 78%, var(--page)); }
.content-image-crop-preview { width: min(100%, 310px); overflow: hidden; border-radius: var(--radius-sm); background: var(--page); border: 1px solid var(--line); }
.content-image-crop-preview img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 100ms linear, object-position 100ms linear; }
.content-image-crop-controls { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.content-image-crop-control { display: grid; gap: 3px; }
.content-image-crop-control input[type="range"] { padding: 0; border: 0; box-shadow: none; accent-color: var(--metal); }
@media (max-width: 520px) { .content-image-crop-controls { grid-template-columns: 1fr; } }
.content-field input:focus,
.content-field textarea:focus {
  outline: none;
  border-color: var(--metal);
  box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14);
}

.content-slots { display: grid; gap: 10px; margin: 12px 0 14px; }
.content-slot {
  display: grid;
  gap: 5px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
/* The description the build wrote - "Atmospheric photograph of the backbar" -
   is what tells an owner what to upload, so it leads. */
.content-slot-what { font-size: 0.92rem; font-weight: 600; }
.content-slot select {
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: inherit;
  font: inherit;
  max-width: 100%;
}
#content-body textarea {
  width: 100%;
  min-height: 72px;
  margin: 10px 0;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  font: inherit;
  resize: vertical;
}

/* ---- The admin console: split editor ------------------------------------
   Fields on the left, the owner's live page on the right. The preview is the
   real page with the slot outlined by the site's own Worker (?ww-slot=), so it
   can never go stale. */
.content-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
  gap: 20px;
  align-items: start;
}
.content-main { display: grid; gap: 14px; min-width: 0; }
.content-intro { margin: 0; color: var(--ink-2); }

.content-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}
.content-search {
  flex: 1 1 240px;
  min-width: 0;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  font: inherit;
}
.content-search:focus { outline: none; border-color: var(--metal); box-shadow: 0 0 0 3px rgba(20, 69, 112, 0.14); }
.content-preview-toggle { display: none; }
.content-mode-tabs { display: flex; gap: 8px; border-bottom: 1px solid var(--line); }
.content-mode-tab {
  appearance: none;
  border: 0;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  padding: 8px 3px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}
.content-mode-tab:hover { color: var(--ink); }
.content-mode-tab.is-active { color: var(--ink); border-bottom-color: var(--metal); }
.content-mode-tab:focus-visible { outline: 2px solid var(--metal); outline-offset: 3px; border-radius: 2px; }

.content-preview-panel {
  position: sticky;
  top: 16px;
  display: grid;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.content-preview-head { display: flex; flex-direction: column; gap: 2px; }
.content-preview-label { font-size: 0.86rem; font-weight: 600; }
.content-preview-panel .content-preview-frame {
  height: 62vh;
  min-height: 320px;
  max-height: 720px;
}
.content-preview-hint { margin: 0; color: var(--ink-2); line-height: 1.45; }

.content-caption { color: var(--muted); }
.content-field select {
  width: 100%;
  max-width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  font: inherit;
}
.content-field-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 2px;
}
.content-crop { width: 100%; }
.content-crop > summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--ink-2);
  list-style-position: inside;
}
.content-crop[open] > summary { margin-bottom: 6px; }
.content-crop .content-image-crop { margin-top: 4px; }
.content-no-results { margin: 0; color: var(--muted); }
.content-foot { display: flex; flex-wrap: wrap; gap: 10px; }
.content-ask { display: grid; gap: 6px; }

@media (max-width: 980px) {
  .content-split {
    display: flex;
    flex-direction: column;
  }
  .content-preview-panel {
    order: -1;
    position: sticky;
    top: 10px;
    z-index: 100;
    display: grid !important;
    padding: 8px 10px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  }
  .content-preview-head {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
  .content-preview-panel .content-preview-frame {
    height: 42vh;
    min-height: 240px;
    max-height: 380px;
  }
  .content-preview-hint { display: none; }
  .content-preview-toggle { display: none !important; }
}

/* ---- Developer AI & Repository Tools ---------------------------------- */
.developer-ai-tools-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 14px 0 16px;
}
.developer-tool-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px;
  border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 580;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.1s ease, border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.developer-tool-btn:hover {
  transform: translateY(-1px);
  border-color: var(--ink-2);
  background: var(--surface-2, #f7f9fb);
  box-shadow: 0 4px 12px rgba(20, 32, 50, 0.06);
}
.developer-tool-btn svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.developer-tool-btn.primary {
  background: var(--metal, #1e293b);
  color: #fff;
  border-color: var(--metal, #1e293b);
}
.developer-tool-btn.primary:hover {
  background: var(--ink, #0f172a);
}
.developer-access-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  background: rgba(46, 125, 50, 0.1);
  color: #2e7d32;
  border: 1px solid rgba(46, 125, 50, 0.25);
  margin-bottom: 12px;
}
.developer-pending-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  background: rgba(230, 81, 0, 0.1);
  color: #e65100;
  border: 1px solid rgba(230, 81, 0, 0.25);
  margin-bottom: 12px;
}
.developer-tool-modal {
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: 24px 26px;
  max-width: 560px;
  width: calc(100vw - 32px);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 20px 50px rgba(20, 32, 50, 0.25);
}
.developer-tool-modal::backdrop {
  background: rgba(20, 32, 50, 0.46);
  backdrop-filter: blur(2px);
}
.developer-tool-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.developer-tool-modal-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 1.15rem;
  font-weight: 650;
}
.developer-tool-modal-close {
  background: transparent;
  border: 0;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--ink-2);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
.developer-tool-modal-close:hover {
  color: var(--ink);
  background: var(--surface-2);
}
.developer-step {
  margin-bottom: 16px;
}
.developer-step-num {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 4px;
}
.developer-step-desc {
  font-size: 0.9rem;
  color: var(--ink);
  margin-bottom: 6px;
  line-height: 1.45;
}
.developer-code-box {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--page, #f8f9fa);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.84rem;
  color: var(--ink);
}
.developer-code-box code {
  flex: 1;
  white-space: pre;
  overflow-x: auto;
}
.developer-copy-btn {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.developer-copy-btn:hover {
  background: var(--surface-2);
  border-color: var(--ink-2);
}

/* ---- Site-scoped MCP -------------------------------------------------- */
.mcp-connection-status, .mcp-client-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
.mcp-client-tabs { border-bottom: 1px solid var(--line); gap: 2px; }
.mcp-client-tab { appearance: none; border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--ink-2); padding: 9px 12px; font: inherit; font-weight: 650; cursor: pointer; }
.mcp-client-tab.is-active { color: var(--ink); border-bottom-color: var(--metal, #1e293b); }
.mcp-config-box { align-items: flex-start; padding: 14px; }
.mcp-config-box code { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.5; }
.mcp-workflow { margin: 18px 0 0; padding-left: 1.4rem; color: var(--ink-2); }
.mcp-workflow li { margin: 8px 0; padding-left: 4px; }
.mcp-auth-shell { max-width: 720px; }
.mcp-auth-card { margin-top: 8vh; }
.mcp-consent-form { display: grid; gap: 20px; margin-top: 24px; }
.mcp-consent-form > label { display: grid; gap: 8px; font-weight: 700; }
.mcp-consent-form select { width: 100%; min-height: 46px; border: 1px solid var(--line-2); border-radius: 8px; background: var(--surface); color: var(--ink); padding: 8px 12px; font: inherit; }
.mcp-consent-form fieldset { border: 1px solid var(--line); border-radius: 10px; padding: 8px 16px; }
.mcp-consent-form legend { padding: 0 6px; font-weight: 700; }
.mcp-scope-row { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.mcp-scope-row:last-child { border-bottom: 0; }
.mcp-scope-row input { margin-top: 4px; }
.mcp-scope-row span { display: grid; gap: 3px; }
.mcp-scope-row small { color: var(--ink-2); line-height: 1.4; }
.mcp-consent-note { padding: 12px 14px; border-radius: 8px; background: var(--surface-2); color: var(--ink-2); font-size: .9rem; }
.mcp-manual-details { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 16px; }
.mcp-manual-details summary { cursor: pointer; font-weight: 650; font-size: 0.92rem; color: var(--ink); }
.mcp-manual-details summary:hover { color: var(--ink-2); }
.mcp-manual-body { margin-top: 12px; }
