/* Zoviz Assistant: the chat widget inside the frame (CHATBOT-DESIGN.md section 6).
   The Zoviz design system (zoviz-design-foundations / zoviz-components-icons,
   homepage snapshot 2026-09-30): Inter (Noto Naskh Arabic for Arabic), ink on
   white, teal for links and focus, the pale lime shared action, the dark green
   form action, the homepage's 1.6-stroke outline icons and its motion ease.
   No inline styles anywhere (the frame's CSP is style-src 'self'); JS toggles
   classes and the hidden attribute only. The fonts are the frame's own files
   (font-src 'self'), nothing else is loaded.
   Contrast: every text/background pair below is at least 4.5:1, and the text
   field's boundary at least 3:1 (WCAG 2.1 AA, 1.4.3 and 1.4.11). Buttons with
   a visible label keep the homepage's quiet borders: their label identifies
   them. */
@font-face {
  font-family: "Inter";
  src: url(/fonts/inter-latin.woff2?v=260c81a4) format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308,
    U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  src: url(/fonts/inter-latin-ext.woff2?v=01ba6c2a) format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Noto Naskh Arabic";
  src: url(/fonts/noto-naskh-arabic-arabic.woff2?v=b5523c99) format("woff2");
  font-weight: 400 700; font-style: normal; font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E,
    U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

:root {
  --zv-ink: #1c2929;          /* 15.0:1 on white */
  --zv-muted: #626e70;        /* 5.3:1 on white, 4.9:1 on --zv-quiet */
  --zv-paper: #ffffff;
  --zv-quiet: #f5f8f7;        /* the homepage's quiet menu surface: bot messages */
  --zv-line: #e4e9e9;         /* separators */
  --zv-edge: #d5dedc;         /* the panel and outline buttons */
  --zv-field: #869390;        /* the text field's boundary: 3.2:1 on white */
  --zv-teal: #00847d;         /* links, focus, selection: 4.6:1 on white */
  --zv-teal-ink: #00716b;     /* links on --zv-quiet: 5.5:1 */
  --zv-action-bg: #e0f2bd;    /* the shared primary action */
  --zv-action-ink: #183d33;   /* 10.0:1 on the lime */
  --zv-action-border: #cbdcae;
  --zv-action-hover: #edfad7;
  --zv-deep: #143e34;         /* the form action and the launcher: white on it 11.9:1 */
  --zv-deep-hover: #087568;   /* white on it 5.6:1 */
  --zv-lime-glyph: #e0f2bd;   /* the launcher glyph on --zv-deep: 10.0:1 */
  --zv-badge: #e9f2ee;        /* the AI label: --zv-action-ink on it 10.5:1 */
  --zv-warm: #f6f3ec;         /* notes: ink on it 13.6:1 */
  --zv-warm-edge: #e6dcc6;
  --zv-ease: cubic-bezier(.23, 1, .32, 1);
  --zv-shadow: 0 2px 10px rgba(23, 59, 51, .16);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; background: transparent; }
body {
  font: 15px/1.55 Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Noto Sans JP",
    "Noto Sans KR", "Noto Sans SC", sans-serif;
  color: var(--zv-ink);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
:root:lang(ar) body {
  font-family: "Noto Naskh Arabic", Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px; line-height: 1.7;
}
:root:lang(ar) .zv-hbtn, :root:lang(ar) .zv-sources, :root:lang(ar) .zv-feedback, :root:lang(ar) .zv-status { font-size: 14px; }
:root:lang(ar) .zv-ai-label, :root:lang(ar) .zv-hint { font-size: 13px; letter-spacing: 0; }
[hidden] { display: none !important; }
.zv-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus-visible { outline: 3px solid var(--zv-teal); outline-offset: 2px; }
.zv-icon { flex: none; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* the directional arrow follows the reading direction; nothing else mirrors */
:root[dir="rtl"] .zv-dir { transform: scaleX(-1); }

/* The launcher: the frame is 72 x 72 while the panel is closed. */
.zv-launcher {
  position: fixed; inset-block-end: 8px; inset-inline-end: 8px;
  width: 56px; height: 56px; border-radius: 50%; border: 1px solid transparent; cursor: pointer;
  background: var(--zv-deep); color: var(--zv-lime-glyph);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 6px rgba(23, 59, 51, .28);
}
.zv-launcher .zv-icon { width: 28px; height: 28px; }
/* (snippet v2) on a phone the snippet gives the closed frame 64 px: a 48 px button */
@media (max-width: 66px) {
  .zv-launcher { width: 48px; height: 48px; }
  .zv-launcher .zv-icon { width: 24px; height: 24px; }
}
/* two-tone ring: the white spread keeps the teal ring visible on a dark host section */
.zv-launcher:focus-visible { outline-offset: 2px; box-shadow: 0 0 0 2px #fff, 0 2px 6px rgba(23, 59, 51, .28); }

/* The panel: inset in the frame so its shadow shows (the snippet sizes the frame). */
.zv-panel {
  position: fixed; inset: 12px; display: flex; flex-direction: column;
  background: var(--zv-paper); border: 1px solid var(--zv-edge); border-radius: 16px;
  box-shadow: var(--zv-shadow); overflow: hidden;
}
.zv-full .zv-panel { inset: 0; border-radius: 0; border: 0; box-shadow: none; }

/* The name never truncates and the close button always stays in the first row's
   corner: in a long language New chat / End chat move to a second row, where
   their labels may wrap inside the buttons. */
.zv-head {
  position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  padding-block: 12px; padding-inline: 14px 48px;
  border-block-end: 1px solid var(--zv-line); background: var(--zv-paper);
}
.zv-avatar {
  flex: none; width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  background: var(--zv-deep); color: var(--zv-lime-glyph);
}
.zv-avatar .zv-icon { width: 20px; height: 20px; }
.zv-name { flex: 1 0 auto; min-width: 0; }
.zv-title { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.3; letter-spacing: -.01em; white-space: nowrap; }
.zv-ai-label {
  display: inline-block; margin: 2px 0 0; padding: 0 7px; border-radius: 6px;
  font-size: 11.5px; font-weight: 600; line-height: 1.6; letter-spacing: .01em;
  color: var(--zv-action-ink); background: var(--zv-badge);
}
.zv-actions {
  flex: 0 1 auto; min-width: 0; display: flex; align-items: center; justify-content: flex-end;
  gap: 0; margin-inline-start: auto;
}
.zv-hbtn {
  min-height: 36px; padding: 5px 7px; border-radius: 8px; cursor: pointer;
  border: 1px solid transparent; background: transparent; color: var(--zv-ink);
  font: inherit; font-size: 13px; font-weight: 500; line-height: 1.3; text-align: center;
}
.zv-hbtn:not(.zv-close) { flex: 0 1 auto; min-width: 0; }
.zv-close {
  position: absolute; inset-block-start: 12px; inset-inline-end: 6px;
  display: inline-flex; align-items: center; justify-content: center; min-width: 36px; min-height: 36px; padding: 0;
}
.zv-close .zv-icon { width: 20px; height: 20px; }
/* (owner 2026-10-16) Open in Zoviz Agent: an icon button before New chat,
   shown only when the hand-off is on for this visitor (frame.js) */
.zv-hbtn.zv-agent {
  flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: 36px; padding: 0;
}
.zv-agent .zv-icon { width: 20px; height: 20px; }

.zv-head, .zv-status, .zv-ts, .zv-form, .zv-hint { flex: none; }
.zv-log:focus-visible { outline-offset: -3px; }
.zv-log { flex: 1 1 auto; overflow-y: auto; padding: 16px 14px; display: flex; flex-direction: column; gap: 12px; }
.zv-msg { max-width: 88%; padding: 10px 14px; border-radius: 16px; overflow-wrap: anywhere; }
.zv-text { white-space: pre-line; margin: 0; }
.zv-bot { align-self: flex-start; background: var(--zv-quiet); border-end-start-radius: 6px; }
.zv-user { align-self: flex-end; background: var(--zv-deep); color: #fff; border-end-end-radius: 6px; }
.zv-note {
  align-self: stretch; max-width: none; border-radius: 12px;
  background: var(--zv-warm); color: var(--zv-ink); border: 1px solid var(--zv-warm-edge);
}
.zv-sources { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--zv-muted); }
.zv-link { color: var(--zv-teal); font-weight: 500; text-underline-offset: 3px; }
.zv-bot .zv-link, .zv-note .zv-link { color: var(--zv-teal-ink); }
.zv-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* the shared primary action (a page or tool to open, the contact form, copy) */
.zv-btn {
  display: inline-flex; align-items: center; gap: 12px;
  min-height: 44px; padding: 10px 16px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--zv-action-border); background: var(--zv-action-bg); color: var(--zv-action-ink);
  font: inherit; font-size: 14px; font-weight: 600; line-height: 1.35; text-decoration: none;
}
.zv-btn .zv-icon { width: 18px; height: 18px; }
/* a choice the visitor picks (and the yes/no of the feedback) */
.zv-choice {
  display: inline-flex; align-items: center;
  min-height: 40px; padding: 8px 14px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--zv-edge); background: var(--zv-paper); color: var(--zv-ink);
  font: inherit; font-size: 14px; font-weight: 500; line-height: 1.35;
}
.zv-choice:disabled { opacity: .5; cursor: default; }
.zv-copy {
  margin: 10px 0 0; padding: 10px 12px; max-height: 180px; overflow: auto; white-space: pre-wrap;
  font: inherit; font-size: 13px; line-height: 1.5;
  background: var(--zv-paper); color: var(--zv-ink); border: 1px solid var(--zv-edge); border-radius: 10px;
}
.zv-feedback {
  align-self: flex-start; display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  font-size: 13px; color: var(--zv-muted);
}
.zv-feedback .zv-choice { min-height: 36px; padding: 6px 12px; font-size: 13px; }

/* (2026-10-15) image tools: the offer, the job and the picture under a bot
   message (frame.js imageCard). The offer's own action is the lime one. */
.zv-card { display: grid; justify-items: start; gap: 6px; margin-top: 10px; }
.zv-card .zv-row { margin-top: 4px; }
.zv-fact, .zv-card-line { margin: 0; font-size: 14px; line-height: 1.5; }
.zv-key { color: var(--zv-muted); }
.zv-price .zv-value { font-weight: 600; }
.zv-choice.zv-primary {
  border-color: var(--zv-action-border); background: var(--zv-action-bg); color: var(--zv-action-ink); font-weight: 600;
}
.zv-result { max-width: 100%; }
/* transparency (a removed background) shows on a quiet checkerboard: two
   gradients, no image file (the stylesheet loads nothing but the fonts) */
.zv-image {
  display: block; max-width: 100%; height: auto; border-radius: 10px; border: 1px solid var(--zv-line);
  background-color: var(--zv-paper);
  background-image: linear-gradient(45deg, var(--zv-line) 25%, transparent 25%, transparent 75%, var(--zv-line) 75%),
    linear-gradient(45deg, var(--zv-line) 25%, transparent 25%, transparent 75%, var(--zv-line) 75%);
  background-size: 16px 16px; background-position: 0 0, 8px 8px;
}
/* the running job: an indeterminate bar drawn here (the browser's own moves
   whatever the visitor's motion setting); still stripes unless motion is welcome */
.zv-progress {
  display: block; width: 100%; min-width: 180px; height: 6px; margin: 2px 0 4px; border: 0; border-radius: 3px;
  -webkit-appearance: none; appearance: none; overflow: hidden; color: var(--zv-teal);
  background: repeating-linear-gradient(-45deg, var(--zv-badge) 0 6px, var(--zv-line) 6px 12px);
}
.zv-progress::-webkit-progress-bar { background: transparent; }
.zv-progress::-moz-progress-bar { background: transparent; }

/* (2026-10-15) logo options: the logo album's designs under a bot message
   (frame.js logoCard). In the widget one design per line, each preview in a
   light frame and never wider than the bubble; agent.css gives the wide page
   two columns. The bubble takes its full width at once, so it does not grow
   when the pictures arrive. */
.zv-msg:has(.zv-logos) { width: 100%; }
.zv-logos { justify-items: stretch; }
.zv-logo-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px;
}
.zv-logo {
  display: grid; gap: 8px; min-width: 0; padding: 10px; border-radius: 12px;
  border: 1px solid var(--zv-line); background: var(--zv-paper);
}
/* the width and height attributes (frame.js) keep its room before it loads */
.zv-logo-img { display: block; max-width: 100%; max-height: 240px; height: auto; object-fit: contain; margin-inline: auto; }
.zv-logo-missing { margin: 0; padding: 12px 0; font-size: 13px; color: var(--zv-muted); text-align: center; }
/* (logo release 2, task 3) a logo change's preview: the saved logo ("Now")
   beside the change, drawn from the server's preview (an svg); the icon's
   colours as swatches when the card asks which part; fonts as quiet buttons
   (never .zv-choice: a later message does not retire them) */
.zv-logo-edit-body { display: grid; gap: 8px; width: 100%; }
.zv-logo-edit-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; width: 100%; }
.zv-logo-edit-fig { margin: 0; display: grid; gap: 4px; justify-items: center; padding: 8px;
  border: 1px solid var(--zv-line); border-radius: 10px; background: var(--zv-paper); }
.zv-logo-edit-img { display: block; width: 100%; max-height: 160px; height: auto; object-fit: contain; }
.zv-logo-edit-part { display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--zv-edge); background: var(--zv-paper); }
.zv-logo-edit-part .zv-swatch { width: 28px; height: 28px; }
.zv-swatch { display: inline-block; width: 16px; height: 16px; vertical-align: -3px; margin-inline-end: 6px; }
.zv-swatch circle { stroke: var(--zv-edge); stroke-width: 1; }
.zv-logo-edit-font {
  display: inline-flex; align-items: center; min-height: 40px; padding: 8px 14px; border-radius: 10px;
  cursor: pointer; border: 1px solid var(--zv-edge); background: var(--zv-paper); color: var(--zv-ink);
  font: inherit; font-size: 14px; font-weight: 500; line-height: 1.35;
}
.zv-logo .zv-row { margin-top: 0; gap: 6px; }
.zv-logos > .zv-row { margin-top: 2px; }
.zv-logo-wait { display: grid; gap: 4px; }
/* Customize, Save and the album link: quiet outline controls; More is the lime action */
.zv-logo-link, .zv-logo-save {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 36px; padding: 6px 12px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--zv-edge); background: var(--zv-paper); color: var(--zv-ink);
  font: inherit; font-size: 13.5px; font-weight: 500; line-height: 1.35; text-decoration: none;
}
.zv-logo-link .zv-icon { width: 16px; height: 16px; }
.zv-logos > .zv-row .zv-logo-link { min-height: 44px; padding: 10px 14px; font-size: 14px; }
/* saved: a quiet confirmation, still readable (10.5:1) */
.zv-logo-save:disabled { cursor: default; border-color: transparent; background: var(--zv-badge); color: var(--zv-action-ink); }
.zv-logo-save[aria-disabled="true"], .zv-logo-more[aria-disabled="true"] { opacity: .55; cursor: default; }
/* (owner 2026-10-17) the compact card (frame.js logoCard, the widget only):
   the first three previews one under the other in slimmer frames, nothing on
   them (a horizontal preview is about 700 x 120: three side by side would be
   too small to read in the bubble); then Continue in Zoviz Agent (the shared
   primary action, .zv-btn), its line (4.9:1 on --zv-quiet) and the album as
   a small text link */
.zv-logo-strip {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px;
}
.zv-logo-thumb { padding: 8px; }
.zv-logo-thumb .zv-logo-img { max-height: 72px; }
.zv-logo-compact > .zv-row { margin-top: 4px; }
.zv-logo-go-note { font-size: 13px; color: var(--zv-muted); }
.zv-logo-also .zv-link { display: inline-flex; align-items: center; gap: 4px; font-size: 13.5px; }
.zv-logo-also .zv-icon { width: 14px; height: 14px; }

/* (owner 2026-10-16) the hand-off under an answer (frame.js handoffCard): its
   one button is the shared primary action (.zv-btn), never a choice */
.zv-handoff { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/* (owner 2026-10-16, phase 0) the sign-in prompt under a message (frame.js
   signInPrompt): why, the shared primary action (.zv-btn, never a choice) and
   the ways to sign in in a small muted line (4.9:1 on --zv-quiet) */
.zv-signin { display: grid; justify-items: start; gap: 6px; margin-top: 10px; }
.zv-signin-act { display: grid; justify-items: start; gap: 4px; }
.zv-signin .zv-row { margin-top: 2px; }
.zv-signin-methods { margin: 0; font-size: 13px; line-height: 1.5; color: var(--zv-muted); }

.zv-status { min-height: 0; padding: 0 14px; font-size: 13px; color: var(--zv-muted); }
.zv-status:not(:empty) { padding: 6px 14px; }
.zv-ts { padding: 0 14px 8px; }

/* (attach first) the form wraps only for the added image's chip, a line of
   its own above the box: the box's basis is 0, so the box, the buttons and
   Send always share one line */
.zv-form {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px;
  padding: 12px 14px 6px; border-block-start: 1px solid var(--zv-line);
}
.zv-input {
  flex: 1 1 0%; min-width: 0; min-height: 48px; max-height: 120px; resize: none; padding: 12px 14px;
  font: inherit; font-size: 16px; line-height: 22px;   /* 16 px: no zoom on focus in mobile browsers; 22 + 24 + 2 = 48 */
  color: var(--zv-ink); border: 1px solid var(--zv-field); border-radius: 10px; background: var(--zv-paper);
}
.zv-input::placeholder { color: var(--zv-muted); opacity: 1; }   /* 5.3:1, never the browser's faded grey */
/* the transparent outline is what forced colours (Windows High Contrast) draw */
.zv-input:focus-visible, .zv-input:focus {
  outline: 2px solid transparent; outline-offset: 1px;
  border-color: var(--zv-teal); box-shadow: 0 0 0 3px rgba(0, 132, 125, .22);
}
/* an empty box in a right-to-left interface reads right to left (dir="auto" sees no text yet) */
:root[dir="rtl"] .zv-input:placeholder-shown { direction: rtl; }
.zv-send {
  flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 16px; border: 1px solid transparent; border-radius: 10px; cursor: pointer;
  background: var(--zv-deep); color: #fff; font: inherit; font-size: 15px; font-weight: 600;
}
.zv-send .zv-icon { width: 18px; height: 18px; }
.zv-send:disabled { opacity: .55; cursor: default; }
/* (image tools) add an image: beside the box, shown only to staff and test accounts */
.zv-attach {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 44px; min-height: 48px;
  padding: 0; border-radius: 10px; cursor: pointer; border: 1px solid var(--zv-field);
  background: var(--zv-paper); color: var(--zv-ink);
}
.zv-attach .zv-icon { width: 20px; height: 20px; }
.zv-attach:disabled { opacity: .55; cursor: default; }
/* (attach first) the image waiting for Send: its thumbnail, "Image added"
   and a remove button, in a quiet chip */
.zv-staged { flex: 0 0 100%; min-width: 0; display: flex; }
.zv-chip {
  display: inline-flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%;
  padding-block: 4px; padding-inline: 4px; border: 1px solid var(--zv-edge); border-radius: 12px;
  background: var(--zv-quiet);
}
.zv-staged-img, .zv-thumb {
  background-color: var(--zv-paper);
  background-image: linear-gradient(45deg, var(--zv-line) 25%, transparent 25%, transparent 75%, var(--zv-line) 75%),
    linear-gradient(45deg, var(--zv-line) 25%, transparent 25%, transparent 75%, var(--zv-line) 75%);
  background-size: 12px 12px; background-position: 0 0, 6px 6px;
}
.zv-staged-img { flex: none; display: block; width: 40px; height: 40px; object-fit: cover; border-radius: 8px; }
.zv-staged-label {
  min-width: 0; font-size: 13.5px; font-weight: 500; line-height: 1.35; color: var(--zv-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.zv-staged-x {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
  padding: 0; border-radius: 8px; cursor: pointer; border: 1px solid transparent; background: transparent;
  color: var(--zv-muted);
}
.zv-staged-x .zv-icon { width: 18px; height: 18px; }
/* a file dragged over the chat: the box it goes to is marked */
.zv-drop .zv-input { border-style: dashed; border-color: var(--zv-teal); box-shadow: 0 0 0 3px rgba(0, 132, 125, .22); }
/* the image sent with a message, under its text in the visitor's bubble */
.zv-thumb { display: block; max-width: 100%; max-height: 160px; width: auto; height: auto; margin-top: 8px; border-radius: 10px; }
.zv-hint { margin: 0; padding: 2px 14px 12px; font-size: 12px; line-height: 1.5; color: var(--zv-muted); }

/* The staff sign-in (plan I8): frame.html#staff, opened directly */
.zv-staff { max-width: 480px; margin: 0 auto; padding: 32px 18px; background: var(--zv-paper); min-height: 100%; }
.zv-staff .zv-title { font-size: 22px; font-weight: 600; letter-spacing: -.02em; white-space: normal; }
.zv-staff p { margin: 12px 0; color: var(--zv-muted); }
.zv-staff-form { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.zv-staff-form label { flex: 1 1 100%; font-size: 14px; font-weight: 500; color: var(--zv-ink); }
.zv-staff-form .zv-input { flex: 1 1 200px; }
.zv-staff .zv-hbtn { border-color: var(--zv-edge); }
.zv-staff-state:empty { display: none; }
.zv-staff .zv-staff-state { font-weight: 600; color: var(--zv-ink); }
.zv-staff-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; }
.zv-staff .zv-hbtn { font-size: 14px; min-height: 40px; padding: 8px 14px; border-radius: 10px; }
body:has(.zv-staff:not([hidden])) { overflow: auto; background: var(--zv-paper); }

/* (owner 2026-10-16, phase 0) signed-in.html: the tab Zoviz's sign-in returns
   to, opened directly (never a frame) */
body.zv-page { overflow: auto; background: var(--zv-paper); }
.zv-page-main { display: grid; justify-items: start; gap: 16px; max-width: 480px; margin: 0 auto; padding: 48px 18px; }
.zv-page-main .zv-title { font-size: 20px; line-height: 1.4; white-space: normal; }

/* A phone: the frame is the whole screen (the snippet sizes it) */
@media (max-width: 380px) {
  .zv-head { padding-inline: 12px 46px; }
  .zv-close { inset-inline-end: 4px; }
  .zv-avatar { width: 30px; height: 30px; border-radius: 9px; }
  .zv-hbtn { padding: 6px 7px; }
  .zv-send { padding: 0 13px; }
}
@media (max-height: 420px) {
  .zv-avatar { display: none; }
  .zv-head { padding-block: 6px; }
  .zv-close { inset-block-start: 6px; }
  .zv-hint { padding-block: 0 6px; }
}
/* Touch: principal controls reach 44 px */
@media (pointer: coarse) {
  .zv-hbtn, .zv-close { min-height: 44px; }
  .zv-close { min-width: 44px; }
  .zv-hbtn.zv-agent { min-width: 44px; }
  .zv-btn, .zv-choice, .zv-feedback .zv-choice { min-height: 44px; }
  .zv-attach { min-width: 44px; min-height: 44px; }
  .zv-staged-x { width: 44px; height: 44px; }
  .zv-logo-link, .zv-logo-save { min-height: 44px; }
  .zv-logo-also .zv-link { min-height: 44px; }
  .zv-head { padding-inline-end: 52px; }
  .zv-close { inset-block-start: 8px; inset-inline-end: 4px; }
}

@media (hover: hover) and (pointer: fine) {
  .zv-launcher:hover { background: var(--zv-deep-hover); }
  .zv-hbtn:hover { background: var(--zv-quiet); }
  .zv-btn:hover { background: var(--zv-action-hover); }
  .zv-choice:hover:not(:disabled) { border-color: var(--zv-teal); background: var(--zv-quiet); }
  .zv-choice.zv-primary:hover:not(:disabled) { border-color: var(--zv-action-border); background: var(--zv-action-hover); }
  .zv-attach:hover:not(:disabled) { border-color: var(--zv-teal); background: var(--zv-quiet); }
  .zv-staged-x:hover { border-color: var(--zv-edge); background: var(--zv-paper); color: var(--zv-ink); }
  .zv-logo-link:hover, .zv-logo-save:hover:not(:disabled):not([aria-disabled="true"]) {
    border-color: var(--zv-teal); background: var(--zv-quiet);
  }
  .zv-logo-more[aria-disabled="true"]:hover { background: var(--zv-action-bg); }
  .zv-send:hover:not(:disabled) { background: var(--zv-deep-hover); }
  .zv-link:hover { text-decoration-thickness: 2px; }
}

@keyframes zv-rise { from { opacity: 0; transform: translateY(8px); } }
@keyframes zv-fade { from { opacity: 0; } }
/* the image job's bar: a teal stretch crossing the track */
@keyframes zv-slide { from { background-position: -67% 0; } to { background-position: 167% 0; } }
@media (prefers-reduced-motion: no-preference) {
  .zv-launcher, .zv-btn, .zv-choice, .zv-hbtn, .zv-send, .zv-attach, .zv-logo-link, .zv-logo-save {
    transition: background-color 160ms var(--zv-ease), border-color 160ms var(--zv-ease), transform 160ms var(--zv-ease);
  }
  .zv-launcher:active, .zv-btn:active, .zv-send:active:not(:disabled), .zv-choice:active:not(:disabled),
  .zv-attach:active:not(:disabled) { transform: scale(.98); }
  .zv-panel:not([hidden]) { animation: zv-rise 200ms var(--zv-ease); }
  .zv-progress {
    background: linear-gradient(90deg, var(--zv-teal), var(--zv-teal)) -67% 0 / 40% 100% no-repeat, var(--zv-line);
    animation: zv-slide 1.4s ease-in-out infinite;
  }
}
@media (prefers-reduced-motion: reduce) {
  .zv-panel:not([hidden]) { animation: zv-fade 200ms linear; }
}
