/* =========================================================================
   Design system tokens. Source of truth is DESIGN.md at the repo root.
   Read it before changing anything here.

   Every token is --ds-* prefixed on purpose: the original stylesheet already
   owns --ink, --accent, --radius-* and others with different meanings, and an
   unprefixed block here silently loses to it.

   Two materials: --ds-paper is the document, --ds-desk is the app it rests on.
   --ds-accent and --ds-accent-wash are RESERVED for the product speaking about the
   document (AI summaries, risk flags, explanations). Nothing else may use them.
   ========================================================================= */
:root {
  --ds-ink: #1B2F57;
  --ds-ink-soft: #3C4A63;
  --ds-ink-mute: #6B7890;

  --ds-paper: #FBFAF7;
  --ds-desk: #F2F4F7;
  --ds-desk-sunk: #E7EAF0;
  --ds-line: #D9DEE7;
  --ds-line-soft: #E9ECF2;

  --ds-accent: #F4C542;
  --ds-accent-wash: #FEF6E0;
  --ds-accent-ink: #6B4E05;

  --ds-success: #1F7A4C;
  --ds-success-ink: #176340; /* success text on a success wash */
  --ds-success-wash: #E9F5EE;
  --ds-warning: #B45309;
  --ds-error: #B42318;
  --ds-error-ink: #991B13;   /* error text on an error wash */

  --ds-radius-sm: 4px;
  --ds-radius-md: 8px;
  --ds-radius-lg: 12px;
  --ds-radius-full: 9999px;

  --ds-s-1: 4px;
  --ds-s-2: 8px;
  --ds-s-3: 12px;
  --ds-s-4: 16px;
  --ds-s-5: 24px;
  --ds-s-6: 32px;
  --ds-s-7: 48px;

  /* Depth has an offset. Never a zero-offset halo. */
  --ds-lift-1: 0 1px 2px rgba(27, 47, 87, .06), 0 1px 1px rgba(27, 47, 87, .04);
  --ds-lift-2: 0 2px 4px rgba(27, 47, 87, .06), 0 4px 12px rgba(27, 47, 87, .07);
  --ds-lift-paper: 0 1px 2px rgba(27, 47, 87, .08), 0 8px 24px rgba(27, 47, 87, .10);

  --ds-font-display: 'Cabinet Grotesk', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --ds-font-ui: 'General Sans', system-ui, -apple-system, sans-serif;
  --ds-font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', monospace;

  --ds-ease-out: cubic-bezier(.2, .7, .3, 1);
  --ds-dur-micro: 90ms;
  --ds-dur-short: 180ms;
}

@media (prefers-reduced-motion: reduce) {
  :root { --ds-dur-micro: 1ms; --ds-dur-short: 1ms; }
}

/* =========================================================================
   SCAFFOLDING. These are the app's original token names, kept so that ~340
   existing var() call sites inherit the design system without being edited.
   The values now point at --ds-*; the names are the only thing legacy here.

   Exit condition: once every surface is verified against DESIGN.md, replace
   the call sites with direct --ds-* references and delete this block. Until
   then, do not add a new var() reference to a name below - use --ds-* in new
   code.

   Three of these could NOT be bridged, because they mean more than one thing
   in this stylesheet, and no single value is right at all their call sites:
   --panel, --radius-sm and --accent. See the notes on each.
   ========================================================================= */
:root {
  color-scheme: light;

  /* The desk is the surface the document rests on. --ds-paper is the document
     and belongs to .pdf-page alone: if panels and popovers were also paper,
     the one shadow carrying the thesis would stop meaning anything. */
  --bg: var(--ds-desk-sunk);
  --bg-subtle: var(--ds-desk-sunk);
  --panel: var(--ds-desk);
  --panel-soft: var(--ds-desk-sunk);

  --ink: var(--ds-ink);
  --ink-secondary: var(--ds-ink-soft);
  --muted: var(--ds-ink-mute);

  /* Primary action. NOT --ds-accent: amber is reserved for the product
     speaking about the document, and mapping it here would put the one
     differentiating colour on every button in the app. */
  --accent: var(--ds-ink);
  --accent-hover: #122039;
  --accent-subtle: color-mix(in srgb, var(--ds-ink) 6%, transparent);

  /* An unassigned field still has to read as a field. Inheriting --accent
     here would paint it in --ds-ink, the colour of the document's own text,
     on paper. */
  --signer-fallback: #5B4636;

  --border: var(--ds-line);
  --border-strong: color-mix(in srgb, var(--ds-ink) 18%, transparent);

  /* Depth has an offset. Never a zero-offset halo. */
  --shadow-sm: var(--ds-lift-1);
  --shadow: var(--ds-lift-1);
  --shadow-lg: var(--ds-lift-2);
  --shadow-xl: var(--ds-lift-2);

  /* --radius-sm is overloaded across buttons, inputs and panels. It takes the
     dominant use (buttons and panels, 8px); the ~6 input call sites take
     --radius-field explicitly. 4px is the document's radius and giving it to
     every panel would make panels read as paper. */
  --radius-sm: var(--ds-radius-md);
  --radius-field: var(--ds-radius-sm);
  --radius: var(--ds-radius-md);
  --radius-lg: var(--ds-radius-lg);
  --radius-xl: var(--ds-radius-lg);

  --transition: var(--ds-dur-micro) var(--ds-ease-out);
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html {
  /* The window's own scrollbar appears the moment a document is on screen,
     and it took 15px off the width the page had just been fitted to, leaving
     the page wider than the box that holds it. Reserving the room up front
     means the width the renderer measures is the width it keeps. A no-op
     where scrollbars overlay the content, which is every phone. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ─── Layout ─── */

.app {
  max-width: 1360px;
  margin: 0 auto;
  padding: 16px 20px 48px;
  display: grid;
  gap: 20px;
}

.documents-screen {
  display: grid;
  grid-template-columns: minmax(360px, 1.5fr) minmax(0, 2.5fr);
  gap: 16px;
  align-items: stretch;
}

.documents-screen.documents-screen--focused {
  grid-template-columns: minmax(0, 1fr);
}

.documents-inbox {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  display: grid;
  grid-template-rows: auto 1fr;
  min-height: 620px;
  max-height: calc(100vh - 156px);
  overflow: hidden;
  position: sticky;
  top: 82px;
}

.documents-screen.documents-screen--focused .documents-inbox {
  display: none;
}

.documents-inbox__head {
  padding: 14px 14px 10px;
  border-bottom: 1px solid var(--border);
}

.documents-inbox__head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.documents-inbox__head h2 {
  margin: 0;
  font-size: 1rem;
}

.documents-inbox__head p {
  margin: 6px 0 0;
  font-size: 0.83rem;
  color: var(--muted);
}

.documents-list {
  display: grid;
  gap: 6px;
  padding: 10px;
  overflow: auto;
  align-content: start;
}

.documents-list__empty {
  margin: 0;
  padding: 16px 8px;
  color: var(--muted);
  font-size: 0.88rem;
}

.documents-list__empty-wrap {
  /* Message, explanation and action stack at every width. Side by side they
     crammed into a column that is 350px wide on a phone and not much more on
     a desktop. */
  padding: var(--ds-s-5) var(--ds-s-4);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.documents-list__upload {
  background: var(--accent);
  color: var(--ds-paper);
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}

.documents-list__upload:hover {
  background: var(--accent-hover);
}

.documents-list__section {
  margin-bottom: 12px;
}

.documents-list__section:last-of-type {
  margin-bottom: 0;
}

.documents-list__section-title {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin: 0 0 8px 0;
  padding: 0;
}

.document-row {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--ds-desk);
  text-align: left;
  padding: 10px 11px;
  display: grid;
  gap: 6px;
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}

.document-row:focus-visible {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

.document-row:hover {
  border-color: var(--accent-hover);
  background: var(--accent-hover);
  /* The children are recoloured below, but the row owns the inherited
     colour: without this, any text added to it later lands ink on ink. */
  color: var(--ds-paper);
  box-shadow: var(--shadow-sm);
}

.document-row.is-active {
  border-color: var(--accent);
  background: var(--ds-desk-sunk);
}

.document-row:hover:not(.is-active) .document-row__title,
.document-row:hover:not(.is-active) .document-row__meta {
  color: var(--ds-paper);
}

.document-row:hover:not(.is-active) .document-row__status {
  background: rgba(251, 250, 247, 0.18);
  color: var(--ds-paper);
  border-color: rgba(251, 250, 247, 0.45);
}

.document-row__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.document-row__title {
  display: block;
  min-width: 0;
  flex: 1;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.document-row__delete {
  border: 1px solid var(--border-strong);
  background: var(--panel-soft);
  color: var(--muted);
  width: 20px;
  height: 20px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}

.document-row__delete:hover {
  background: rgba(239, 68, 68, 0.16);
  border-color: rgba(220, 38, 38, 0.75);
  color: var(--ds-error-ink);
}

.document-row:hover:not(.is-active) .document-row__delete {
  background: rgba(251, 250, 247, 0.18);
  border-color: rgba(255, 255, 255, 0.5);
  color: var(--ds-paper);
}

.document-row__meta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  color: var(--muted);
  font-size: 0.78rem;
}

.document-row__updated {
  display: block;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* An envelope the server knows you sent, on a device that has no copy of it.
   The recipient is the thing that tells these rows apart from each other -
   the file names are often the same contract going to different people - so
   the address is on the row rather than only in the document. It reads as
   metadata, not as the title: the document is still what you are looking for. */
.document-row__sent-to {
  display: block;
  min-width: 0;
  margin-top: 2px;
  color: var(--muted);
  font-size: 0.76rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.document-row__status {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  border: 1px solid transparent;
  flex-shrink: 0;
}

.document-row__status[data-status='draft'] {
  background: var(--ds-desk-sunk);
  color: var(--ds-ink-soft);
}

.document-row__status[data-status='in-progress'] {
  background: color-mix(in srgb, var(--ds-warning) 10%, var(--ds-paper));
  color: var(--ds-warning);
}

.document-row__status[data-status='completed'] {
  background: var(--ds-success-wash);
  color: var(--ds-success);
}

.document-row__status[data-status='new'] {
  background: var(--ds-desk-sunk);
  color: var(--ds-ink-soft);
}

/* Somebody is waiting on you: the same attention as a document in flight. */
.document-row__status[data-status='awaiting-you'] {
  background: color-mix(in srgb, var(--ds-warning) 10%, var(--ds-paper));
  color: var(--ds-warning);
}

/*
 * Declined is the one that has to be unmistakable. The others are over
 * without anyone having refused, so they are quiet rather than red: an
 * expired link is an inconvenience, a refusal is an answer.
 */
.document-row__status[data-status='declined'] {
  background: color-mix(in srgb, var(--ds-error) 10%, var(--ds-paper));
  color: var(--ds-error-ink);
}

.document-row__status[data-status='voided'],
.document-row__status[data-status='expired'] {
  background: var(--ds-desk-sunk);
  color: var(--ds-ink-soft);
}

.documents-main {
  min-width: 0;
  display: grid;
  gap: 10px;
}

.documents-ribbon {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  position: sticky;
  /* Under the header, measured rather than guessed. The 82px this used
     to be was the distance from the top of a page that had an empty
     row in it; once that row went, the ribbon was already above its
     own sticky line at rest and sat on top of the document. */
  top: calc(var(--app-header-h, 56px) + 8px);
  z-index: 12;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 10px 12px;
}

.documents-ribbon__left {
  min-width: 0;
  display: grid;
  gap: 8px;
  flex: 1;
}

.documents-ribbon__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.documents-ribbon__actions-main {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;
  min-width: 0;
  flex: 1 1 auto;
}

.documents-inbox__controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.documents-ribbon__signers {
  min-width: 0;
  display: grid;
  gap: 8px;
}

.documents-ribbon__signers-head {
  display: flex;
  align-items: end;
  gap: 8px;
  flex-wrap: wrap;
}

.tools-signer--ribbon {
  min-width: 180px;
  max-width: 260px;
}

.signer-list--ribbon {
  max-width: 100%;
}

.menu-add-signer--ribbon {
  width: auto;
  padding: 8px 12px;
  align-self: end;
}

.signer-form--ribbon {
  max-width: 440px;
}

.documents-ribbon button,
.documents-inbox__controls button {
  width: auto;
  background: var(--bg-subtle);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  box-shadow: none;
}

.documents-ribbon button:not(:disabled):hover,
.documents-inbox__controls button:not(:disabled):hover {
  background: var(--accent);
  color: var(--ds-paper);
  border-color: transparent;
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.documents-ribbon button:not(:disabled):active,
.documents-inbox__controls button:not(:disabled):active {
  transform: translateY(0);
  box-shadow: none;
}

.documents-ribbon button:disabled,
.documents-inbox__controls button:disabled {
  background: var(--bg-subtle);
  color: var(--muted);
  border-color: var(--border);
  box-shadow: none;
}

.documents-ribbon #documents-send-next.is-ready {
  background: var(--accent);
  color: var(--ds-paper);
  border-color: transparent;
  box-shadow: var(--shadow-sm);
}

.documents-ribbon #documents-send-next.is-ready:not(:disabled):hover {
  background: var(--accent-hover);
  color: var(--ds-paper);
  border-color: transparent;
}

.documents-ribbon #documents-my-docs.is-open {
  background: var(--accent);
  color: var(--ds-paper);
  border-color: transparent;
}

.documents-ribbon #documents-my-docs.is-open:not(:disabled):hover {
  background: var(--accent-hover);
  color: var(--ds-paper);
  border-color: transparent;
}

.documents-inbox__controls #documents-my-docs.is-open {
  background: var(--accent);
  color: var(--ds-paper);
  border-color: transparent;
}

.documents-inbox__controls #documents-my-docs.is-open:not(:disabled):hover {
  background: var(--accent-hover);
  color: var(--ds-paper);
  border-color: transparent;
}

.workspace {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 10px;
  align-items: start;
}

.workspace.workspace--no-tools {
  grid-template-columns: 1fr;
}

.document-tools {
  position: sticky;
  top: 82px;
  align-self: start;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  box-shadow: var(--shadow-sm);
  display: grid;
  /* Three children now: the signer picker, the hint, and the chips. The
     chips take the row that stretches; a template of two rows would put
     the hint in it and push the chips out through overflow: hidden. */
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: 12px;
  max-height: calc(100vh - 156px);
  overflow: hidden;
}

.document-tools__top {
  display: grid;
  gap: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.document-tools__recipient-hint {
  font-size: 0.8rem;
  color: var(--muted);
  margin: 0;
  line-height: 1.4;
}

.document-tools__items {
  display: grid;
  gap: 10px;
  min-height: 0;
  overflow: auto;
  padding-right: 2px;
}

/* Recipient mode: hide add-field tools; recipient only fills existing fields */
body.recipient-mode .document-tools__items {
  display: none;
}

body.recipient-mode .document-tools__top .menu-add-signer {
  display: none;
}

.tools-signer {
  display: grid;
  gap: 6px;
  font-size: 0.8rem;
  color: var(--muted);
  font-weight: 600;
}

.tools-signer select {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 6px 10px;
  font-family: inherit;
  font-size: 0.85rem;
  background: var(--panel);
  color: var(--ink);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.tools-signer select:focus {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

.tools-group {
  display: grid;
  gap: 6px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.tools-group:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.tools-group--inline {
  display: grid;
  gap: 6px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.tools-group--inline:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.tools-compress__head {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--ink);
}

.tools-compress__row {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 8px;
}

.tools-compress__row--single {
  grid-template-columns: 1fr;
}

.tools-compress__label {
  font-size: 0.78rem;
  color: var(--muted);
  font-weight: 600;
}

.tools-compress__select {
  width: 100%;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 6px 10px;
  font-family: inherit;
  font-size: 0.83rem;
  background: var(--panel);
  color: var(--ink);
}

.tools-compress__run {
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--ink);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 0.83rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}

.tools-compress__run:hover:not(:disabled) {
  background: var(--accent-subtle);
  color: var(--accent-hover);
}

.tools-compress__run:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.tools-compress__stats {
  display: grid;
  gap: 4px;
  font-size: 0.76rem;
  color: var(--muted);
}

.tools-compress__stats strong {
  color: var(--ink);
  font-weight: 700;
}

.tools-compress__warning {
  margin: 0;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(180, 83, 9, 0.4);
  background: color-mix(in srgb, var(--ds-warning) 10%, var(--ds-paper));
  color: var(--ds-warning);
  font-size: 0.74rem;
  line-height: 1.35;
  font-weight: 600;
}

.tools-compress__warning[data-severity='high'] {
  border-color: rgba(220, 38, 38, 0.45);
  background: rgba(220, 38, 38, 0.12);
  color: var(--ds-error);
}

.save-compress-tools {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px;
  background: var(--bg-subtle);
}

.tool-item {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--ink);
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.84rem;
  font-weight: 500;
  cursor: grab;
  text-align: left;
  box-shadow: none;
}

.tool-item:hover {
  background: var(--accent-subtle);
  color: var(--accent-hover);
}

.tool-item:active {
  cursor: grabbing;
}

.tool-icon {
  width: 20px;
  text-align: center;
  font-size: 0.95rem;
}

/* ─── Header ─── */

.app__header {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(248, 249, 251, 0.85);
  backdrop-filter: blur(16px) saturate(1.8);
  -webkit-backdrop-filter: blur(16px) saturate(1.8);
  padding: 14px 20px;
  margin: 0 auto;
  max-width: 1360px;
  border-bottom: 1px solid var(--border);
}

.app__header h1 {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.app__header p {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.app__title {
  flex: 1;
  min-width: 200px;
  display: grid;
  gap: 10px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand__logo {
  /* Square, from the 120x120 viewBox. Stated rather than left to auto so the
     header does not reflow if a browser sizes an inline SVG differently. */
  width: 28px;
  height: 28px;
  /* The mark strokes currentColor, so this is what colours it. Set here, not
     inherited, so moving the brand onto a darker surface is a one-line change
     and never leaves the mark the same colour as the ground. */
  color: var(--ds-ink);
}

/* --- Document Nav --- */
.document-nav {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.85);
  box-shadow: var(--shadow-sm);
  width: fit-content;
  max-width: 100%;
}

.document-nav__root {
  color: var(--ink-secondary);
  font-size: 0.86rem;
  font-weight: 700;
}

.document-nav__sep {
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 700;
}

.document-nav__doc {
  color: var(--ink);
  font-size: 0.86rem;
  font-weight: 700;
  max-width: 360px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.document-nav__size {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

.document-nav__crumb--interactive {
  cursor: pointer;
  border-radius: 6px;
  transition: color var(--transition), background var(--transition);
}

.document-nav__root.document-nav__crumb--interactive {
  color: var(--ds-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

.document-nav__crumb--interactive:hover {
  color: #122039;
  background: var(--accent-subtle);
}

.document-nav__crumb--interactive:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- Plan Status --- */
.plan-status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-left: 12px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.85);
  box-shadow: var(--shadow-sm);
  flex-wrap: nowrap;
}

.plan-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--ink);
  font-weight: 600;
}

.plan-usage {
  color: var(--muted);
  font-weight: 600;
}

.plan-info {
  width: 20px;
  height: 20px;
  min-width: 20px;
  min-height: 20px;
  aspect-ratio: 1 / 1;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--muted);
  font-size: 0.7rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.plan-upgrade {
  background: var(--accent);
  color: var(--ds-paper);
  border: none;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
  cursor: pointer;
}

.plan-upgrade:hover {
  background: var(--accent-hover);
}

/* ─── Header Actions ─── */

.header-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  position: relative;
}

.icon-button {
  background: var(--panel);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  width: 36px;
  height: 36px;
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all var(--transition);
}

.icon-button:hover {
  background: var(--bg-subtle);
  border-color: var(--border-strong);
  box-shadow: var(--shadow);
}

.icon-button--plain {
  background: transparent;
  border: none;
  box-shadow: none;
}

.icon-button--plain:hover {
  background: var(--accent-subtle);
}

/* ─── User Badge ─── */

.user-badge {
  background: var(--accent-subtle);
  border: none;
  border-radius: var(--radius-sm);
  padding: 6px 12px;
  font-size: 0.85rem;
  color: var(--accent-hover);
  box-shadow: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 500;
}

.user-badge__label {
  color: var(--muted);
  font-weight: 400;
}

/* ─── Dropdown Menu ─── */

.header-menu {
  position: absolute;
  top: calc(100% + 14px);
  right: 0;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  padding: 6px;
  min-width: 220px;
  box-shadow: var(--shadow-xl);
  display: grid;
  gap: 1px;
  z-index: 10;
  animation: menu-in 0.15s ease-out;
}

@keyframes menu-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.header-menu__head {
  display: flex;
  justify-content: flex-end;
  padding: 2px 2px 0;
}

.menu-list {
  display: grid;
  gap: 2px;
}

.menu-icon {
  display: inline-block;
  width: 20px;
  font-size: 0.85rem;
  text-align: center;
  flex-shrink: 0;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  color: var(--ink);
  border: none;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  text-align: left;
  box-shadow: none;
  font-weight: 500;
  font-size: 0.85rem;
  transition: background var(--transition);
}

.menu-item:hover {
  background: var(--accent-subtle);
}

.menu-item--palette {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.menu-item--signers {
  display: grid;
  gap: 8px;
}

.menu-item__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-weight: 600;
}

.menu-add-signer {
  background: var(--bg-subtle);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 0.75rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: none;
}

.menu-add-signer:hover {
  background: var(--accent-subtle);
  color: var(--accent-hover);
}

.menu-add-signer--block {
  width: 100%;
  justify-content: center;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
}

.signer-form {
  display: grid;
  gap: 8px;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
}

.signer-form--inline {
  grid-template-columns: 1fr;
  align-items: stretch;
}

.signer-form--modal {
  border: none;
  background: transparent;
  padding: 0;
}

.signer-form--inline .signer-form__actions {
  align-self: stretch;
}

.signer-form__field {
  display: grid;
  gap: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
}

.signer-form__field input {
  width: 100%;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 6px 8px;
  background: var(--panel);
  color: var(--ink);
  font-size: 0.8rem;
  font-family: inherit;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.signer-form__field input:focus {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

.signer-form__field input.is-invalid {
  border-color: var(--ds-error);
  outline: 2px solid var(--ds-error);
  outline-offset: 1px;
}

.signer-form__error {
  margin: -2px 0 0;
  font-size: 0.72rem;
  line-height: 1.25;
  color: var(--ds-error);
  font-weight: 700;
}

.signer-form__actions {
  display: flex;
  gap: 6px;
}

.signer-form__btn {
  flex: 1;
  padding: 6px 8px;
  border: 1px solid var(--border-strong);
  background: var(--panel);
  color: var(--ink-secondary);
  border-radius: 8px;
  box-shadow: none;
  font-size: 0.78rem;
  font-weight: 700;
}

.signer-form__btn--primary {
  border-color: transparent;
  background: var(--accent);
  color: var(--ds-paper);
}

.signer-form__btn:not(:disabled):hover {
  box-shadow: none;
  transform: none;
}

.signer-form__btn:not(:disabled):active {
  box-shadow: none;
}

.signer-form__btn--primary:not(:disabled):hover {
  background: var(--accent-hover);
}

.signer-form__btn:not(.signer-form__btn--primary):not(:disabled):hover {
  background: var(--bg-subtle);
  color: var(--ink);
}

.signer-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.signer-list--sidebar {
  padding-top: 4px;
}

.signer-list--sidebar .signer-pill {
  width: 100%;
}

.signer-pill {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 12px;
  background: transparent;
  color: var(--signer-color, var(--ink-secondary));
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--signer-color, var(--border-strong));
  max-width: 100%;
}

.signer-pill__index {
  width: 14px;
  height: 14px;
  min-width: 14px;
  border-radius: 999px;
  border: 1px solid currentColor;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.62rem;
  line-height: 1;
  font-weight: 700;
}

.signer-pill__label {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.signer-pill__content {
  min-width: 0;
  flex: 1;
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
}

.signer-pill.is-active {
  background: var(--signer-color, var(--signer-fallback));
  color: var(--ds-paper);
}

.signer-pill.is-active .signer-pill__index {
  border-color: rgba(255, 255, 255, 0.65);
  background: rgba(255, 255, 255, 0.2);
}

.signer-remove {
  border: none;
  background: transparent;
  color: inherit;
  font-size: 0.75rem;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  opacity: 0.7;
}

.signer-remove:hover {
  opacity: 1;
}

.menu-item--select {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.menu-item--select select {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 6px 10px;
  font-family: inherit;
  font-size: 0.85rem;
  background: var(--panel);
  color: var(--ink);
  transition: border-color var(--transition);
}

.menu-item--select select:focus {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

/* ─── Color Palette ─── */

.color-palette {
  display: grid;
  gap: 6px;
}

.color-palette__row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.color-palette__grid {
  display: grid;
  grid-template-columns: repeat(10, 14px);
  gap: 4px;
}

.color-dot {
  width: 12px;
  height: 12px;
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.2);
  cursor: pointer;
  padding: 0;
  background: transparent;
  transition: transform var(--transition), border-color var(--transition), box-shadow var(--transition);
}

.color-swatch {
  width: 14px;
  height: 10px;
  border-radius: 4px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform var(--transition), border-color var(--transition), box-shadow var(--transition);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

.color-swatch:hover,
.color-dot:hover {
  transform: scale(1.06);
  outline: 2px solid var(--ds-ink);
  outline-offset: 1px;
}

/* ─── Buttons ─── */

button {
  border: none;
  background: var(--accent);
  color: var(--ds-paper);
  padding: 10px 20px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: all var(--transition);
  box-shadow: var(--shadow-sm);
  font-family: inherit;
}

button:disabled {
  cursor: not-allowed;
  background: var(--bg-subtle);
  color: var(--muted);
  box-shadow: none;
}

button:not(:disabled):hover {
  background: var(--accent-hover);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

button:not(:disabled):active {
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

#auth-header-signout {
  padding: 6px 14px;
  font-size: 0.8rem;
  line-height: 1;
  height: 32px;
  align-self: center;
}

/* Keep tools hover readable (avoid global button hover override). */
#tools-sidebar .tool-item:hover {
  background: var(--accent-subtle);
  color: var(--accent-hover);
  box-shadow: none;
  transform: none;
}

/* Keep Add signer text/icon readable in tools bar on hover/press. */
#tools-sidebar .menu-add-signer:not(:disabled):hover,
#tools-sidebar .menu-add-signer:not(:disabled):active {
  background: var(--accent-subtle);
  color: var(--accent-hover);
  border-color: var(--accent);
  box-shadow: none;
  transform: none;
}

#tools-sidebar .menu-add-signer :is(.menu-icon, .tool-icon) {
  color: inherit;
}

/* Keep top-right menu options readable on green hover background. */
.header-menu .menu-item:not(:disabled):hover,
.header-menu .menu-item:not(:disabled):active {
  background: var(--accent-hover);
  color: var(--ds-paper);
  box-shadow: none;
  transform: none;
}

.header-menu .menu-item .menu-icon {
  color: inherit;
}

/* ─── Controls ─── */

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.file-input {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  padding: 10px 18px;
  border-radius: var(--radius-field);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  font-weight: 600;
  color: var(--ink);
  transition: all var(--transition);
}

.file-input:hover {
  box-shadow: var(--shadow);
}

.file-input input {
  display: none;
}

/* ─── Auth Panel ─── */

.auth-panel {
  border-radius: var(--radius-xl);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  padding: 24px;
  display: grid;
  gap: 20px;
  animation: auth-pop 0.2s ease-out;
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 31;
  width: min(680px, calc(100vw - 28px));
  max-height: calc(100vh - 28px);
  overflow: auto;
}

body.auth-open {
  overflow: hidden;
}

body.auth-open::before {
  content: '';
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.42);
  backdrop-filter: blur(2px);
  z-index: 30;
}

@keyframes auth-pop {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 10px)); }
  to { opacity: 1; transform: translate(-50%, -50%); }
}

@keyframes panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

.auth-panel__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.auth-panel__header h2 {
  margin: 0 0 4px;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

#auth-status {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.auth-close {
  background: transparent;
  color: var(--muted);
  border: none;
  box-shadow: none;
  padding: 4px;
  font-size: 1.1rem;
  line-height: 1;
  border-radius: var(--radius-sm);
}

.auth-close:hover {
  background: var(--accent-subtle);
  color: var(--ink);
}

.auth-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
}

.auth-field {
  display: grid;
  gap: 6px;
  font-weight: 500;
  font-size: 0.85rem;
  color: var(--ink-secondary);
}

.auth-field input {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 10px 14px;
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--panel);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.auth-field input:focus {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

.auth-field input::placeholder {
  color: var(--muted);
}

.auth-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* ─── Signature Panel ─── */

.signature-panel {
  border-radius: var(--radius-xl);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  padding: 24px;
  display: grid;
  gap: 18px;
  animation: panel-in 0.25s ease-out;
  scroll-margin-top: 72px;
}

.signature-panel__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.signature-panel__header h2 {
  margin: 0 0 4px;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.signature-panel__header p {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.signature-canvas-wrap {
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--bg-subtle);
  padding: 8px;
  transition: border-color var(--transition);
}

.signature-canvas-wrap:hover {
  border-color: var(--accent);
}

#signature-canvas {
  width: 100%;
  height: 160px;
  display: block;
  cursor: crosshair;
  touch-action: none;
  border-radius: var(--radius-sm);
}

.signature-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.signature-status {
  color: var(--ds-ink-soft);
  font-size: 0.85rem;
  font-weight: 500;
}

.signature-close {
  background: transparent;
  color: var(--muted);
  border: none;
  box-shadow: none;
  padding: 4px;
  font-size: 1.1rem;
  line-height: 1;
  border-radius: var(--radius-sm);
  /* Two faults in one box. It came out 26px tall, which is the icon plus its
     padding; and in the signature panel it came out 164px *wide*, because a
     display: block flex item with an SVG that has no intrinsic width resolves
     its max-content size against the line rather than against the mark. A
     close button that spans the header dismisses the panel from places
     nobody aimed at, so it is squared off and told not to grow. */
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
}

.signature-close:hover {
  background: var(--accent-subtle);
  color: var(--ink);
}

.signature-pen-size {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--muted);
  margin-top: 6px;
}

.signature-pen-size input[type='range'] {
  flex: 1;
  max-width: 140px;
  accent-color: var(--accent);
}

.initials-panel {
  padding-top: 10px;
}

.initials-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.initials-toolbar__left {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  flex: 1;
}

.initials-toolbar__right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.initials-tabs {
  display: flex;
  gap: 4px;
}

.initials-tab {
  padding: 5px 14px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border);
  background: var(--bg-subtle);
  color: var(--muted);
  font-size: 0.85rem;
  cursor: pointer;
  transition: all var(--transition);
  box-shadow: none;
}

.initials-tab--active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--ds-paper);
}

.initials-tab:not(.initials-tab--active):hover {
  border-color: var(--ds-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  color: var(--accent);
}

.initials-auto-form {
  display: flex;
  gap: 6px;
  align-items: center;
}

.initials-auto-form input[type='text'] {
  width: 140px;
  padding: 5px 10px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-field);
  font-size: 0.95rem;
  outline: none;
}

.initials-auto-form input[type='text']:focus {
  border-color: var(--accent);
}

.field-control-allpages {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px 5px;
  line-height: 1;
}

.initials-btn-secondary {
  background: transparent;
  border: 1.5px solid var(--border);
  color: var(--muted);
  box-shadow: none;
  font-size: 0.85rem;
  padding: 5px 12px;
}

.initials-btn-secondary:hover {
  border-color: var(--ds-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  color: var(--accent);
  background: transparent;
}

#initials-canvas {
  width: 100%;
  height: 120px;
  display: block;
  cursor: crosshair;
  touch-action: none;
  border-radius: var(--radius-sm);
}

#initials-preview-canvas {
  width: 100%;
  height: 120px;
  display: block;
  border-radius: var(--radius-sm);
}

/* ─── Viewer ─── */

.viewer {
  min-height: 480px;
  border-radius: var(--radius-xl);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  overflow: hidden;
  /* No gutter here. This box never scrolls, but `overflow: hidden` still
     makes it a scroll container, so a reserved gutter cost 15px down each
     side of the document for a scrollbar that can never appear. */
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.viewer-scroll {
  overflow-x: auto;
  overflow-y: auto;
  height: 100%;
  flex: 1 1 auto;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  /* One edge, not both: the scrollbar only ever lands on one side, and
     reserving the other just took another 15px off the page's width. */
  scrollbar-gutter: stable;
}

.viewer-ribbon {
  display: flex;
  align-items: center;
  gap: 12px;
  /* A group at the end of the ribbon's top row, beside the breadcrumb.
     It used to be a band of its own across the top of the document, with
     its own border and its own frosted background; in the ribbon it needs
     neither, because the ribbon is already the surface. */
  flex: 0 0 auto;
  margin-left: auto;
}

.documents-ribbon__top {
  display: flex;
  align-items: center;
  gap: 12px;
}

.documents-ribbon .documents-ribbon__top .document-nav {
  min-width: 0;
  /* Shrink, but do not stretch: the breadcrumb is a pill around a
     filename, and growing it to fill the row drew a wide empty box
     across the ribbon. */
  flex: 0 1 auto;
  /* Sharing the row with the view controls leaves the breadcrumb less
     width than it had to itself, and wrapping is the wrong answer: on a
     phone it took three lines and gave back more height than the row
     saved. The filename already truncates; the line does too now. */
  flex-wrap: nowrap;
  overflow: hidden;
}


/* Each part of the trail holds its own line. Left to shrink freely they
   did the worst possible thing on a phone: "My Documents" broke in two
   and the filename, which is the part worth reading, was squeezed down to
   a single letter. The trail keeps its width and the name gives way, down
   to a few characters and an ellipsis. */
.documents-ribbon .documents-ribbon__top .document-nav > * {
  white-space: nowrap;
}

.documents-ribbon .documents-ribbon__top .document-nav__root {
  flex: 0 0 auto;
}

.documents-ribbon .documents-ribbon__top .document-nav__doc {
  flex: 0 1 auto;
  min-width: 6ch;
}

.viewer-tools {
  display: flex;
  align-items: center;
  gap: 10px;
}

.viewer.is-pannable {
  cursor: grab;
}

.viewer.is-panning {
  cursor: grabbing;
  user-select: none;
}

.viewer.is-active {
  border-color: var(--accent);
  box-shadow: var(--shadow-lg);
}

.pdf-stage {
  position: relative;
  width: 100%;
  display: inline-block;
  flex: 0 0 auto;
  padding: 16px;
}

.pdf-content {
  position: relative;
  transform-origin: top left;
}

.pdf-pages {
  display: grid;
  gap: 0;
}

.pdf-page {
  /* Ground, radius and shadow are set with the rest of the design system near
     the end of this file. These two are not, and the annotation layer is
     absolutely positioned against them. */
  position: relative;
  overflow: hidden;
}

.pdf-page-sep {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.pdf-page-sep::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--border);
}

.pdf-page-sep__label {
  position: relative;
  z-index: 1;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
}

.viewer-close {
  background: var(--panel);
  color: var(--muted);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-sm);
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  padding: 0;
  font-size: 1rem;
  transition: all var(--transition);
}

.viewer-close:hover {
  background: var(--bg-subtle);
  color: var(--ink);
}

#undo-btn {
  background: var(--panel);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-sm);
  /* A block with an inline icon and a word beside it, and nothing holding
     the pair together: on a phone the icon took the first line and Undo
     took the second, both clipped by the 32px below. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--radius-sm);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
}

#undo-btn:hover,
#save-btn:hover {
  background: var(--bg-subtle);
  color: var(--ink);
}

#save-btn {
  background: var(--panel);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-sm);
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  cursor: pointer;
  transition: all var(--transition);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ─── Zoom Controls ─── */

.zoom-controls {
  display: inline-flex;
  flex-wrap: nowrap;
  white-space: nowrap;
  align-items: center;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 4px;
  box-shadow: var(--shadow-sm);
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--ink-secondary);
}

.zoom-controls button {
  background: transparent;
  color: var(--ink-secondary);
  border: none;
  padding: 4px 8px;
  border-radius: 6px;
  box-shadow: none;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  /* A lone sign is a narrow target, so the button is squared off to stay
     pressable, and nothing in here is allowed to break onto a second line.
     A thumb needs more than this; see the touch block at the end of the file. */
  min-width: 34px;
  min-height: 30px;
  display: inline-grid;
  place-items: center;
  white-space: nowrap;
}

.zoom-controls button:hover {
  background: var(--accent-subtle);
  color: var(--ds-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.pdf-page canvas {
  width: 100%;
  height: auto;
  display: block;
}

/* ─── Annotation Layer ─── */

.annotation-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.annotation-field {
  position: absolute;
  padding: 4px 8px;
  border: 1.5px solid var(--signer-color, var(--signer-fallback));
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.92);
  font-size: 0.95rem;
  color: #000000;
  pointer-events: auto;
  cursor: move;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition);
}

.annotation-field[data-signer-badge]::before {
  content: attr(data-signer-badge);
  position: absolute;
  left: 0;
  top: -6px;
  transform: translateY(-100%);
  background: var(--signer-color, var(--signer-fallback));
  color: var(--ds-paper);
  border-radius: 999px;
  padding: 2px 7px;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.1;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--shadow-sm);
}

.annotation-field:hover {
  box-shadow: var(--shadow);
}

.annotation-field.is-mark {
  font-weight: 700;
  font-size: 1.1rem;
}

.annotation-field[contenteditable='true'] {
  min-width: 120px;
  outline: none;
  cursor: text;
}

.annotation-signature {
  padding: 4px;
  background: rgba(255, 255, 255, 0.6);
  border: 1.5px dashed var(--signer-color, var(--signer-fallback));
  cursor: move;
}

.annotation-signature img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

.annotation-stamp {
  padding: 4px;
  background: rgba(255, 255, 255, 0.65);
  border: 1.5px solid var(--signer-color, var(--signer-fallback));
  cursor: move;
}

.annotation-stamp img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

.annotation-signature.is-final {
  border: none;
  background: transparent;
  padding: 0;
}

.annotation-field.is-final {
  border: 1.5px solid transparent;
  background: transparent;
  padding: 4px 8px;
  outline: none;
  box-shadow: none;
  cursor: move;
}

.annotation-field.is-final:hover {
  border-color: var(--signer-color, var(--signer-fallback));
  background: rgba(255, 255, 255, 0.5);
}

.annotation-field.is-pending-empty {
  border: 1.5px dashed var(--signer-color, var(--signer-fallback));
  background: rgba(255, 255, 255, 0.72);
  box-shadow: var(--shadow-sm);
}

.annotation-field.is-pending-empty:hover {
  border-style: solid;
  background: rgba(255, 255, 255, 0.82);
}

.annotation-signature.is-final:hover {
  border: 1.5px dashed var(--signer-color, var(--signer-fallback));
  background: rgba(255, 255, 255, 0.4);
}

.annotation-stamp.is-final {
  border: none;
  background: transparent;
  padding: 0;
}

.annotation-stamp.is-final:hover {
  border: 1.5px solid var(--signer-color, var(--signer-fallback));
  background: rgba(255, 255, 255, 0.4);
}

/* ─── Field Controls ─── */

.field-controls {
  position: absolute;
  top: 0;
  right: -10px;
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 6px;
  padding: 4px;
  border-radius: var(--radius-sm);
  background: var(--panel);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
  transform: translateY(-100%);
  white-space: nowrap;
}

.annotation-field:hover .field-controls {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(-100%);
}

.annotation-field .field-controls:hover {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(-100%);
}

.field-select {
  position: relative;
}

.field-select select {
  appearance: none;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 4px 22px 4px 8px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  line-height: 1.1;
}

.field-select::after {
  content: '▾';
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.65rem;
  color: var(--muted);
  pointer-events: none;
}

.field-select--font select {
  min-width: 140px;
}

.field-select--size select {
  width: 64px;
  text-align: center;
}

.field-color-toggle {
  position: relative;
  width: 34px;
  height: 26px;
  padding: 0;
  font-weight: 700;
  font-size: 0.85rem;
}

.field-color-toggle::before {
  content: '▾';
  position: absolute;
  right: 4px;
  top: 4px;
  font-size: 0.55rem;
  color: var(--muted);
}

.field-color-toggle::after {
  content: '';
  position: absolute;
  left: 6px;
  right: 10px;
  bottom: 4px;
  height: 3px;
  border-radius: 3px;
  background: var(--color, #000000);
}

.field-color-palette {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 8px;
  box-shadow: var(--shadow-lg);
  display: none;
  gap: 6px;
  width: max-content;
  z-index: 5;
}

.annotation-field.is-color-open .field-color-palette {
  display: grid;
}

.field-resize-handle {
  position: absolute;
  right: -6px;
  bottom: -6px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--signer-color, var(--signer-fallback));
  border: 2px solid var(--ds-paper);
  box-shadow: var(--shadow-sm);
  opacity: 0;
  cursor: nwse-resize;
  transition: opacity var(--transition), transform var(--transition);
  pointer-events: auto;
}

.annotation-field:hover .field-resize-handle {
  opacity: 1;
  transform: scale(1.05);
}

.field-control-btn {
  border: none;
  background: transparent;
  color: var(--ink-secondary);
  font-size: 0.8rem;
  font-weight: 700;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  cursor: pointer;
  pointer-events: auto;
  transition: all var(--transition);
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.field-color {
  display: none;
}

.field-control-btn:hover {
  background: var(--accent-subtle);
  color: var(--ds-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.field-control-done {
  color: var(--ds-success);
}

.field-control-done:hover {
  background: rgba(27, 138, 75, 0.12);
  color: var(--ds-success-ink);
}

.field-control-remove {
  margin-left: auto;
}

/* ─── Context Menu ─── */

.context-menu {
  position: fixed;
  z-index: 20;
  display: none;
  min-width: 200px;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xl);
  padding: 6px;
  animation: menu-in 0.12s ease-out;
}

.context-menu__select {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-secondary);
}

.context-menu__select select {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 4px 8px;
  font-family: inherit;
  font-size: 0.8rem;
  background: var(--panel);
  color: var(--ink);
}

.context-menu__group {
  display: grid;
  gap: 2px;
  padding: 4px 0;
}

.context-menu__group + .context-menu__group {
  border-top: 1px solid var(--border);
  margin-top: 4px;
  padding-top: 8px;
}

.context-menu button {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  text-align: left;
  background: transparent;
  color: var(--ink);
  box-shadow: none;
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-size: 0.9rem;
  font-weight: 500;
}

.context-menu button:hover {
  background: var(--accent-subtle);
  color: var(--accent-hover);
}

/* ─── Placeholder / Empty State ─── */

.placeholder {
  height: 100%;
  min-height: 420px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  color: var(--muted);
  font-size: 0.95rem;
  width: 100%;
  text-align: center;
  padding: 40px 20px;
}

.placeholder button {
  padding: 12px 28px;
  font-size: 0.95rem;
}

.placeholder-or,
.placeholder-drag {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.placeholder-or {
  margin-top: 2px;
}

.placeholder-inline {
  margin: 0;
}

.placeholder-icon {
  width: 64px;
  height: 64px;
  opacity: 0.4;
  margin-bottom: 4px;
}

/* ─── Modals ─── */

.modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(4px);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 30;
}

.modal-content {
  background: var(--panel);
  border-radius: var(--radius-xl);
  padding: 24px;
  width: min(520px, 100%);
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--border);
  display: grid;
  gap: 16px;
  animation: modal-in 0.2s ease-out;
}

@keyframes modal-in {
  from { opacity: 0; transform: scale(0.96) translateY(8px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}

.modal-content--wide {
  width: min(680px, 100%);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.modal-header h3 {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
}

.modal-status {
  color: var(--muted);
  font-size: 0.9rem;
}

.modal-actions {
  display: flex;
  gap: 8px;
  padding-top: 4px;
}

.modal-actions--stack {
  flex-direction: column;
}

.modal-actions--stack button {
  width: 100%;
  justify-content: flex-start;
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}

.pricing-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  background: var(--panel);
  display: grid;
  gap: 8px;
}

.pricing-card h4 {
  margin: 0;
  font-size: 0.95rem;
}

.pricing-price {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--ink);
}

.pricing-price span {
  font-size: 0.8rem;
  color: var(--muted);
  font-weight: 500;
}

.pricing-note {
  margin: 12px 0 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.payment-summary {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-subtle);
  padding: 10px 12px;
}

.payment-summary__plan {
  margin: 0 0 4px;
  color: var(--ink-secondary);
  font-size: 0.86rem;
  font-weight: 600;
}

.payment-summary__price {
  margin: 0;
  color: var(--ink);
  font-size: 1.06rem;
  font-weight: 800;
}

.payment-summary__price span:last-child {
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 500;
}

.payment-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
}

.payment-field {
  display: grid;
  gap: 4px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--muted);
}

.payment-field--wide {
  grid-column: 1 / -1;
}

.payment-field input {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 9px 10px;
  font-size: 0.9rem;
  font-family: inherit;
  color: var(--ink);
  background: var(--panel);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.payment-field input:focus {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

.payment-field input.is-invalid {
  border-color: var(--ds-error);
  outline: 2px solid var(--ds-error);
  outline-offset: 1px;
}

.payment-status {
  margin: 0;
  font-size: 0.84rem;
  color: var(--accent-hover);
  font-weight: 600;
}

.payment-status.is-error {
  color: var(--ds-error);
}

.payment-test-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel);
  padding: 10px;
  display: grid;
  gap: 4px;
}

.payment-test-card h4 {
  margin: 0 0 2px;
  font-size: 0.82rem;
  color: var(--ink);
}

.payment-test-card p {
  margin: 0;
  font-size: 0.8rem;
  color: var(--ink-secondary);
}

.modal-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 6px 2px 0;
}

.option-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: var(--ink);
}

.option-toggle input {
  width: 16px;
  height: 16px;
}

.option-select {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--muted);
}

.option-select select {
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 4px 8px;
  font-size: 0.85rem;
  color: var(--ink);
}

/* ─── Date Picker ─── */

.modal-content input[type="date"] {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  padding: 10px 14px;
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  width: 100%;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.modal-content input[type="date"]:focus {
  border-color: var(--accent);
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

/* ─── Storage List ─── */

.storage-list {
  display: grid;
  gap: 8px;
  max-height: 360px;
  overflow: auto;
  padding-right: 6px;
}

.storage-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--panel);
  transition: all var(--transition);
}

.storage-item:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.storage-item h4 {
  margin: 0 0 4px;
  font-size: 0.95rem;
  font-weight: 600;
}

.storage-meta {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.storage-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.delivery-debug {
  position: fixed;
  right: 14px;
  bottom: 14px;
  width: min(420px, calc(100vw - 28px));
  max-height: min(42vh, 360px);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  display: grid;
  grid-template-rows: auto 1fr;
  overflow: hidden;
  z-index: 24;
}

.delivery-debug__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
}

.delivery-debug__head h3 {
  margin: 0;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--ink-secondary);
}

.delivery-debug__actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

#delivery-debug-clear,
#delivery-debug-copy {
  width: auto;
  box-shadow: none;
  background: var(--panel);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  font-size: 0.73rem;
  font-weight: 700;
}

#delivery-debug-clear:not(:disabled):hover,
#delivery-debug-copy:not(:disabled):hover {
  background: var(--accent-subtle);
  color: var(--accent-hover);
}

.delivery-debug__list {
  padding: 8px;
  display: grid;
  gap: 7px;
  align-content: start;
  overflow: auto;
}

.delivery-debug__empty {
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
}

.delivery-debug__item {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--ds-desk);
  padding: 7px 8px;
  display: grid;
  gap: 5px;
}

.delivery-debug__item.is-success {
  border-color: color-mix(in srgb, var(--ds-success) calc(0.4 * 100%), transparent);
}

.delivery-debug__item.is-error {
  border-color: rgba(220, 38, 38, 0.45);
}

.delivery-debug__item.is-pending {
  border-color: rgba(180, 83, 9, 0.45);
}

.delivery-debug__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.72rem;
  color: var(--muted);
}

.delivery-debug__badge {
  border-radius: 999px;
  padding: 1px 6px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  border: 1px solid transparent;
}

.delivery-debug__badge.is-success {
  background: color-mix(in srgb, var(--ds-success) calc(0.12 * 100%), transparent);
  color: var(--ds-success);
  border-color: color-mix(in srgb, var(--ds-success) calc(0.35 * 100%), transparent);
}

.delivery-debug__badge.is-error {
  background: rgba(220, 38, 38, 0.11);
  color: var(--ds-error);
  border-color: rgba(220, 38, 38, 0.35);
}

.delivery-debug__badge.is-pending {
  background: color-mix(in srgb, var(--ds-warning) 10%, var(--ds-paper));
  color: var(--ds-warning);
  border-color: rgba(180, 83, 9, 0.35);
}

.delivery-debug__recipient {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.delivery-debug__raw {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  font-size: 0.68rem;
  line-height: 1.35;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 6px;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--ink-secondary);
}

/* ─── Responsive ─── */

@media (max-width: 1080px) {
  .documents-screen {
    grid-template-columns: 1fr;
  }

  .documents-inbox {
    position: static;
    max-height: 360px;
    min-height: 0;
  }

  .workspace {
    grid-template-columns: 1fr;
  }

  .document-tools {
    position: static;
    max-height: none;
    overflow: visible;
    grid-template-rows: auto;
  }

  .document-tools__items {
    overflow: visible;
  }
}

@media (max-width: 720px) {
  .app__header {
    flex-wrap: wrap;
  }

  .documents-ribbon {
    flex-direction: column;
    align-items: stretch;
  }

  /* A row, not a block: the view controls sit at the end of it, and as
     block children they stacked underneath instead - a second line, which
     is the line this row exists to save. Never wraps, because the bar to
     their left folds into its ... menu rather than growing. */
  .documents-ribbon__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: nowrap;
    /* A flex item's floor is its content, so a row that does not wrap
       stretches past its column and then reports that wider width as
       the room available. The fold read 453px of room on a 390px phone
       and kept a button it had no space for. */
    min-width: 0;
  }

  .documents-ribbon__actions-main {
    display: flex;
    flex-wrap: nowrap;
    min-width: 0;
  }

  .documents-inbox__head-row {
    align-items: stretch;
    flex-direction: column;
  }

  .documents-inbox__controls {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
  }

  .payment-grid {
    grid-template-columns: 1fr;
  }

  .document-nav {
    width: 100%;
    justify-content: flex-start;
  }

  .plan-status {
    width: 100%;
    justify-content: center;
  }

  .header-actions {
    order: 4;
  }

  .app__header h1 {
    font-size: 1.1rem;
  }

  .app__header p {
    display: none;
  }

  .controls {
    flex-direction: column;
    align-items: stretch;
  }

  .auth-actions {
    flex-direction: column;
  }

  .signature-actions {
    flex-direction: column;
  }

  button,
  .file-input {
    justify-content: center;
    width: 100%;
  }
}

/* Consent to electronic records and signatures (ESIGN). Deliberately plain
   and readable: this is a legal disclosure, not marketing copy. */
.consent-accept {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-bottom: 12px;
  font-size: 14px;
  line-height: 1.45;
  cursor: pointer;
}

.consent-accept input {
  margin-top: 3px;
  flex: 0 0 auto;
}

/* =========================================================================
   Design system application — DESIGN.md
   Scoped to the surfaces where trust is won: the document, the signer view
   and the consent step. The editor keeps its existing styling for now; this
   is deliberately a partial migration, not a sweep through the whole file.
   ========================================================================= */

body {
  font-family: var(--ds-font-ui);
  background: var(--bg);
  color: var(--ds-ink);
}

h1, h2, h3,
.app-title,
.modal-header h3 {
  font-family: var(--ds-font-display);
  letter-spacing: -.015em;
}

/* The document is paper on a desk. This shadow is doing the thesis's work;
   do not reuse it on anything that is not the document. */
.pdf-page {
  background: var(--ds-paper);
  border-radius: var(--ds-radius-sm);
  box-shadow: var(--ds-lift-paper);
}

.viewer,
#pdf-pages {
  background: var(--ds-desk);
}

/* Hashes, envelope ids and ISO timestamps have to align in a column to be
   checkable at a glance. The only place mono earns its keep. */
.doc-hash,
.audit-time,
.envelope-id,
.cert-value {
  font-family: var(--ds-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: .78rem;
  word-break: break-all;
}

/* The reserved register: the product speaking about the document.
   Nothing outside this block may use --ds-accent or --ds-accent-wash. */
.insight-panel {
  background: var(--ds-accent-wash);
  border: 1px solid color-mix(in srgb, var(--ds-accent) 45%, transparent);
  border-radius: var(--ds-radius-md);
  padding: var(--ds-s-4);
}

.insight-panel__title {
  font-family: var(--ds-font-display);
  font-size: .95rem;
  color: var(--ds-accent-ink);
  margin: 0 0 var(--ds-s-2);
}

.insight-panel__disclaimer {
  font-size: .72rem;
  color: var(--ds-ink-mute);
  margin-top: var(--ds-s-3);
}

.insight-mark {
  background: var(--ds-accent);
  color: #3B2B02;
  padding: 0 3px;
  border-radius: 2px;
}

/* Consent to electronic records and signatures (ESIGN). Plain and readable:
   this is a legal disclosure, not marketing copy. */
.consent-disclosure {
  max-height: 46vh;
  overflow-y: auto;
  margin: 0 0 var(--ds-s-4);
  padding: var(--ds-s-3) var(--ds-s-4);
  border: 1px solid var(--ds-line);
  border-radius: var(--ds-radius-md);
  background: var(--ds-paper);
  font-family: var(--ds-font-ui);
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
  color: var(--ds-ink-soft);
}

.consent-accept {
  display: flex;
  gap: var(--ds-s-2);
  align-items: flex-start;
  margin-bottom: var(--ds-s-3);
  font-size: 14px;
  line-height: 1.45;
  cursor: pointer;
}

.consent-accept input {
  margin-top: 3px;
  flex: 0 0 auto;
}

/* Signer surface: calm, generous, mobile-first. No sender chrome. */
body.is-signing .documents-ribbon__main,
body.is-signing .documents-compress,
body.is-signing .documents-print {
  display: none;
}

body.is-signing .workspace {
  gap: var(--ds-s-5);
}

@media (max-width: 860px) {
  body.is-signing .workspace {
    grid-template-columns: 1fr;
  }
  body.is-signing .pdf-page {
    max-width: 100%;
  }
}

/* A field settling as it is completed. The one authored moment in the
   product, because it is the moment someone commits to something. */
.annotation-field {
  transition: border-color var(--ds-dur-short) var(--ds-ease-out),
              background-color var(--ds-dur-short) var(--ds-ease-out);
}

.annotation-field.is-final {
  border-style: solid;
  border-width: 1px;
  border-color: var(--ds-line-soft);
}

:focus-visible {
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

/* Consent actions follow DESIGN.md rather than the legacy button classes:
   one primary action per surface, in ink. Declining is a legitimate outcome
   but it is not the recommended one, so it must not be the loudest control. */
#consent-modal .modal-actions {
  display: flex;
  gap: var(--ds-s-3);
  justify-content: flex-end;
}

#consent-continue {
  background: var(--ds-ink);
  color: var(--ds-paper);
  border: 1px solid transparent;
  border-radius: var(--ds-radius-md);
  font-family: var(--ds-font-ui);
  font-weight: 600;
  padding: 10px 18px;
  cursor: pointer;
  transition: background var(--ds-dur-micro) var(--ds-ease-out);
}

#consent-continue:hover:not(:disabled) { background: #122039; }

#consent-continue:disabled {
  background: var(--ds-desk-sunk);
  color: var(--ds-ink-mute);
  cursor: not-allowed;
}

#consent-decline {
  background: transparent;
  color: var(--ds-ink);
  border: 1px solid var(--ds-line);
  border-radius: var(--ds-radius-md);
  font-family: var(--ds-font-ui);
  font-weight: 600;
  padding: 10px 18px;
  cursor: pointer;
}

#consent-decline:hover { background: var(--ds-desk-sunk); }

/* Guided signing bar. Pinned to the bottom so it stays reachable with a thumb
   while the document scrolls behind it. DESIGN.md: ink primary, one action. */
.signer-guide {
  position: fixed;
  left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--ds-s-3);
  padding: 10px 12px 10px 16px;
  background: var(--ds-paper);
  border: 1px solid var(--ds-line);
  border-radius: var(--ds-radius-full);
  box-shadow: var(--ds-lift-2);
  font-family: var(--ds-font-ui);
}

.signer-guide__progress {
  font-size: .82rem;
  color: var(--ds-ink-mute);
  white-space: nowrap;
}

.signer-guide__btn {
  appearance: none;
  border: 1px solid transparent;
  background: var(--ds-ink);
  color: var(--ds-paper);
  font: inherit;
  font-weight: 600;
  font-size: .9rem;
  /* 44px tall: the minimum reliable touch target on iOS. */
  min-height: 44px;
  padding: 0 20px;
  border-radius: var(--ds-radius-full);
  cursor: pointer;
}

.signer-guide__btn:hover { background: #122039; }
.signer-guide__btn:focus-visible { outline: 2px solid var(--ds-ink); outline-offset: 2px; }

/* The field being pointed at, so arriving somewhere mid-document is obvious. */
.annotation-field.is-guided {
  animation: guided-pulse 1.1s var(--ds-ease-out) 2;
}

@keyframes guided-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(27, 47, 87, 0); }
  50% { box-shadow: 0 0 0 6px rgba(27, 47, 87, .18); }
}

@media (prefers-reduced-motion: reduce) {
  .annotation-field.is-guided { animation: none; outline: 2px solid var(--ds-ink); }
}

/* Signer mode: nothing on screen that belongs to the sender. Every row of
   chrome removed is a row of contract the signer can actually see, which
   matters most on a phone. */
body.is-signing .documents-ribbon,
body.is-signing .documents-ribbon__main,
body.is-signing .documents-compress,
body.is-signing .documents-print,
body.is-signing #documents-download,
body.is-signing #menu-save-options {
  display: none !important;
}

@media (max-width: 860px) {
  /* The tool sidebar is sender-only; on a phone it pushes the document off
     the first screen entirely. */
  body.is-signing .document-tools__list,
  body.is-signing .signer-add {
    display: none;
  }

  body.is-signing .workspace {
    display: block;
    padding: 0;
  }

  body.is-signing .viewer {
    padding: 0;
  }

  /* Room for the guide bar so it never covers the last field. */
  body.is-signing #viewer-scroll {
    padding-bottom: 88px;
  }
}

/* The token reset near the top only reaches rules that use the tokens. These five
   chrome animations hardcode their own durations, and a media query adds no
   specificity - so this has to sit at the end of the file to outrank them. */
@media (prefers-reduced-motion: reduce) {
  .header-menu,
  .auth-panel,
  .signature-panel,
  .context-menu,
  .modal-content {
    animation-duration: 1ms;
    animation-timing-function: linear;
  }
}

/* A signer tabbing through the fields on the document is the product's primary
   task, on the surface DESIGN.md calls "operate under suspicion". These three
   suppressed the outline and never restored a ring. */
.annotation-field[contenteditable='true']:focus-visible,
.annotation-field.is-final:focus-visible,
.initials-auto-form input[type='text']:focus-visible {
  outline: 2px solid var(--ds-ink);
  outline-offset: 2px;
}

/* =========================================================================
   Mobile: one view at a time.

   Below 720px the old layout stacked every region vertically - the document
   list, then an empty 480px viewer, then the tools - so a phone showed about
   310px of chrome and a half-screen empty box before any content. A phone has
   room for one thing at a time, so it shows one thing at a time.

   The switch already exists: app.js:5802 toggles .documents-screen--focused
   when a PDF is open and the list view is not active. Desktop uses it to widen
   the workspace; here it picks WHICH view you are looking at.

   This block sits at the end of the file on purpose. A media query adds no
   specificity, so an override declared above the rules it overrides loses.
   ========================================================================= */
@media (max-width: 720px) {
  /* No document open: the list is the screen. Nothing gains from a 480px
     empty rectangle underneath it. */
  .documents-screen:not(.documents-screen--focused) .documents-main {
    display: none;
  }

  /* Document open: the document is the screen. The My Docs control in the
     header is the way back. */
  .documents-screen--focused .documents-inbox {
    display: none;
  }

  .documents-screen {
    gap: 0;
  }

  .documents-inbox {
    max-height: none;
    min-height: calc(100svh - 160px);
  }

  /* The panel head was 119px of chrome over 83px of content. One line. */
  .documents-inbox__head {
    padding-bottom: var(--ds-s-2);
  }

  .documents-inbox__head-row {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-s-2);
  }

  .documents-inbox__head h2 {
    font-size: 1.05rem;
  }

  /* One primary action per surface. When the empty state renders its own
     Add Doc, the one in the head is a second route to the same place, 100px
     away and styled differently. */
  .documents-inbox:has(.documents-list__empty-wrap) .documents-upload {
    display: none;
  }

  /* The empty state says it better and says it once. */
  .documents-inbox:has(.documents-list__empty-wrap) #documents-summary {
    display: none;
  }

  /* An empty strip between two panels is noise with a height. */
  .documents-ribbon:empty,
  .documents-ribbon__left:empty {
    display: none;
  }

  /* The header was two rows and 112px, 13% of the viewport, before content.
     The breadcrumb only says something once a document is open, where it is
     also the way back; until then it repeats the heading below it. */
  .app__header {
    flex-wrap: nowrap;
    align-items: center;
    padding-top: var(--ds-s-2);
    padding-bottom: var(--ds-s-2);
  }

  .app__title {
    flex-direction: row;
    align-items: center;
    gap: var(--ds-s-3);
  }


  /* Thumb reach: the primary action on the empty state sits where a thumb
     rests, not stacked in the middle of the page. 44px minimum target. */
  .documents-list__upload {
    width: 100%;
    min-height: 48px;
  }
  /* The header was wrapping its own actions onto a second row. Brand left,
     actions right, one row. */
  .header-actions {
    flex-wrap: nowrap;
    flex: 0 0 auto;
  }

  .app__title {
    min-width: 0;
    flex: 1 1 auto;
  }

  .app__title h1 {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .documents-inbox__head h2 {
    white-space: nowrap;
  }

  /* An empty list is still a whole screen, so the message and its action sit
     in the optical centre rather than pinned under the heading with 500px of
     nothing below them. */
  .documents-inbox:has(.documents-list__empty-wrap) .documents-list {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 1 1 auto;
    padding-bottom: 12vh;
  }

  .documents-list__empty-wrap {
    flex-direction: column;
    align-items: stretch;
    padding: var(--ds-s-4);
  }
}

/* The empty state is a message and its action in one block, per DESIGN.md.
   Shown at every width: an empty list reads the same on a desktop. */
.documents-list__empty-title {
  font-family: var(--ds-font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ds-ink);
  margin: 0 0 var(--ds-s-1);
}

.documents-list__empty-body {
  font-size: 0.88rem;
  color: var(--ds-ink-mute);
  margin: 0 0 var(--ds-s-4);
  max-width: 34ch;
}

/* =========================================================================
   Header: menu left, brand centred, account right.
   Menu: grouped into sections with a hairline between them.
   ========================================================================= */

/* The brand is the centre of the header at every width, so it is positioned
   against the header rather than ordered between two piles of controls whose
   widths differ and would shift it off-centre. */
.app__header {
  position: sticky;
  justify-content: flex-start;
}

.app__title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  flex-direction: column;
  align-items: center;
  gap: 2px;
  pointer-events: none;
  text-align: center;
}

.app__title .brand {
  pointer-events: auto;
}

/* The menu button leads, on the left, where a thumb and a cursor both expect
   a menu to be. */
.header-actions {
  display: contents;
}

#menu-toggle {
  order: -1;
  margin-right: auto;
}

.header-actions > :not(#menu-toggle):not(.header-menu) {
  order: 1;
  flex: 0 0 auto;
}

/* display:contents promoted these to direct flex children of the header, where
   they stretch unless told not to. */
#menu-toggle {
  flex: 0 0 auto;
}

/* A pre-existing `button { width: 100% }` under 720px sized buttons for the
   stacked column layout they used to sit in. Header buttons are inline now, so
   it has to stop at the header. Specificity beats it in or out of a query. */
.app__header button {
  width: auto;
}

/* ...except the icon buttons, which are square by definition and were sized at
   .icon-button:36px before `width: auto` above overrode them. */
.app__header .icon-button {
  width: 36px;
}

/* The dropdown is positioned against the header now that its old relative
   parent is display:contents, and it opens under the button on the left. */
.header-menu {
  left: var(--ds-s-5);
  right: auto;
  top: calc(100% + 8px);
}

/* ─── Menu sections ─── */

.menu-section + .menu-section {
  margin-top: var(--ds-s-2);
  padding-top: var(--ds-s-2);
  border-top: 1px solid var(--ds-line);
}

/* The menu lives inside .app__header, where a pre-existing mobile rule hides
   every <p>. These labels are paragraphs, so they need the specificity back. */
.app__header .menu-section__label,
.menu-section__label {
  display: block;
  margin: 0 0 2px;
  padding: 0 10px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ds-ink-mute);
}

/* A section whose every item is hidden would otherwise show a heading and a
   divider over nothing. Most of these items are toggled by document state. */
.menu-section:not(:has(.menu-item:not([hidden]))) {
  display: none;
}

/* The ribbon holds the document actions, all of which are hidden until a
   document is open. With none open it was an empty 76px box at every width,
   so it now goes when it has nothing to show. :empty does not apply - the
   buttons are present in the DOM, just hidden. */
.documents-ribbon:not(:has(button:not([hidden]))) {
  display: none;
}

/* Two file inputs, both hidden, and nothing else: zero height but still a
   row of the page grid, which spent a 20px gap on it above every screen. */
.controls:not(:has(> *:not([hidden]))) {
  display: none;
}

/* The document navigator moved out of the header and into the ribbon, directly
   above the document's own actions: it names the thing those buttons act on, so
   it belongs beside them rather than under the brand. The ribbon already hides
   itself when no document is open, which is exactly when the breadcrumb has
   nothing to say. */
.documents-ribbon {
  flex-direction: column;
  align-items: stretch;
  gap: var(--ds-s-2);
}

.documents-ribbon .document-nav {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--ds-ink-mute);
  min-width: 0;
}

/* The filename is the one part worth reading at a glance. */
.documents-ribbon .document-nav__doc {
  color: var(--ds-ink);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.documents-ribbon .document-nav__size {
  font-family: var(--ds-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
  color: var(--ds-ink-mute);
}

/* The ribbon now carries the breadcrumb too, so it shows whenever either the
   breadcrumb has a document to name or an action is available. */
.documents-ribbon:not(:has(button:not([hidden]))):not(:has(.document-nav__doc:not([hidden]))) {
  display: none;
}

/* Icons. One size, one weight, inheriting the colour of whatever they sit in,
   so a disabled control's icon dims with its label and an ink button's icon
   goes to paper with its text. Emoji could do none of that. */
.icon {
  width: 1em;
  height: 1em;
  flex: none;
  vertical-align: -0.125em;
  color: currentColor;
}

/* In the menu and ribbon the icon reads as a quiet marker beside the label,
   not as a second thing competing with it. */
.menu-icon .icon,
.menu-item > .icon,
.documents-ribbon button .icon,
.documents-ribbon__actions-main .icon {
  width: 1.05em;
  height: 1.05em;
  opacity: 0.7;
}

/* The icon-only buttons carry no label, so their icon is the whole control. */
.icon-button .icon {
  width: 18px;
  height: 18px;
  opacity: 1;
}

/* =========================================================================
   Enabled controls should look pressable.

   The ribbon and inbox buttons were desk-sunk grey on a desk panel with
   muted text and no border: the exact treatment this stylesheet uses for
   DISABLED. Contrast measured fine at 7.4:1, so nothing failed a check;
   they simply read as inert. DESIGN.md already describes the answer - a
   ghost button is paper with a line border and ink text, and disabled is
   40% opacity - so enabled and disabled stop sharing a look.
   ========================================================================= */
.documents-ribbon button,
.documents-inbox__controls button {
  background: var(--ds-paper);
  color: var(--ds-ink);
  border: 1px solid var(--ds-line);
  box-shadow: var(--ds-lift-1);
}

.documents-ribbon button:hover:not(:disabled),
.documents-inbox__controls button:hover:not(:disabled) {
  background: var(--ds-desk-sunk);
  border-color: var(--ds-ink-mute);
  /* The earlier hover rule (same specificity, so it still applies) sets
     color: var(--ds-paper) for a dark hover background that this rule
     replaced with a light one. Without restating the colour the label
     renders paper on #E7EAF0: about 1.1:1, which is invisible.
     A light background takes dark text. */
  color: var(--ds-ink);
}

.documents-ribbon button:active:not(:disabled),
.documents-inbox__controls button:active:not(:disabled) {
  color: var(--ds-ink);
  background: var(--ds-desk-sunk);
  box-shadow: none;
  transform: translateY(1px);
}

/* The icon travels with the label's colour, so it dims on disable by itself. */
.documents-ribbon button .icon,
.documents-inbox__controls button .icon {
  opacity: 0.85;
}

/* One treatment for every disabled control, and it is unmistakably not the
   enabled one. DESIGN.md: 40% opacity, no pointer events. */
.documents-ribbon button:disabled,
.documents-inbox__controls button:disabled,
button:disabled {
  background: var(--ds-desk);
  color: var(--ds-ink-mute);
  border-color: var(--ds-line-soft);
  box-shadow: none;
  opacity: 0.45;
  cursor: not-allowed;
}

/* The signed-in identity is the account the document will be sent from, so it
   shows the address, not a display name that may be anything. */
.user-badge {
  min-width: 0;
}

.user-badge #user-name {
  font-family: var(--ds-font-mono);
  font-size: 0.78rem;
  color: var(--ds-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 22ch;
  display: inline-block;
  vertical-align: bottom;
}

/* ─── Document bar: one primary, the rest secondary ──────────────────────────
   Spec: docs/specs/2026-10-09-document-ux.md

   These sit at the end of the file on purpose. The generic
   `.documents-ribbon button` rules above have the same specificity, so an
   earlier declaration would lose to them and the primary would render as
   another grey button. */
.documents-ribbon button.ribbon-primary {
  background: var(--ds-ink);
  color: var(--ds-paper);
  border: 1px solid var(--ds-ink);
  box-shadow: var(--ds-lift-1);
  font-weight: 600;
}

.documents-ribbon button.ribbon-primary:not(:disabled):hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--ds-paper);
}

.documents-ribbon button.ribbon-primary .icon {
  opacity: 1;
}

/* One label is printed, never both. */
.ribbon-primary__label--short {
  display: none;
}

/* The ink button gives way before the row does.
   The actions row cannot wrap - the line it would take is the line the row
   exists to save - and the view controls beside it are `flex: 0 0 auto`, so
   nothing on the right can yield. That leaves the widest thing on the left:
   "Send for signature" is 187px of a 390px screen, and carrying it pushed the
   ... toggle 34px underneath the Zoom out button. The short form is a prefix
   of the full one, and the full one stays in aria-label at every width. */
@media (max-width: 430px) {
  .ribbon-primary__label--full {
    display: none;
  }

  .ribbon-primary__label--short {
    display: inline;
  }
}

/* Narrower still and the icon says it alone: at 320px even a short label
   leaves the toggle sitting on the zoom controls. */
@media (max-width: 380px) {
  .documents-ribbon button.ribbon-primary .ribbon-primary__label {
    display: none;
  }

  .documents-ribbon button.ribbon-primary {
    /* Square, like the ... toggle it now sits beside, rather than a wide
       button with one glyph adrift in the middle of it. The height comes
       from the row: zeroing the padding without it collapses the button
       onto its icon, a 17px ink dot beside 41px neighbours - the same stub
       the toggle above carries a comment about. */
    align-self: stretch;
    aspect-ratio: 1;
    width: auto;
    min-height: 40px;
    padding: 0;
    display: inline-grid;
    place-items: center;
  }
}

.documents-ribbon button.ribbon-primary:disabled {
  background: var(--ds-ink);
  border-color: var(--ds-ink);
  color: var(--ds-paper);
  opacity: 0.45;
}

/* Rare or destructive actions. Reachable in two clicks, loud in none. */
.ribbon-overflow {
  position: relative;
  margin-left: auto;
  /* The toggle is a button among buttons. Stretching the wrapper to the
     row's cross size lets the toggle match whatever the labelled buttons
     measure, rather than a number copied off them that drifts the next time
     their padding or type size changes. */
  align-self: stretch;
}

.documents-ribbon button.ribbon-overflow__toggle {
  /* Square, from the row's own height: zeroing the padding had collapsed it
     to the height of its icon, a 17px stub beside 41px neighbours. */
  height: 100%;
  width: auto;
  aspect-ratio: 1;
  /* A floor for the case where it is the only thing left on the bar and has
     no taller neighbour to take its height from. */
  min-height: 36px;
  padding: 0;
  display: inline-grid;
  place-items: center;
}

.ribbon-overflow__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 40;
  min-width: 190px;
  padding: 6px;
  display: grid;
  gap: 2px;
  background: var(--ds-paper);
  border: 1px solid var(--ds-line);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-lift-2, 0 8px 24px rgba(27, 47, 87, 0.12));
}

.documents-ribbon .ribbon-overflow__menu button {
  width: 100%;
  justify-content: flex-start;
  text-align: left;
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}

.documents-ribbon .ribbon-overflow__menu button:not(:disabled):hover {
  background: var(--ds-desk-sunk);
  color: var(--ds-ink);
  border-color: var(--ds-line);
  transform: none;
  box-shadow: none;
}

/* Destructive, and it reads that way only once you are already in the menu. */
.documents-ribbon .ribbon-overflow__menu #documents-revoke-route:not(:disabled):hover {
  background: var(--ds-error-wash, #FCEFEE);
  color: var(--ds-error);
  border-color: rgba(180, 35, 24, 0.3);
}

/* ─── Field rail: name the groups that were already there ─────────────────── */
.tools-group__label {
  margin: 0 0 6px;
  padding: 0 4px;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ds-ink-mute);
}

.tools-group__label:not(:first-child),
.tools-group + .tools-group__label {
  margin-top: 14px;
}

/* ─── My Documents: groups, and one primary that creates something ───────── */
.documents-list__section + .documents-list__section {
  margin-top: 20px;
}

/* Needs-you rows sit on paper: these are the ones with your name on them.
   Scoped away from :hover, because this has the same specificity as
   .document-row:hover and comes later, so without :not() it would keep the
   background light while the hover rules set the text to paper. */
.documents-list__section--needs-you .document-row:not(:hover) {
  background: var(--ds-paper);
}

.documents-inbox__controls button.inbox-primary {
  background: var(--ds-ink);
  color: var(--ds-paper);
  border: 1px solid var(--ds-ink);
  box-shadow: var(--ds-lift-1);
  font-weight: 600;
}

.documents-inbox__controls button.inbox-primary:not(:disabled):hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--ds-paper);
}

.documents-inbox__controls button.inbox-primary .icon {
  opacity: 1;
}



/* ─── No document open: the list gets the window ─────────────────────────────
   The right pane holds a document. With none open it was an empty box taking
   three fifths of the screen while the list was squeezed into a column. */
.documents-screen.documents-screen--empty {
  grid-template-columns: minmax(0, 1fr);
}

.documents-screen--empty .documents-main {
  display: none;
}

/* ─── The drag ghost ─────────────────────────────────────────────────────────
   A finger covers the thing it is pointing at, so a touch drag with no ghost
   is aiming blind. This follows the finger slightly above it, where it can
   actually be seen. */
.tool-ghost {
  position: fixed;
  z-index: 60;
  transform: translate(-50%, -140%);
  padding: 7px 12px;
  border-radius: var(--ds-radius-md);
  background: var(--ds-ink);
  color: var(--ds-paper);
  font-family: var(--ds-font-ui);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--ds-lift-2);
  opacity: 0.95;
}

.tool-ghost--over {
  background: var(--ds-success);
}

/* A tool must not scroll the drawer when the gesture is a drag. */
.tool-item {
  touch-action: none;
}

/* ─── Portrait: document under the ribbon, tools in a drawer below ───────────
   Authoring on a phone used to be impossible, not merely awkward: placement
   was HTML5 drag-and-drop, which touch does not implement, so every tool in
   the rail was inert. With pointer-based placement it works, and the layout
   follows: ribbon, then the document, then the tools within thumb reach.

   End of file on purpose. A media query adds no specificity, so this has to
   come after the rules it overrides. */
/* Portrait, not just phone-width. A tablet held upright is 768 or 820 CSS px,
   which sailed past a 720px breakpoint and got the desktop rail: an 814px tall
   block of tools stacked above the document, which is the layout this replaced.
   Orientation is the thing being responded to, so orientation is in the query. */
@media (max-width: 720px), (orientation: portrait) and (max-width: 1100px) {
  .documents-screen--focused .workspace,
  .documents-screen--focused .workspace.workspace--no-tools {
    display: flex;
    flex-direction: column;
    gap: 0;
  }

  /* The document comes first. The drawer is docked, so it is last whatever
     the source order says. */
  .documents-screen--focused .workspace {
    /* One number for the drawer's height and the document's clearance, so
       they cannot drift apart and leave the last clause under the drawer. */
    --drawer-h: 258px;
  }

  .documents-screen--focused .viewer {
    order: 1;
    padding-bottom: calc(var(--drawer-h) + 12px + env(safe-area-inset-bottom));
  }

  .documents-screen--focused .document-tools {
    order: 2;
    position: fixed;
    /* The base rule is sticky with top: 82px. That top survives the switch to
       fixed, and with both offsets set the top wins, which pinned the drawer
       under the header instead of docking it. */
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 25;
    margin: 0;
    max-height: var(--drawer-h);
    overflow-y: auto;
    border: 0;
    border-top: 1px solid var(--ds-line);
    border-radius: 0;
    padding: 8px 12px calc(8px + env(safe-area-inset-bottom));
    background: var(--ds-paper);
    box-shadow: 0 -2px 4px rgba(27, 47, 87, 0.05), 0 -8px 20px rgba(27, 47, 87, 0.06);
    display: block;
  }

  /* The signer picker belongs to authoring, but it does not belong in a
     drawer that has to stay short. */
  .documents-screen--focused .document-tools__top {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 6px;
  }

  /* The signer picker is context, not an action: it should not cost as much
     height as a whole group of fields. */
  /* Add signer is already in the document bar above. In a drawer this short,
     a duplicate costs a row that a group of fields needs more. Scoped to the
     drawer: the + in the signer bar wears the same class and is the only way
     to add a signer there. */
  .documents-screen--focused .document-tools .menu-add-signer {
    display: none;
  }

  /* The signer picker and the hint share a line: the picker says who the
     next field belongs to, the hint says what to do with it. */
  .documents-screen--focused .document-tools__top {
    margin-bottom: 0;
  }

  .documents-screen--focused .tools-group__label {
    margin: 4px 0 3px;
    font-size: 0.6rem;
  }

  /* Each group scrolls sideways on its own, so twelve tools fit in three
     short rows instead of a wall. */
  .documents-screen--focused .tools-group--inline {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
  }

  .documents-screen--focused .tools-group--inline::-webkit-scrollbar {
    display: none;
  }

  .documents-screen--focused .tool-item {
    /* The base rule is width: 100%, which made every chip claim its own row
       and turned a sideways-scrolling strip into a vertical list. */
    width: auto;
    flex: 0 0 auto;
    white-space: nowrap;
    /* 36px is under the 44px touch floor on purpose: the whole chip row is
       the target and the rows are spaced, and three groups plus a signer
       picker have to fit above the fold of a phone. It is the floor the rest
       of the phone UI is held to - see tests/tap-targets.test.mjs. */
    min-height: 36px;
    padding: 6px 11px;
    font-size: 0.82rem;
    border: 1px solid var(--ds-line);
    border-radius: var(--ds-radius-md);
    background: var(--ds-desk);
  }
}

/* ─── The menu is a panel, not a dropdown ────────────────────────────────────
   A dropdown anchored to the hamburger put four sections and a dozen actions
   in a 220px box hanging off the corner. It slides in from the right edge
   instead, full height, at the width of the documents column, so the sections
   have room to read as sections.

   End of file: the earlier .header-menu rules are plain class selectors, and a
   later rule of equal specificity is what overrides them. */
.header-menu {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: auto;
  width: min(380px, 100vw);
  max-height: none;
  margin: 0;
  padding: var(--ds-s-4);
  border: 0;
  border-left: 1px solid var(--ds-line);
  border-radius: 0;
  background: var(--ds-paper);
  box-shadow: -8px 0 28px rgba(27, 47, 87, 0.14);
  display: flex;
  flex-direction: column;
  gap: var(--ds-s-2);
  overflow-y: auto;
  z-index: 50;
  animation: menu-slide-in var(--ds-dur-base, 0.22s) var(--ds-ease-out, ease-out);
}

@keyframes menu-slide-in {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}

/* Dims the page so the panel reads as a layer over it. Clicks pass through to
   the document listener that already closes the menu on an outside click, so
   this needs no element and no handler of its own. */
body.has-menu-open::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 49;
  background: rgba(27, 47, 87, 0.32);
  pointer-events: none;
  animation: menu-scrim-in var(--ds-dur-base, 0.22s) var(--ds-ease-out, ease-out);
}

@keyframes menu-scrim-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.header-menu__head {
  justify-content: flex-end;
  padding: 0 0 var(--ds-s-2);
}

/* Sections can breathe at this width. */
.header-menu .menu-section + .menu-section {
  margin-top: var(--ds-s-3);
  padding-top: var(--ds-s-3);
}

.header-menu .menu-item {
  min-height: 44px;
}

/* ─── The account you are signed in as, in the menu ──────────────────────────
   This used to sit in the header, right-aligned, against a title centred by
   absolute positioning: the two overlapped as soon as the address was long or
   the window narrow. It belongs beside the action that changes it anyway. */
.header-menu .user-badge {
  display: grid;
  gap: 1px;
  padding: 8px 10px 10px;
  min-width: 0;
}

.header-menu .user-badge__label {
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ds-ink-mute);
}

.header-menu .user-badge #user-name {
  font-family: var(--ds-font-mono);
  font-size: 0.78rem;
  color: var(--ds-ink);
  /* The header version truncated at 22ch because it had a title to avoid.
     In the panel there is room to wrap, and a half-shown address is worse
     than two lines: it is the account a signer sees the document come from,
     so you have to be able to read all of it. */
  max-width: none;
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
  display: block;
}

/* ─── One view at a time, on any portrait screen ─────────────────────────────
   The original rules for this are in the 720px block above and stop at phone
   width. A tablet in portrait has the same problem they solve: room for one
   thing, not two. */
@media (orientation: portrait) and (min-width: 721px) and (max-width: 1100px) {
  .documents-screen:not(.documents-screen--focused) .documents-main {
    display: none;
  }

  .documents-screen--focused .documents-inbox {
    display: none;
  }

  .documents-screen {
    gap: 0;
  }
}

/* ─── The drawer has to look like something you drag out of ──────────────────
   Docked at the bottom of a phone, the rail read as a list of labels. Nothing
   said the chips were draggable and nothing said where to drag them. */
.tools-drawer__hint {
  /* In the rail too, not only the drawer. A column of chips reads as a
     palette; nothing in it says a chip is something you pick up and drop
     on the page, and clicking one puts a field somewhere nobody chose. */
  display: block;
  margin: 0 0 8px;
  font-size: 0.74rem;
  color: var(--ds-ink-mute);
}

/* A recipient cannot add a field at all, and the hint above this one in
   their rail says exactly that. Specificity, not source order: the
   portrait rule below sets display on the same two-class footing. */
body.recipient-mode .document-tools .tools-drawer__hint {
  display: none;
}

@media (max-width: 720px), (orientation: portrait) and (max-width: 1100px) {
  .documents-screen--focused .tools-drawer__hint {
    display: block;
    margin: 0 0 6px;
    font-size: 0.74rem;
    color: var(--ds-ink-mute);
  }

  /* A grab bar: the shape every bottom sheet uses to say "this is a surface,
     and it has something in it". */
  .documents-screen--focused .document-tools::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    margin: 0 auto 10px;
    border-radius: var(--ds-radius-full);
    background: var(--ds-line);
  }

  .documents-screen--focused .tools-group__label {
    font-size: 0.66rem;
    color: var(--ds-ink-soft);
  }

  /* The three groups stand side by side, each its own column: label on top,
     chips under it. Stacked they cost three label rows and three chip rows and
     took a third of the screen off the document, and each group scrolled
     inside its own row, which showed one chip at a time. Now the whole strip
     scrolls sideways, so a group that does not fit is a swipe away.

     The grid reads the markup order label, group, label, group, label, group:
     two rows, filling down a column before starting the next. */
  .documents-screen--focused .document-tools__items {
    display: grid;
    grid-template-rows: auto auto;
    grid-auto-flow: column;
    grid-auto-columns: auto;
    align-items: start;
    gap: 2px 14px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    padding-bottom: 2px;
    /* The right edge fades, which is the only thing on screen that says there
       is another group past it. */
    mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
  }

  .documents-screen--focused .document-tools__items::-webkit-scrollbar {
    display: none;
  }

  /* A hairline between columns, so each label reads as the heading of what is
     under it rather than as one long row of words. */
  .documents-screen--focused .tools-group__label:not(:first-child),
  .documents-screen--focused .tools-group--inline:not(:first-of-type) {
    padding-left: 14px;
    margin-left: -7px;
    border-left: 1px solid var(--ds-line);
  }

  .documents-screen--focused .tools-group__label {
    margin: 0 0 4px;
    scroll-snap-align: start;
  }

  /* Scrolling belongs to the strip now, not to each group. */
  .documents-screen--focused .tools-group--inline {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow: visible;
  }

  /* Two rows instead of six: the drawer needs less of the screen. */
  .documents-screen--focused .workspace {
    --drawer-h: 186px;
  }

  /* Chips that read as objects, not as text: paper, a border, a lift, and the
     icon kept so the eye has something to aim at. */
  .documents-screen--focused .tool-item {
    gap: 7px;
    background: var(--ds-paper);
    border: 1px solid var(--ds-line);
    box-shadow: var(--ds-lift-1);
    color: var(--ds-ink);
    font-weight: 500;
  }

  .documents-screen--focused .tool-item:active {
    background: var(--ds-desk-sunk);
    transform: scale(0.97);
  }

  .documents-screen--focused .tool-item .tool-icon {
    color: var(--ds-ink-mute);
  }
}

/* A field is an object you move, so the browser does not get to treat a
   finger on one as a scroll. Without this the page scrolls out from under a
   drag on touch and the field never reaches where it was going. */
.annotation-field {
  touch-action: none;
}

/* While a field is being dragged, the page says it will take it. */
#pdf-stage.is-drop-target {
  outline: 2px dashed var(--ds-ink-mute);
  outline-offset: -4px;
}

/* ─── The signer bar: a second ribbon, only when asked for ───────────────────
   Signers used to be a permanent block at the top of the tool drawer. Most
   documents have one signer and nothing to choose between, so the block was
   paying rent on the most expensive space on a phone. It opens under the
   ribbon from Add signer, and it owns the whole job: + adds, x removes, and
   the chip switches whose field comes next. */
.signer-bar {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: var(--ds-s-2, 8px);
  margin: 0 0 var(--ds-s-2, 8px);
  padding: 10px 12px;
  border: 1px solid var(--ds-line);
  border-radius: var(--ds-radius-lg, 12px);
  background: var(--ds-paper);
  box-shadow: var(--ds-lift-1);
  animation: signer-bar-in var(--ds-dur-base, 0.18s) var(--ds-ease-out, ease-out);
}

.signer-bar[hidden] {
  display: none;
}

@keyframes signer-bar-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.signer-list--bar {
  /* One line, always. Four signers on a phone wrapped to four rows and left
     the + stranded on a fifth, which turned a strip under the ribbon into a
     block taller than the ribbon. Past the edge of the screen they scroll. */
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: nowrap;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  /* Says there is another signer past the edge. */
  mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
}

.signer-list--bar::-webkit-scrollbar {
  display: none;
}

.signer-list--bar .signer-pill {
  scroll-snap-align: start;
}

/* Chips side by side, each one a target: tap to switch, x to remove. */
.signer-list--bar .signer-pill {
  /* Sized by its name, never squeezed: a shrunk chip clipped the name and
     left a number and an x, which names nobody. The row wraps instead. */
  flex: 0 0 auto;
  width: auto;
  align-items: center;
  min-height: 34px;
}

/* The base chip is built for a full-width sidebar row, where min-width: 0 and
   flex-basis 0 let a long name ellipsis instead of stretching the row. In a
   chip that sizes to its own content those two collapse the name to a few
   pixels and leave a number and an x, which names nobody. Here the name sets
   the width and the row wraps. */
.signer-list--bar .signer-pill__content {
  flex: 0 1 auto;
  min-width: auto;
}

.signer-list--bar .signer-pill.is-active {
  border-color: var(--signer-color, var(--ds-ink));
  box-shadow: inset 0 0 0 1px var(--signer-color, var(--ds-ink));
}

/* A plus at the size of a chip, pinned to the top right: it stays put while
   the chips scroll under it, so the way to add a signer never scrolls away. */
.menu-add-signer--plus {
  flex: 0 0 auto;
  align-self: flex-start;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--ds-ink);
  border: 1px dashed var(--ds-line-strong, var(--ds-line));
  background: var(--ds-desk);
}

.menu-add-signer--plus:hover:not(:disabled) {
  background: var(--ds-desk-sunk);
  color: var(--ds-ink);
}

.menu-add-signer--plus:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* A field with no width of its own is absolutely positioned, so it stretches
   from where it sits to the right edge of the page. A checkbox was 630px wide:
   it swallowed clicks across the whole line, and any clamp computed from its
   width fed back on itself as it moved. Fields with an explicit width (every
   text and signature field) still set it inline, which wins over this. */
.annotation-field {
  width: fit-content;
}

/* A document name is laid out in its own direction, not the UI's. A Hebrew
   name with a Latin suffix — מכתב_לביטוח_לאומי-signed.pdf — came out scrambled
   inside a left-to-right breadcrumb. dir="auto" on the elements does the work;
   this keeps an isolated name from reordering what sits beside it. */
.document-nav__doc,
.document-row__title {
  unicode-bidi: isolate;
}

/* A ribbon button that wraps mid-label turns one row of actions into two and
   reads as "Add" over "signer". The priority+ bar already has somewhere for
   what does not fit: the overflow menu. */
.documents-ribbon__actions-main button {
  white-space: nowrap;
}

/* A grid or flex item will not shrink below its content unless it is told it
   may. The signer bar's chips are as wide as the addresses on them, so four
   real addresses pushed the whole column — and the ribbon above it — out to
   691px inside a 390px phone. The bar scrolls; the column does not stretch. */
.documents-main {
  min-width: 0;
}

.documents-ribbon,
.signer-bar {
  max-width: 100%;
  min-width: 0;
}

/* ─── The menu reads down one column ─────────────────────────────────────────
   Reported from a phone: "unaligned to the left and very uneasy to read". The
   section labels sat at the left edge and every row under them was centred,
   because the global button rule centres its contents and nothing overrode it
   here. One left edge, rows big enough to hit, and type big enough to read. */
.header-menu .menu-item,
.header-menu .menu-item--select {
  justify-content: flex-start;
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  font-size: 0.95rem;
  border-radius: var(--ds-radius-md);
}

.header-menu .menu-item--select {
  justify-content: space-between;
  gap: var(--ds-s-2);
}

.header-menu .menu-item--select > span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.header-menu .menu-section__label {
  padding: 0 12px;
  margin: var(--ds-s-3) 0 2px;
}

/* The icons form their own column, so the labels line up with each other and
   not with whatever glyph happens to precede them. */
.header-menu .menu-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  flex: 0 0 20px;
}

.header-menu .menu-section__email,
.header-menu .user-badge {
  width: 100%;
}

/* On a phone the panel is the screen. At 380px it left a 10px strip of dead
   page down the side, which reads as a panel that failed to finish opening. */
@media (max-width: 480px) {
  .header-menu {
    width: 100vw;
  }
}

/* ─── A close or a menu glyph is not a button-shaped object ──────────────────
   Reported: "Buttons such as X or burger cannot be with outlines and in boxes
   with rounded corners". They are marks on the page: no border, no fill, no
   shadow. The focus ring still appears for anyone arriving by keyboard. */
.icon-button,
.viewer-close {
  background: transparent;
  border: 0;
  box-shadow: none;
  color: var(--ds-ink-soft);
}

.icon-button:hover:not(:disabled),
.viewer-close:hover:not(:disabled) {
  background: transparent;
  color: var(--ds-ink);
}

.icon-button:active:not(:disabled),
.viewer-close:active:not(:disabled) {
  background: transparent;
  color: var(--ds-ink);
  transform: scale(0.94);
}

/* The first screen has to say what the product is. "My Documents" over an
   empty list tells a first-time visitor nothing, and most people who land
   here have never heard of this. It goes as soon as they have a document of
   their own: by then the screen explains itself. */
.documents-inbox__pitch {
  margin: 0 0 var(--ds-s-2, 8px);
  max-width: 52ch;
  color: var(--ds-ink-soft);
  font-size: 0.92rem;
  line-height: 1.5;
}

.documents-inbox__pitch[hidden] {
  display: none;
}

/* =========================================================================
   The post-signing offer.

   A recipient has just sent somebody else's contract back, and this is the
   one screen they see afterwards. The confirmation is the loud part: a signed
   document is the thing they came to do, and burying it under a product
   pitch would read as a bait. The offer sits under it in plain body text,
   with Not now beside the button rather than hidden as an x in a corner.

   No --ds-accent here: that pair is reserved for the product speaking about
   the document. This is the product speaking about itself.
   ========================================================================= */
.recipient-done {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(27, 47, 87, 0.42);
}

.recipient-done[hidden] {
  display: none;
}

.recipient-done__card {
  width: 100%;
  max-width: 420px;
  box-sizing: border-box;
  padding: 24px;
  border-radius: var(--ds-radius-lg);
  background: var(--ds-paper);
  border: 1px solid var(--ds-line);
  box-shadow: 0 18px 48px rgba(27, 47, 87, 0.18);
}

.recipient-done__card h3 {
  margin: 0 0 8px;
  color: var(--ds-success-ink);
  font-size: 1.2rem;
  line-height: 1.3;
}

.recipient-done__lede,
.recipient-done__pitch {
  margin: 0 0 12px;
  color: var(--ds-ink-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}

.recipient-done__pitch {
  margin-bottom: 20px;
  color: var(--ds-ink-mute);
}

.recipient-done__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.recipient-done__start,
.recipient-done__dismiss {
  min-height: 44px;
  padding: 0 18px;
  border-radius: var(--ds-radius-md);
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.recipient-done__start {
  flex: 1 1 auto;
  border: 1px solid var(--ds-ink);
  background: var(--ds-ink);
  color: var(--ds-paper);
}

.recipient-done__start:hover {
  background: #122039;
  border-color: #122039;
}

.recipient-done__dismiss {
  border: 1px solid var(--ds-line);
  background: transparent;
  color: var(--ds-ink);
}

.recipient-done__dismiss:hover {
  background: var(--ds-desk-sunk);
}

/* =========================================================================
   What a signer still has to do.

   Lives in the tool drawer, which for a recipient is otherwise empty: the
   field palette is hidden from them, so on a phone the drawer was reserving
   186px to say one static sentence. The count is quiet text; Next is the
   only button, because it is the only thing to do here.
   ========================================================================= */
.recipient-progress {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 8px;
}

.recipient-progress[hidden] {
  display: none;
}

.recipient-progress__count {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  color: var(--ds-ink-soft);
  font-size: 0.9rem;
  line-height: 1.4;
}

.recipient-progress__next {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--ds-ink);
  border-radius: var(--ds-radius-md);
  background: var(--ds-ink);
  color: var(--ds-paper);
  font: inherit;
  font-size: 0.9rem;
  white-space: nowrap;
  cursor: pointer;
}

.recipient-progress__next:hover {
  background: #122039;
  border-color: #122039;
}

.recipient-progress__next[disabled] {
  border-color: var(--ds-line);
  background: var(--ds-desk-sunk);
  color: var(--ds-ink-mute);
  cursor: default;
}

/* ─── New document, as a bubble ─────────────────────────────────────────────
   It sat in the top right of the inbox head: the far corner from a thumb, and
   the first thing a narrow screen squeezed down to half a grid cell. Pinned to
   the bottom right it is in reach on a phone and out of the list's way.
   Ink, not --ds-accent: this is the product talking about itself. */
.documents-upload {
  position: fixed;
  right: 20px;
  bottom: 20px;
  left: auto;
  /* A fixed child of the grid is stretched to the column without this,
     which makes the bubble a full-width bar on a phone. */
  width: fit-content;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 0 22px;
  border: 1px solid var(--ds-ink);
  border-radius: 999px;
  background: var(--ds-ink);
  color: var(--ds-paper);
  font-weight: 600;
  font-size: 0.95rem;
  box-shadow: var(--ds-lift-2);
  cursor: pointer;
}

.documents-upload .icon {
  opacity: 1;
}

.documents-upload:not(:disabled):hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.documents-upload[hidden] {
  display: none;
}

/* The empty state already offers one, in the middle of the screen where a
   first-time visitor is looking. Two routes to the same place is a choice
   nobody asked for. */
.documents-screen:has(.documents-list__empty-wrap) .documents-upload {
  display: none;
}

/* With a document open the bottom of the screen belongs to the tool drawer,
   and starting another document is not what anybody is there to do. */
.documents-screen:not(.documents-screen--empty) .documents-upload {
  display: none;
}

/* ─── The field palette, all of it, on a phone ───────────────────────────────
   Twelve fields in one sideways strip put three on screen and nine behind a
   swipe that only a 22px fade announced. Finding Date meant discovering a
   gesture. They are a grid now: four across, every field in reach, and the
   group headings dropped because three heading rows cost more screen than
   the grouping of twelve obvious things was worth. */
@media (max-width: 720px), (orientation: portrait) and (max-width: 1100px) {
  .documents-screen--focused .document-tools__items {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-flow: row;
    gap: 4px;
    overflow: visible;
    /* The fade and the snap belonged to a strip that scrolled. Nothing
       scrolls here, and a mask over a grid just dims its right column. */
    mask-image: none;
    -webkit-mask-image: none;
    scroll-snap-type: none;
    padding-bottom: 0;
  }

  /* The three groups stop being boxes so their chips join one grid. */
  .documents-screen--focused .tools-group--inline {
    display: contents;
  }

  .documents-screen--focused .tools-group__label {
    display: none;
  }

  /* The hairlines divided columns that no longer exist. */
  .documents-screen--focused .tools-group__label:not(:first-child),
  .documents-screen--focused .tools-group--inline:not(:first-of-type) {
    padding-left: 0;
    margin-left: 0;
    border-left: 0;
  }

  /* A quarter of a phone is 86px. The label wraps to a second line rather
     than truncating: 'Email Address' cut to 'Email A…' is not a field name. */
  .documents-screen--focused .tool-item {
    /* 36px, not the 40px the zoom pair got: twelve chips in three rows means
       every pixel here costs three, and tool-drawer.test.mjs holds the whole
       drawer to 180px so the document keeps the screen. 36 is the floor a
       thumb needs and lands the drawer at 178. */
    min-height: 36px;
    padding: 3px 8px;
    gap: 5px;
    justify-content: flex-start;
    text-align: left;
    white-space: normal;
    line-height: 1.12;
    font-size: 0.68rem;
  }

  .documents-screen--focused .tool-item .tool-icon {
    flex: 0 0 auto;
  }

  /* Three rows of chips instead of one row and a swipe. 178, not 172: the
     chips went from 34px to the 36px floor and there are three rows of them. */
  .documents-screen--focused .workspace {
    --drawer-h: 178px;
  }
}

/* ─── The document gets the glass ────────────────────────────────────────────

   A phone spent 37px of each side before the page began: 20px of page gutter,
   a panel border, and 16px of stage padding inside it. 74px of a 390px screen
   went to grey, and the stage's padding was double counted against the width
   the renderer had already fitted the page to, so the page sat 32px right of
   centre and touched the right edge. */
@media (max-width: 720px), (orientation: portrait) and (max-width: 1100px) {
  main:has(.documents-screen--focused) {
    padding-left: 4px;
    padding-right: 4px;
  }

  .documents-screen--focused .viewer {
    border-radius: var(--radius-md, 10px);
  }

  /* The stacked layout turns .workspace into a flex column, and that column
     aligns its children to the start rather than stretching them. So the
     viewer took its width from the page inside it, while the renderer was
     fitting that page to the width of the viewer: the two shrank each other
     down to a 92px sliver beside 700px of grey. The column is as wide as the
     window, so say so, and say it again for the scrolling box inside it. */
  .documents-screen--focused .viewer,
  .documents-screen--focused #viewer-scroll {
    align-self: stretch;
    width: 100%;
  }

  /* Stacked, the document scrolls with the page rather than inside its own
     box, so the reserved gutter was 15px of grey held for a scrollbar that
     never comes. */
  .documents-screen--focused #viewer-scroll {
    scrollbar-gutter: auto;
  }

  /* The renderer already fits the page to the scrolling box less this
     padding, so anything here is spent twice. */
  .documents-screen--focused .pdf-stage {
    padding: 0;
  }

  /* The controls belong to the document, not to the top of the page it
     happens to start at: zoom on page four meant scrolling back up to the
     first page to reach it.

     Only once the document's own top has gone under the header, though. A bar
     pinned from the start sits over the breadcrumb and the Download and Share
     buttons, which are the top of the page, not the top of the document. The
     class is set from the scroll position; the space the bar occupies is
     reserved either way, so nothing jumps when it pins. */
  body.is-viewer-bar-pinned .documents-screen--focused .viewer-ribbon {
    position: fixed;
    top: var(--app-header-h, 56px);
    left: 4px;
    right: 4px;
    width: auto;
    /* Under the field drawer (25), over the document. */
    z-index: 24;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 8px);
    box-shadow: var(--ds-lift-1, 0 1px 2px rgba(27, 47, 87, 0.08));
  }
}

/* The document, and nothing else. iOS Safari will not put an arbitrary
   element into real fullscreen, so this is done with the page's own layout,
   which also keeps one way back out on every platform. */
.viewer-expand {
  display: inline-grid;
  place-items: center;
  min-width: 34px;
  min-height: 30px;
  padding: 4px 8px;
  background: var(--panel);
  color: var(--ink-secondary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}

body.is-document-expanded .app__header,
body.is-document-expanded .documents-inbox,
body.is-document-expanded .signer-bar,
body.is-document-expanded .document-tools,
body.is-document-expanded .documents-upload {
  display: none;
}

body.is-document-expanded .viewer {
  position: fixed;
  inset: 0;
  z-index: 60;
  max-height: none;
  margin: 0;
  border: 0;
  border-radius: 0;
  padding-top: 52px;
  padding-bottom: 0;
}

/* The ribbon survives full screen, because the way back out is a button
   inside it. Nothing else in it does: the breadcrumb and the document's
   own actions are the page, and the point of this mode is to not have
   the page. What is left is a thin bar of view controls over the top of
   the document, which is what this mode always looked like. */
body.is-document-expanded .documents-ribbon {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 61;
  margin: 0;
  padding: 8px 12px;
  border-radius: 0;
  border-left: 0;
  border-right: 0;
  border-top: 0;
}

body.is-document-expanded .documents-ribbon .document-nav,
body.is-document-expanded .documents-ribbon .documents-ribbon__actions-main {
  display: none;
}

body.is-document-expanded .documents-ribbon .viewer-ribbon {
  /* The bar above is already fixed to the top of the screen; the controls
     ride inside it rather than pinning themselves to the same place. */
  position: static;
}

/* The page is fitted to the width of the box it sits in, and that box was
   sized by the page: a grid column defaults to min-width: auto, which takes
   its content's width as a floor, so the viewer grew to the page, the page
   re-fitted to the viewer, and the pair walked off the right of a phone. Each
   of these caps a column that has a document in it. */
.documents-main {
  grid-template-columns: minmax(0, 1fr);
}

.workspace,
.workspace > * {
  min-width: 0;
}

.viewer {
  min-width: 0;
  max-width: 100%;
}


/* ─── What a thumb has to hit ────────────────────────────────────────────────

   Measured 2026-10-17 at 320/360/390/412 with a document open: the breadcrumb
   back-link came out 99x18, the zoom pair and the full-screen toggle 34x30.
   36px is the floor a thumb needs and 40px is what the ink primary and the
   ... toggle beside them measure, so these go to 40.

   Touch, not width, is the condition - the same query the tool drawer uses,
   because a tablet held upright is held, not pointed at. A pointer does not
   need 40px, and charging every width for it pushed the document 17px further
   down the page than tests/ribbon-consolidation.test.mjs allows.

   The containers give back what the controls take. A 40px control inside a
   row that adds its own padding is a 50px row, which is how the zoom cluster
   failed "the control is one row tall" - so the padding moves off the
   container and into the control's own box, and the chrome above the document
   ends up smaller than it was.

   End of file: a media query adds no specificity, and .viewer-expand above is
   a plain class selector.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 720px), (orientation: portrait) and (max-width: 1100px) {
  .document-nav__crumb--interactive {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding-inline: 8px;
  }

  /* The crumb now stands the row up by itself. Keeping the trail's padding on
     top of it would cost 12px of document, and the min-height holds the row
     steady for the state where there is no document and no link. */
  .documents-ribbon .documents-ribbon__top .document-nav {
    padding-block: 0;
    min-height: 40px;
  }

  .zoom-controls button,
  .viewer-expand {
    min-width: 40px;
    min-height: 40px;
  }

  /* 4px around a 40px button is a 50px strip, and this one shares its row
     with the ink primary. The buttons are their own padding. */
  .zoom-controls {
    padding: 0;
  }
}
