/* Ulo Pro client pages (my.ulopro.com): the proposal page, its expired/landing shells, and every
   sheet and form on them. Brand tokens only (tokens.css) — no literal color, size or radius here.
   No selector below ever needs an inline style: this is the one stylesheet the CSP allows
   (FOLLOWUPS #2 drops 'unsafe-inline' from style-src on this host once nothing here needs it). */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--up-paper);
  color: var(--up-ink);
  font-family: var(--up-sans);
  font-size: 16px;
  line-height: 1.5;
}
h1, h2, h3 { font-weight: 700; line-height: 1.15; }
.num { font-family: var(--up-mono); font-variant-numeric: tabular-nums; }
a { color: var(--up-blue-text); }

.rule { height: 3px; background: var(--up-grad); }

/* --- simple status pages: index.html (nothing to show yet), expired.html ------------------- */

.status-page {
  min-height: calc(100vh - 3px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--up-page-pad);
}
.status-card { max-width: 32rem; text-align: center; }
.status-card h1 { font-size: var(--up-h2); margin: 0 0 0.75rem; }
.status-card p { margin: 0; color: var(--up-mute); }

/* --- the app shell: everything below is built into #app by /my/js/proposal.js -------------- */

.app { max-width: 40rem; margin: 0 auto; padding-bottom: 1rem; }
.boot-message { padding: 4rem var(--up-page-pad); text-align: center; color: var(--up-mute); }

.demo-banner {
  background: var(--up-ink);
  color: var(--up-paper);
  text-align: center;
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.65rem var(--up-page-pad);
}
.demo-banner[hidden] { display: none; }

.readonly-banner {
  background: color-mix(in srgb, var(--up-blue) 12%, var(--up-paper));
  color: var(--up-ink);
  padding: 0.75rem var(--up-page-pad);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  font-size: 0.95rem;
}
.readonly-banner[hidden] { display: none; }
.readonly-banner button {
  font: inherit;
  font-weight: 600;
  background: none;
  border: 0;
  min-height: 0;
  padding: 0;
  color: var(--up-blue-text);
  text-decoration: underline;
  cursor: pointer;
}

/* --- cover ----------------------------------------------------------------------------------- */

.cover { padding: 2rem var(--up-page-pad) 1.5rem; }
.cover .kicker {
  display: block;
  color: var(--up-mute);
  font-weight: 600;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.35rem;
}
.cover h1 { font-size: var(--up-h1); letter-spacing: -0.02em; margin: 0 0 0.6rem; }
.cover .meta { margin: 0.2rem 0; color: var(--up-mute); }
.cover .meta strong { color: var(--up-ink); font-weight: 600; }

.project-description { padding: 0 var(--up-page-pad) 1.5rem; }
.project-description :first-child { margin-top: 0; }
.project-description :last-child { margin-bottom: 0; }

/* --- sticky area tabs -------------------------------------------------------------------------- */

.area-tabs {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  gap: 0.35rem;
  overflow-x: auto;
  background: var(--up-paper);
  border-top: 1px solid var(--up-rule);
  border-bottom: 1px solid var(--up-rule);
  padding: 0.5rem var(--up-page-pad);
  -webkit-overflow-scrolling: touch;
}
.area-tabs[hidden] { display: none; }
.area-tab {
  flex: 0 0 auto;
  font: inherit;
  font-weight: 600;
  font-size: 0.9rem;
  min-height: var(--up-control-h);
  padding: 0 0.9rem;
  border-radius: var(--up-radius);
  border: 1px solid var(--up-rule);
  background: var(--up-paper);
  color: var(--up-ink);
  cursor: pointer;
}
.area-tab[aria-current="true"] {
  color: var(--up-blue-text);
  border-color: var(--up-blue);
  background: color-mix(in srgb, var(--up-blue) 8%, var(--up-paper));
}

/* --- an area's section -------------------------------------------------------------------------- */

.area { padding: 1.5rem var(--up-page-pad); border-bottom: 1px solid var(--up-rule); scroll-margin-top: 3.5rem; }
.area h2 { font-size: var(--up-h3); margin: 0 0 0.6rem; }
.area-description { margin: 0 0 1rem; }
.area-description :first-child { margin-top: 0; }
.area-description :last-child { margin-bottom: 0; }
.area-photos[hidden] { display: none; }

.lines { display: flex; flex-direction: column; gap: 0.6rem; margin: 0.75rem 0; }
.line-group { border: 1px solid var(--up-rule); border-radius: var(--up-radius); padding: 0.65rem 0.8rem; }
.line-row { display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem; }
.line-name { font-weight: 600; }
.line-qty { color: var(--up-mute); font-size: 0.9rem; margin-left: 0.35rem; font-weight: 400; }
.line-price { white-space: nowrap; }
.line-note { color: var(--up-mute); font-size: 0.9rem; margin-top: 0.25rem; }
.line-children {
  margin: 0.5rem 0 0 1rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--up-rule);
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.line-children .line-row { font-size: 0.95rem; }

.area-supplies {
  display: flex;
  justify-content: space-between;
  color: var(--up-mute);
  padding-top: 0.6rem;
  margin-top: 0.25rem;
  border-top: 1px dashed var(--up-rule);
}
.area-total {
  display: flex;
  justify-content: space-between;
  font-weight: 700;
  font-size: 1.05rem;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--up-rule);
}

/* --- summary, schedule -------------------------------------------------------------------------- */

.summary, .schedule { padding: 1.5rem var(--up-page-pad); }
.schedule { padding-top: 0; }
.summary h2, .schedule h2 { font-size: var(--up-h3); margin: 0 0 0.6rem; }
.summary-row, .schedule-row { display: flex; justify-content: space-between; padding: 0.3rem 0; }
.summary-row.total {
  font-weight: 700;
  font-size: 1.15rem;
  border-top: 1px solid var(--up-rule);
  margin-top: 0.4rem;
  padding-top: 0.6rem;
}
.schedule-row .label { color: var(--up-mute); }

/* --- terms, in full ------------------------------------------------------------------------------ */

.terms { padding: 1.5rem var(--up-page-pad) 3rem; border-top: 1px solid var(--up-rule); }
.terms h2 { font-size: var(--up-h3); margin: 0 0 0.75rem; }
.terms-body p { margin: 0 0 0.9rem; }
.terms-body ul { margin: 0 0 0.9rem 1.25rem; padding: 0; }
.terms-body li { margin-bottom: 0.35rem; }
.terms-note { color: var(--up-mute); font-size: 0.9rem; margin-top: 1rem; }

.version-history { padding: 0 var(--up-page-pad) 1rem; color: var(--up-mute); font-size: 0.9rem; }
.version-history ul { list-style: none; margin: 0.35rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
.version-history button {
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  min-height: 0;
  color: var(--up-blue-text);
  text-decoration: underline;
  cursor: pointer;
}

/* --- sticky bottom action bar -------------------------------------------------------------------- */

.bottom-bar {
  position: sticky;
  bottom: 0;
  z-index: 20;
  display: flex;
  gap: 0.6rem;
  padding: 0.75rem var(--up-page-pad) calc(0.75rem + env(safe-area-inset-bottom, 0px));
  background: var(--up-paper);
  border-top: 1px solid var(--up-rule);
}
.bottom-bar[hidden] { display: none; }
.bottom-bar .button { flex: 1; }
.bottom-bar a.button { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }

/* --- controls: buttons, inputs, checkboxes -------------------------------------------------------- */

button, .button {
  font: inherit;
  font-weight: 600;
  min-height: var(--up-control-h);
  padding: 0 1.1rem;
  border-radius: var(--up-radius);
  border: 1px solid var(--up-rule);
  background: var(--up-paper);
  color: var(--up-ink);
  cursor: pointer;
}
button.primary, .button.primary {
  background: var(--up-grad-cta);
  color: var(--up-on-blue);
  border: 0;
  border-radius: var(--up-radius-pill);
}
button:disabled, .button:disabled { opacity: 0.5; cursor: not-allowed; }

button:focus-visible, .button:focus-visible, a:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 3px solid var(--up-blue);
  outline-offset: 2px;
}

.field { margin: 0 0 1.1rem; }
.field label { display: block; font-weight: 600; margin: 0 0 0.3rem; }
.field .hint { display: block; font-weight: 400; font-size: 0.85rem; color: var(--up-mute); margin-top: 0.3rem; }
input, textarea, select {
  font: inherit;
  width: 100%;
  min-height: var(--up-control-h);
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--up-rule);
  border-radius: var(--up-radius);
  background: var(--up-paper);
  color: var(--up-ink);
}
textarea { min-height: 7rem; resize: vertical; }

.checkbox-field { display: flex; align-items: flex-start; gap: 0.65rem; margin: 0 0 1.1rem; }
.checkbox-field input[type="checkbox"] {
  width: 1.35rem;
  height: 1.35rem;
  min-height: 0;
  flex: 0 0 auto;
  margin-top: 0.1rem;
}
.checkbox-field label { font-weight: 400; margin: 0; }

/* --- notices --------------------------------------------------------------------------------------- */

.notice { padding: 0.75rem 1rem; border-radius: var(--up-radius); border: 1px solid var(--up-rule); margin: 0 0 1rem; }
.notice.error { border-color: var(--up-ink); }
.notice.success { border-color: var(--up-blue); color: var(--up-blue-text); }
.notice[hidden] { display: none; }

/* --- sheets: Accept and sign, Request changes ------------------------------------------------------ */

.sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: color-mix(in srgb, var(--up-ink) 55%, transparent);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
}
.sheet-overlay[hidden] { display: none; }
.sheet {
  background: var(--up-paper);
  color: var(--up-ink);
  width: 100%;
  max-width: 34rem;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--up-radius) var(--up-radius) 0 0;
  padding: 1.25rem var(--up-page-pad) calc(1.5rem + env(safe-area-inset-bottom, 0px));
}
.sheet h2 { font-size: var(--up-h3); margin: 0 0 0.75rem; }
.sheet .review-row { display: flex; justify-content: space-between; padding: 0.35rem 0; }
.sheet .review-row.total { font-weight: 700; border-top: 1px solid var(--up-rule); margin-top: 0.4rem; padding-top: 0.6rem; }
.sheet-actions { display: flex; gap: 0.6rem; margin-top: 1.25rem; }
.sheet-actions .button { flex: 1; }

@media (min-width: 40rem) {
  .sheet-overlay { align-items: center; padding: var(--up-page-pad); }
  .sheet { border-radius: var(--up-radius); }
}

/* --- the invoice and its payment: public/my/invoice.html, built by /my/js/invoice.js ------------
   Tokens only. The brand has no error hue: a problem is bold ink. The one pill is the primary
   action (button.primary above); no shadows. */

.inv-head { padding: 2rem var(--up-page-pad) 1rem; }
.inv-head .kicker {
  display: block;
  color: var(--up-mute);
  font-weight: 600;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.35rem;
}
.inv-head h1 { font-size: var(--up-h2); letter-spacing: -0.01em; margin: 0 0 0.5rem; }
.inv-head .meta { margin: 0; color: var(--up-mute); }
.inv-head .meta strong { color: var(--up-ink); font-weight: 600; }

.inv-section { padding: 1.25rem var(--up-page-pad); border-top: 1px solid var(--up-rule); }
.inv-section h2 { font-size: var(--up-h3); margin: 0 0 0.75rem; }
.inv-section h2 + p { margin-top: 0; }
.inv-note { color: var(--up-mute); font-size: 0.9rem; }

.inv-row { display: flex; justify-content: space-between; gap: 1rem; padding: 0.3rem 0; }
.inv-row.inv-tax { color: var(--up-mute); }
.inv-row.inv-total { font-weight: 700; border-top: 1px solid var(--up-rule); margin-top: 0.35rem; padding-top: 0.6rem; }
.inv-row.inv-balance { font-weight: 700; font-size: 1.2rem; }
.inv-row .num { white-space: nowrap; }

.inv-status-title { font-weight: 700; font-size: 1.1rem; margin: 0 0 0.5rem; }
.inv-receipt { border: 1px solid var(--up-rule); border-radius: var(--up-radius); padding: 0.6rem 0.8rem; margin-top: 0.5rem; }

.pay-methods { display: flex; flex-direction: column; gap: 0.6rem; margin: 0 0 1rem; }
.pay-method {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  min-height: var(--up-control-h);
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--up-rule);
  border-radius: var(--up-radius);
  background: var(--up-paper);
  cursor: pointer;
}
.pay-method.is-chosen { border-color: var(--up-blue); background: color-mix(in srgb, var(--up-blue) 6%, var(--up-paper)); }
.pay-method input[type="radio"] { width: 1.25rem; height: 1.25rem; min-height: 0; flex: 0 0 auto; margin: 0.15rem 0 0; }
.pay-method-text { display: flex; flex-direction: column; gap: 0.15rem; }
.pay-method-label { font-weight: 600; }
.pay-method-desc { color: var(--up-mute); font-size: 0.9rem; }

.pay-detail { margin: 0 0 1rem; }
.pay-element { min-height: var(--up-control-h); }
.pay-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0.75rem 0 0; }
.pay-actions .button.primary { flex: 1 1 12rem; }
.pay-actions a.button { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }

/* Problems are bold ink, never a colour. */
.pay-error { font-weight: 700; color: var(--up-ink); margin: 0.5rem 0; }

/* The credit-card fee disclosure: never smaller or fainter than the text around it (Visa 5.5.1.9). */
.pay-disclosure { font-size: 1rem; color: var(--up-ink); margin: 0.9rem 0 0; }

.inv-send { display: flex; flex-direction: column; gap: 0.5rem; margin: 0 0 1rem; }
.inv-send .field { margin: 0; }
.inv-other h2 + p { margin-top: 0; }
.inv-other h2:not(:first-child) { margin-top: 1.5rem; }

.demo-panel { border-top: 3px solid var(--up-ink); }
.demo-panel .button { flex: 1 1 12rem; }

@media (min-width: 40rem) {
  .inv-send { flex-direction: row; align-items: flex-end; }
  .inv-send .field { flex: 1; }
}

/* --- product photos and friendly names on the proposal's rows (CJ, 2026-09-29: "the items I am
   selling need photos"; "Sonos Amp", not its model number). /my/js/proposal.js renderLineRow
   builds [photo] name × qty, brand and model small beneath, then the price. A device's photo is
   64px, an accessory's 40px, labor has none. Phone-first: the text column shrinks and wraps, so
   nothing scrolls sideways at 375px. ------------------------------------------------------------ */

.line-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  overflow-wrap: anywhere;
}
.line-model { color: var(--up-mute); font-size: 0.85rem; font-weight: 400; }
.line-detail { color: var(--up-mute); font-size: 0.85rem; font-weight: 400; }
.line-children .line-name { font-weight: 400; }
.line-row.has-photo { align-items: center; }
.line-row .line-price { flex: 0 0 auto; }
.line-photo {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  object-fit: contain;
  border: 1px solid var(--up-rule);
  border-radius: var(--up-radius);
  /* Distributor photos are shot for a white page, and about a third are transparent PNGs: a black
     amp on the dark theme's paper would vanish. The brand's one theme-invariant white keeps every
     photo on white in both themes. */
  background: var(--up-on-blue);
}
.line-children .line-photo { width: 40px; height: 40px; }

/* --- change orders on the client page (FOLLOWUPS #68): /my/js/proposal.js renderChangeOrder lists
   what is added and removed as the proposal's rows are drawn (a 64px photo, none on labor), with
   the area each line lands in beneath it, then what the change does to the total. ------------- */

.line-area { color: var(--up-mute); font-size: 0.85rem; margin-top: 0.25rem; }
.summary-note { color: var(--up-mute); font-size: 0.9rem; margin: 0.6rem 0 0; }

/* --- a change order's own page and the proposal's list of them (FOLLOWUPS #91): a way back to the
   proposal, where the change order stands, and on the proposal's page one card per change order,
   each a plain link. Cards are 8px, never pills; the open one is outlined in blue. -------------- */

.back-nav { padding: 1rem var(--up-page-pad) 0; }
.back-nav a { font-weight: 600; text-decoration: none; }
.co-state { margin: 0 var(--up-page-pad) 1.5rem; }
.sheet .summary-note { margin: 0.4rem 0 0; }

.change-orders { padding: 0 var(--up-page-pad) 1.5rem; }
.change-orders h2 { font-size: var(--up-h3); margin: 0 0 0.6rem; }
.co-list { display: flex; flex-direction: column; gap: 0.5rem; }
.co-link {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.15rem 0.75rem;
  min-height: var(--up-control-h);
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--up-rule);
  border-radius: var(--up-radius);
  color: var(--up-ink);
  text-decoration: none;
}
.co-link.is-open { border-color: var(--up-blue); }
.co-link-title { font-weight: 600; flex: 1 1 auto; min-width: 0; }
.co-link-amount { white-space: nowrap; }
.co-link-status { flex: 1 0 100%; color: var(--up-mute); font-size: 0.9rem; }
.co-link.is-open .co-link-status { color: var(--up-blue-text); font-weight: 600; }

/* The "signed copy is being prepared" page (src/client/pdf-routes.js, FOLLOWUPS #126): a way back. */
.status-card .status-back { margin-top: 1.25rem; }
.status-card .status-back a { font-weight: 600; }
