/* Portal shell. The back-office at /admin/ has its own stylesheet (Unfold) and
   shares nothing with this file.

   The portal wears Arrowstone's own kit, lifted from arrowstonecabinetry.com:
   Marcellus over Montserrat, black and greys on white, hairline rules and
   black pill buttons; boxed fields and small-cornered cards where people work.
   Every shared value -- colour, type, corners, shadows, sizes -- is a token in
   :root below, and every rule reads the token. */

:root {
  /* ======================================================== shared values
     Every rule below reads these; a rule never types a colour, a corner, a
     shadow, a text size or a control height of its own. Five groups. */

  /* --- Colour: surfaces */
  --portal-surface: #ffffff;
  --portal-panel: #f5f5f5;          /* the only filled panels */
  --portal-head: #f3f3f3;           /* a card's head, a table's top group row */
  --portal-raised: #fafafa;         /* a nested group row, a drop zone */
  --portal-chosen: #f6f6f6;         /* the chosen tile */
  --portal-disabled: #f4f4f4;       /* a field that cannot change */
  --portal-badge: #ebebeb;          /* a grey count or state badge */
  --portal-hover: rgba(0, 0, 0, 0.06);
  --portal-hover-faint: rgba(0, 0, 0, 0.03);
  --portal-scrim: rgba(0, 0, 0, 0.12);   /* behind a pop-up */
  --portal-scrim-strong: rgba(0, 0, 0, 0.42);   /* behind a full-screen modal */
  --portal-veil: rgba(255, 255, 255, 0.92);     /* a caption over a picture */

  /* --- Colour: text. The greys are darker than the marketing site's: a page
     someone works on is read at length and often on a shop laptop in daylight,
     so every one of these clears 4.5:1 on white rather than looking delicate. */
  --portal-ink: #000000;
  --portal-body: rgba(0, 0, 0, 0.84);
  --portal-muted: rgba(0, 0, 0, 0.68);
  --portal-faint: rgba(0, 0, 0, 0.58);
  --portal-ghost: rgba(0, 0, 0, 0.56);
  --portal-ink-hover: rgba(0, 0, 0, 0.78);   /* a black button under the pointer */

  /* --- Colour: lines */
  --portal-rule: rgba(0, 0, 0, 0.09);
  --portal-rule-strong: rgba(0, 0, 0, 0.16);
  --portal-edge: #b5b5b5;           /* a field's box, an outlined button */
  --portal-edge-soft: #c9c9c9;      /* a choice tile */
  --portal-edge-disabled: #d6d6d6;
  --portal-edge-hover: rgba(0, 0, 0, 0.5);

  /* --- Colour: a cabinet drawn in grey (the Door design swatch) */
  --portal-draw-line: rgba(0, 0, 0, 0.35);
  --portal-draw-open: rgba(0, 0, 0, 0.12);
  --portal-draw-toe-kick: rgba(0, 0, 0, 0.28);

  /* --- Colour: meaning. Each a text colour and the wash it sits on. */
  --portal-danger: #9c2b21;
  --portal-danger-strong: #7f2219;
  --portal-danger-wash: #fbf1f0;
  --portal-danger-tint: #fbe3e0;
  --portal-positive: #2f6b3d;
  --portal-positive-wash: #e5f1e8;
  --portal-amber: #7a4900;
  --portal-amber-wash: #fbefd9;
  --portal-amber-faint: #fdf8ee;
  --portal-teal: #1c5f5f;           /* focus, a note, Contacted */
  --portal-teal-wash: #e2f0ef;
  --portal-teal-ring: #d3e8e6;
  --portal-note: #edf4f3;
  --portal-note-ink: #163f3f;
  --portal-blue: #1f4e8c;           /* New, a call */
  --portal-blue-wash: #e6eef8;
  --portal-purple: #553a85;         /* Designing, an email */
  --portal-purple-wash: #eee9f6;
  --portal-brown: #7a4b12;          /* a meeting */
  --portal-brown-wash: #f6ede1;
  --portal-stone: #51504c;          /* Lost, a Stage with no colour of its own */
  --portal-stone-wash: #f2f2ef;
  --portal-bubble: #efeeea;         /* the customer's side of a Conversation */

  /* --- Type: Marcellus over Montserrat, and one scale of sizes, named in px. */
  --portal-display: Marcellus, Georgia, "Times New Roman", serif;
  --portal-ui: Montserrat, "Segoe UI", system-ui, -apple-system, sans-serif;
  --portal-text-10: 0.656rem;       /* spaced capitals */
  --portal-text-11: 0.688rem;
  --portal-text-12: 0.75rem;
  --portal-text-13: 0.813rem;
  --portal-text-14: 0.875rem;
  --portal-text-15: 0.938rem;
  --portal-text-16: 1rem;
  --portal-text-18: 1.125rem;
  --portal-text-20: 1.25rem;
  --portal-text-22: 1.375rem;
  --portal-text-24: 1.5rem;
  --portal-text-30: 1.875rem;
  --portal-text-40: 2.5rem;
  --portal-text-44: 2.75rem;
  --portal-text-50: 3.125rem;
  --portal-text-62: 3.875rem;

  /* --- Corners: one for every box (a field, a tile, a note, a card, a table, a
     menu, a badge), twice that for a pop-up, a pill for a button or a tag. */
  --portal-radius: 4px;
  --portal-radius-pop: calc(2 * var(--portal-radius));
  --portal-pill: 999px;
  --portal-radius-chat: 1.125rem;   /* a Conversation's bubble, card and composer */
  --portal-radius-tail: 0.3125rem;  /* a bubble's corner toward its sender */
  --portal-round: 50%;

  /* --- Shadows */
  --portal-shadow-pop: 0 16px 48px rgba(0, 0, 0, 0.2);
  --portal-shadow-menu: 0 8px 24px rgba(0, 0, 0, 0.12);
  --portal-shadow-lift: 0 6px 18px rgba(0, 0, 0, 0.16);
  --portal-focus-ring: 0 0 0 3px var(--portal-teal-ring);

  /* --- Sizes */
  --portal-control: 2.75rem;        /* a field, a form's button */
  --portal-control-sm: 2.5rem;      /* a toolbar's button, a search box */
  --portal-control-xs: 1.75rem;     /* a card's own small button */
  --portal-measure: 76rem;
  --portal-gutter: 3.5rem;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font: 400 var(--portal-text-15)/1.7 var(--portal-ui);
  color: var(--portal-body);
  background: var(--portal-surface);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  margin: 0 0 0.5rem;
  font-family: var(--portal-display);
  font-weight: 400;
  line-height: 1.06;
  color: var(--portal-ink);
}

h1 { font-size: var(--portal-text-50); }
h2 { font-size: var(--portal-text-22); }

a { color: var(--portal-ink); text-decoration: none; }
a:hover { color: var(--portal-muted); }

:focus-visible { outline: 2px solid var(--portal-ink); outline-offset: 3px; }

/* A label the eye skips until it needs it: small, tracked, upper case. */
.portal-eyebrow {
  margin: 0 0 0.75rem;
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--portal-faint);
}

.portal-lede {
  margin: 0 0 1.5rem;
  max-width: 34rem;
  color: var(--portal-muted);
}

/* ---------------------------------------------------------------- header */

.portal-header {
  display: flex;
  align-items: center;
  gap: 3rem;
  padding: 1.375rem var(--portal-gutter);
  border-bottom: 1px solid var(--portal-rule);
}

.portal-brand { position: relative; display: inline-flex; flex: none; align-items: center; }
/* Off Home, a small arrow in the gutter says the logo goes back there. It hangs
   outside the link's box, so the logo never moves. */
.portal-brand-home {
  position: absolute;
  right: calc(100% + 0.5rem);
  font-size: var(--portal-text-14);
  line-height: 1;
  color: var(--portal-faint);
}
.portal-brand:hover .portal-brand-home { color: var(--portal-ink); }
.portal-brand img { height: 36px; width: auto; display: block; }

/* The function on screen (partials/function_nav.html): its name, a size under the
   logo, then its tabs. Functions are picked from Home, so there is no row of them. */
.portal-function {
  display: flex;
  align-items: center;
  gap: 0.5rem 2rem;
  min-width: 0;
  /* Close to the logo: the header's own gap would push it too far off. */
  margin-left: -1.5rem;
  padding-left: 1.5rem;
  border-left: 1px solid var(--portal-rule-strong);
}
.portal-function-name {
  font: 400 var(--portal-text-20)/1.1 var(--portal-display);
  color: var(--portal-ink);
  white-space: nowrap;
}
.portal-function-name:hover { color: var(--portal-ink); }
/* The tabs give way before the Partner menu does: short of room, they scroll
   sideways rather than run under it (and under 60rem they get a line of their own). */
.portal-function-tabs {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: thin;
}
.portal-function-tabs a {
  padding: 0.25rem 0;
  font-size: var(--portal-text-13);
  font-weight: 500;
  color: var(--portal-muted);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}
/* Reports (crm slice 56) is a tab that opens a menu of reports: it reads as a tab. */
.portal-function-tabs .portal-reports-button {
  display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0;
  font: inherit; font-size: var(--portal-text-13); font-weight: 500; color: var(--portal-muted); white-space: nowrap;
  background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer;
}
.portal-function-tabs .portal-reports-button:focus-visible { outline: none; box-shadow: var(--portal-focus-ring); }
.portal-reports-menu { width: max-content; min-width: 11rem; }
.portal-function-tabs a:hover,
.portal-function-tabs .portal-reports-button:hover { color: var(--portal-ink); }
.portal-function-tabs .portal-reports-button[aria-current="page"],
.portal-function-tabs a[aria-current="page"] {
  font-weight: 600;
  color: var(--portal-ink);
  border-bottom-color: var(--portal-ink);
}
.portal-header .portal-partner-menu { margin-left: auto; }
/* A count beside a tab or a menu line, such as the Unmatched a WLCA rep has to file
   (conversations slice 04): a small black pill, as the bell's. */
.portal-tab-count {
  display: inline-block;
  min-width: 1.125rem;
  margin-left: 0.25rem;
  padding: 0 0.3rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  line-height: 1.125rem;
  text-align: center;
  color: var(--portal-surface);
  background: var(--portal-ink);
  border-radius: var(--portal-pill);
}
/* With nothing to count it takes no room: a tab without one sits as close as the rest. */
.portal-tab-count[hidden] { display: none; }

/* The bell (notifications slice 01): beside the user menu, its unread count a small
   black badge on its shoulder. The user menu keeps its own place at the far right. */
.portal-header .portal-bell-box { margin-left: auto; margin-right: -1.75rem; }
.portal-bell-box { position: relative; flex: none; }
.portal-bell {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  padding: 0.375rem;
  font: inherit;
  color: var(--portal-muted);
  background: none;
  border: 0;
  border-radius: var(--portal-pill);
  cursor: pointer;
}
.portal-bell:hover,
.portal-bell[aria-expanded="true"] { color: var(--portal-ink); }
.portal-bell[aria-expanded="true"] { background: var(--portal-hover); }
.portal-bell:focus-visible { outline: none; box-shadow: var(--portal-focus-ring); }
.portal-bell-count {
  position: absolute;
  top: -0.125rem;
  right: -0.375rem;
  min-width: 1.125rem;
  padding: 0 0.3rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  line-height: 1.125rem;
  text-align: center;
  color: var(--portal-surface);
  background: var(--portal-ink);
  border-radius: var(--portal-pill);
}
.portal-bell-count[hidden] { display: none; }
.portal-header .portal-bell-box ~ .portal-partner-menu { margin-left: 0; }
/* A WLCA rep's Inbox (conversations slice 27): a tray before the bell, as the bell is,
   its Waiting on you count on its shoulder. It takes the bell's place at the far end of
   the left, and the bell steps in beside it. */
.portal-top-inbox {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  padding: 0.375rem;
  color: var(--portal-muted);
  border-radius: var(--portal-pill);
}
.portal-top-inbox:hover,
.portal-top-inbox[aria-current="page"] { color: var(--portal-ink); }
.portal-top-inbox:focus-visible { outline: none; box-shadow: var(--portal-focus-ring); }
.portal-top-inbox .portal-bell-count[hidden] { display: none; }
.portal-header .portal-top-inbox { margin-left: auto; margin-right: -2.25rem; }
.portal-header .portal-top-inbox ~ .portal-bell-box { margin-left: 0; }

/* The bell's panel, as Facebook's: under the bell, its right edge under the bell's
   (notifications/js/bell.js places it, kept inside the window); the newest few, All
   or Unread, Mark all read and See all. Only script opens it. */
.portal-bell-panel {
  position: fixed;
  z-index: 30;
  width: min(23rem, calc(100vw - 1rem));
  max-height: calc(100vh - 6rem);
  overflow: auto;
  color: var(--portal-body);
  background: var(--portal-surface);
  border: 1px solid var(--portal-rule-strong);
  border-radius: var(--portal-radius-pop);
  box-shadow: var(--portal-shadow-menu);
  text-align: left;
}
.portal-bell-panel[hidden] { display: none; }
.portal-bell-panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1rem 0.25rem;
}
.portal-bell-panel-head h2 {
  margin: 0;
  font: 400 var(--portal-text-22)/1.2 var(--portal-display);
  color: var(--portal-ink);
}
.portal-bell-panel-head h2:focus { outline: none; }
.portal-bell-panel-head form { margin: 0; }
.portal-bell-panel-action {
  padding: 0;
  font: 500 var(--portal-text-13) var(--portal-ui);
  color: var(--portal-teal);
  background: none;
  border: 0;
  cursor: pointer;
}
.portal-bell-panel-action:hover,
.portal-bell-panel-action:focus-visible { text-decoration: underline; }
.portal-bell-panel-slot { padding: 0.5rem 1rem 0; }
.portal-bell-panel-slot:empty { display: none; }
.portal-bell-panel-tabs { display: flex; gap: 0.375rem; padding: 0.5rem 1rem 0.625rem; }
.portal-bell-panel-tabs button {
  padding: 0.25rem 0.875rem;
  font: 500 var(--portal-text-13) var(--portal-ui);
  color: var(--portal-body);
  background: none;
  border: 0;
  border-radius: var(--portal-pill);
  cursor: pointer;
}
.portal-bell-panel-tabs button:hover { background: var(--portal-hover); }
.portal-bell-panel-tabs button[aria-pressed="true"] { color: var(--portal-surface); background: var(--portal-ink); }
.portal-bell-panel-tabs button:focus-visible,
.portal-bell-panel-all:focus-visible,
.portal-bell-row a:focus-visible { outline: none; box-shadow: var(--portal-focus-ring); }
.portal-bell-panel-list { margin: 0; padding: 0 0.5rem; list-style: none; }
.portal-bell-row a {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.125rem 0.75rem;
  align-items: center;
  padding: 0.625rem 0.5rem;
  color: var(--portal-body);
  text-decoration: none;
  border-radius: var(--portal-radius-pop);
}
.portal-bell-row a:hover { background: var(--portal-hover-faint); }
.portal-bell-row-title { grid-column: 1; font-size: var(--portal-text-14); color: var(--portal-ink); }
.portal-bell-row.is-unread .portal-bell-row-title { font-weight: 600; }
.portal-bell-row-line {
  grid-column: 1;
  overflow: hidden;
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.portal-bell-row-when { grid-column: 1; font-size: var(--portal-text-12); color: var(--portal-faint); }
.portal-bell-row.is-unread .portal-bell-row-when { font-weight: 600; color: var(--portal-teal); }
.portal-bell-row-dot {
  grid-column: 2;
  grid-row: 1 / span 3;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: var(--portal-round);
  background: var(--portal-teal);
}
.portal-bell-panel-empty { margin: 0; padding: 1.5rem 1rem; font-size: var(--portal-text-14); color: var(--portal-muted); }
.portal-bell-panel-all {
  display: block;
  margin: 0.25rem 0.5rem 0.5rem;
  padding: 0.625rem;
  font-size: var(--portal-text-14);
  font-weight: 500;
  text-align: center;
  color: var(--portal-ink);
  background: var(--portal-panel);
  border-radius: var(--portal-radius-pop);
}
.portal-bell-panel-all:hover { background: var(--portal-badge); }

/* Words for a screen reader alone. */
.portal-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* My Notifications: one row each, newest first; an unread one has a dot and bold title. */
.portal-notifications { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--portal-rule); }
.portal-notification { border-bottom: 1px solid var(--portal-rule); }
.portal-notification a {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.25rem 1.5rem;
  padding: 1rem 0.75rem;
  color: var(--portal-body);
}
.portal-notification a:hover { background: var(--portal-hover-faint); }
.portal-notification-title { display: flex; align-items: center; gap: 0.5rem; font-size: var(--portal-text-14); color: var(--portal-ink); }
.portal-notification.is-unread .portal-notification-title { font-weight: 600; }
.portal-notification-dot { width: 0.5rem; height: 0.5rem; flex: none; border-radius: var(--portal-round); background: var(--portal-ink); }
.portal-notification-line { grid-column: 1; font-size: var(--portal-text-13); color: var(--portal-muted); }
.portal-notification-when { grid-column: 2; grid-row: 1 / span 2; align-self: center; font-size: var(--portal-text-12); color: var(--portal-faint); white-space: nowrap; }

/* Notification choices (notifications slice 03): one row per Kind, one tick per Channel. */
.portal-notification-choices { display: grid; gap: 1.5rem; justify-items: start; }
.portal-notification-choices .portal-list-table { width: 100%; }
.portal-notification-choices th[scope="row"] { font-weight: 500; }
.portal-choice-channel { width: 6rem; text-align: center; }
.portal-choice-channel label { display: inline-flex; padding: 0.25rem; cursor: pointer; }
.portal-choice-channel input { width: 1.05rem; height: 1.05rem; accent-color: var(--portal-ink); }
.portal-choice-channel input:disabled { cursor: not-allowed; opacity: 0.55; }
.portal-choice-reason { display: block; margin-top: 0.125rem; font-size: var(--portal-text-12); font-weight: 400; color: var(--portal-muted); }

/* The Partner a Partner user is signed in under: the one thing on a shared computer
   that must never be a guess, so it is read off the chrome without opening
   anything -- and it is the button everything about signing in hangs from. */
.portal-partner-menu > summary {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.125rem;
  font-size: var(--portal-text-13);
  line-height: 1.35;
  white-space: nowrap;
}
/* No disclosure triangle on this one: the name is the button, and the caret
   sits beside it rather than in front of a two-line block. */
.portal-partner-menu > summary { list-style: none; }
.portal-partner-menu > summary::-webkit-details-marker { display: none; }
.portal-partner-name::after { content: " ▾"; color: var(--portal-faint); }
.portal-partner-name { font-weight: 600; color: var(--portal-ink); }
.portal-user { font-size: var(--portal-text-12); color: var(--portal-muted); }

/* Whose signing-in this is, above the things it lets them do. */
.portal-menu-head {
  margin: 0 0 0.875rem;
  padding-bottom: 0.875rem;
  font-size: var(--portal-text-12);
  color: var(--portal-faint);
  border-bottom: 1px solid var(--portal-rule);
}
.portal-menu-links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.875rem;
}
.portal-menu-links a,
.portal-signout button {
  font-family: inherit;
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-faint);
}
.portal-menu-links a:hover,
.portal-signout button:hover { color: var(--portal-ink); }

.portal-signout { margin: 0; }
.portal-signout button { padding: 0; border: 0; background: none; cursor: pointer; }

/* ----------------------------------------------------------------- main */

.portal-main {
  flex: 1;
  width: 100%;
  max-width: var(--portal-measure);
  margin: 0 auto;
  padding: 3.5rem var(--portal-gutter) 4rem;
}

.portal-page-head-actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex: none;
}

/* -------------------------------------------------------------- messages */

.portal-messages {
  width: 100%;
  max-width: var(--portal-measure);
  margin: 1.5rem auto -1.5rem;
  padding: 0 var(--portal-gutter);
  list-style: none;
}
.portal-messages li {
  padding: 0.875rem 1.125rem;
  margin-bottom: 0.5rem;
  background: var(--portal-panel);
  font-size: var(--portal-text-14);
}
.portal-messages li.error { background: var(--portal-danger-wash); color: var(--portal-danger); }

/* ----------------------------------------------------------------- forms

   One look for every form (partials/form_field.html): a plain name on each field, its
   hint before the box, boxes you can see, choices as tiles to click, and only the
   optional fields marked, since most are needed. Hairlines and pills stay the kit's;
   a field is the one place a box is drawn, because an empty underline reads as nothing. */

.portal-form { max-width: 30rem; }

.portal-field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  min-width: 0;
  margin: 0 0 1.25rem;
  padding: 0;
  border: 0;
}

.portal-field-label {
  display: block;
  margin: 0;
  padding: 0;
  font-size: var(--portal-text-14);
  font-weight: 600;
  line-height: 1.4;
  color: var(--portal-ink);
}
.portal-field-optional {
  margin-left: 0.375rem;
  font-size: var(--portal-text-13);
  font-weight: 400;
  color: var(--portal-muted);
}

.portal-field .helptext {
  display: block;
  margin: 0;
  font-size: var(--portal-text-13);
  line-height: 1.45;
  color: var(--portal-muted);
}
.portal-field .helptext ul { margin: 0; padding-left: 1.1rem; }

.portal-field input:not([type="radio"], [type="checkbox"], [type="file"]),
.portal-field select,
.portal-field textarea,
.portal-input {
  display: block;
  width: 100%;
  height: var(--portal-control);
  margin: 0;
  padding: 0 0.75rem;
  font: 400 var(--portal-text-15)/1.5 var(--portal-ui);
  color: var(--portal-ink);
  background-color: var(--portal-surface);
  border: 1px solid var(--portal-edge);
  border-radius: var(--portal-radius);
}
/* The same box for an input that stands outside a field, sized for a card's toolbar
   (a files card's Kind). */
.portal-input { width: auto; height: var(--portal-control-sm); font-size: var(--portal-text-14); }
/* Grows downwards only, so dragging it never breaks the column it sits in. */
.portal-field textarea {
  height: auto;
  min-height: 5.5rem;
  padding: 0.625rem 0.75rem;
  resize: vertical;
}
.portal-field select,
select.portal-input {
  appearance: none;
  padding-right: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'%3E%3Cpath d='M3 5.5l4 4 4-4' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 14px;
}
.portal-field input::placeholder,
.portal-field textarea::placeholder { color: var(--portal-ghost); }
.portal-field input:not([type="radio"], [type="checkbox"], [type="file"]):hover,
.portal-field select:hover,
.portal-field textarea:hover,
.portal-input:hover { border-color: var(--portal-edge-hover); }
.portal-field input:not([type="radio"], [type="checkbox"], [type="file"]):focus,
.portal-field select:focus,
.portal-field textarea:focus,
.portal-input:focus {
  outline: none;
  border-color: var(--portal-teal);
  box-shadow: var(--portal-focus-ring);
}
.portal-field input:disabled,
.portal-field select:disabled,
.portal-field textarea:disabled {
  color: var(--portal-muted);
  background-color: var(--portal-disabled);
  border-color: var(--portal-edge-disabled);
  cursor: default;
}

.portal-field--invalid input:not([type="radio"], [type="checkbox"], [type="file"]),
.portal-field--invalid select,
.portal-field--invalid textarea { border-color: var(--portal-danger); }

/* A choice of a few (a Lost reason, who reached whom, delivery or pickup): tiles two to
   a row, the chosen one outlined in black. A single tick box is one tile of its own. */
.portal-field--choice > div {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
}
.portal-field--choice > div > div { display: flex; }
.portal-field--choice label,
.portal-tile {
  display: flex;
  flex: 1;
  align-items: flex-start;
  gap: 0.625rem;
  min-height: 3rem;
  margin: 0;
  padding: 0.75rem 0.875rem;
  font-size: var(--portal-text-15);
  font-weight: 400;
  line-height: 1.4;
  color: var(--portal-ink);
  background: var(--portal-surface);
  border: 1px solid var(--portal-edge-soft);
  border-radius: var(--portal-radius);
  cursor: pointer;
}
.portal-field--choice label:hover,
.portal-tile:hover { border-color: var(--portal-edge-hover); }
.portal-field--choice label:has(input:checked),
.portal-tile:has(input:checked) {
  background: var(--portal-chosen);
  border-color: var(--portal-ink);
  box-shadow: inset 0 0 0 1px var(--portal-ink);
}
.portal-field--choice label:has(input:focus-visible),
.portal-tile:has(input:focus-visible) { outline: 2px solid var(--portal-teal); outline-offset: 2px; }
.portal-field--choice input,
.portal-tile input {
  flex: none;
  width: 1rem;
  height: 1rem;
  margin: 0.125rem 0 0;
  accent-color: var(--portal-ink);
}
.portal-tile small.helptext { margin-top: 0.125rem; }
.portal-field--invalid .portal-tile,
.portal-field--invalid.portal-field--choice label { border-color: var(--portal-danger); }
@media (max-width: 30rem) {
  .portal-field--choice > div { grid-template-columns: minmax(0, 1fr); }
}

/* A file to send (a Settings logo): its button a small outlined pill. */
.portal-field input[type="file"] {
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
  cursor: pointer;
}
.portal-field input[type="file"]::file-selector-button {
  margin-right: 1rem;
  height: var(--portal-control-sm);
  padding: 0 1.125rem;
  font: 600 var(--portal-text-13) var(--portal-ui);
  color: var(--portal-ink);
  background: var(--portal-surface);
  border: 0;
  box-shadow: inset 0 0 0 1px var(--portal-edge);
  border-radius: var(--portal-pill);
  cursor: pointer;
}
.portal-field input[type="file"]:hover::file-selector-button { box-shadow: inset 0 0 0 1px var(--portal-ink); }
.portal-field input[type="file"]:disabled,
.portal-field input[type="file"]:disabled::file-selector-button { cursor: default; opacity: 0.6; }
/* The kept logo, shown above its file input, and the tick that removes it. */
.portal-logo-preview {
  display: block;
  max-width: 12rem;
  max-height: 4rem;
  margin: 0 0 0.5rem;
}
.portal-field label.portal-logo-remove {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.5rem;
  font-size: var(--portal-text-14);
  color: var(--portal-body);
  cursor: pointer;
}
.portal-field .portal-logo-remove input[type="checkbox"] {
  width: auto;
  height: auto;
  margin: 0;
  accent-color: var(--portal-ink);
}

/* What was wrong, under the box, behind a small warning mark. */
ul.errorlist {
  margin: 0 0 0.75rem;
  padding: 0;
  list-style: none;
  font-size: var(--portal-text-13);
  line-height: 1.45;
  color: var(--portal-danger);
}
.portal-field ul.errorlist { margin: 0; }
.portal-field ul.errorlist li { display: flex; align-items: flex-start; gap: 0.375rem; }
.portal-field ul.errorlist li::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 0.125rem;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Ccircle cx='7' cy='7' r='6.25' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M7 3.8v4M7 9.6v.6' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Ccircle cx='7' cy='7' r='6.25' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M7 3.8v4M7 9.6v.6' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}
ul.errorlist.nonfield {
  margin-bottom: 1.25rem;
  padding: 0.75rem 0.875rem;
  background: var(--portal-danger-wash);
  border-radius: var(--portal-radius);
}

/* A group of fields under its own name (a Settings section). */
.portal-form-group-title { margin: 0 0 0.25rem; font: 400 var(--portal-text-20)/1.3 var(--portal-display); color: var(--portal-ink); }

/* A line the form says before its fields, in the teal of the portal's notes. */
.portal-note {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  margin: 0 0 1.25rem;
  padding: 0.75rem 0.875rem;
  font-size: var(--portal-text-14);
  line-height: 1.5;
  color: var(--portal-note-ink);
  background: var(--portal-note);
  border-radius: var(--portal-radius);
}

.portal-button,
.portal-form button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 3.25rem;
  padding: 0 2.125rem;
  font-family: inherit;
  font-size: var(--portal-text-12);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-surface);
  background: var(--portal-ink);
  border: 0;
  border-radius: var(--portal-pill);
  cursor: pointer;
  white-space: nowrap;
}
.portal-button:hover,
.portal-form button[type="submit"]:hover { background: var(--portal-ink-hover); color: var(--portal-surface); }
/* A form's own buttons: the one action black, a second one outlined, one that cannot
   be undone red, and Cancel plain text. */
.portal-form button[type="submit"],
.portal-form .portal-button {
  height: var(--portal-control);
  padding: 0 1.5rem;
  font-size: var(--portal-text-14);
  letter-spacing: 0;
  text-transform: none;
  border-radius: var(--portal-pill);
}
.portal-form button.portal-button--line,
.portal-button--line { color: var(--portal-ink); background: var(--portal-surface); box-shadow: inset 0 0 0 1px var(--portal-edge); }
.portal-form button.portal-button--line:hover,
.portal-button--line:hover { color: var(--portal-ink); background: var(--portal-surface); box-shadow: inset 0 0 0 1px var(--portal-ink); }
.portal-form button.portal-button--danger,
.portal-button--danger { background: var(--portal-danger); }
.portal-form button.portal-button--danger:hover,
.portal-button--danger:hover { background: var(--portal-danger-strong); }

.portal-form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.75rem;
}
.portal-quiet { font-size: var(--portal-text-13); color: var(--portal-muted); }
.portal-form-actions .portal-quiet {
  display: inline-flex;
  align-items: center;
  height: var(--portal-control);
  padding: 0 0.875rem;
  font: 500 var(--portal-text-14) var(--portal-ui);
  color: var(--portal-body);
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
}
.portal-form-actions .portal-quiet:hover { color: var(--portal-ink); text-decoration: underline; }

/* ------------------------------------------------------------ sign-in page

   The one screen a Partner user meets before the shell means anything: it drops the
   shell, keeps the sheet on the left, and gives the right half to a kitchen. */

.portal-auth {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 860fr) minmax(0, 580fr);
  max-width: none;
  padding: 0;
}

.portal-auth-sheet {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 2.5rem;
  padding: 2.75rem 4.5rem 2.5rem;
}

.portal-auth-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}
.portal-auth-top img { height: 34px; width: auto; display: block; }
.portal-auth-kicker {
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--portal-faint);
}

.portal-auth-body { max-width: 35rem; }
.portal-auth-body h1 { font-size: var(--portal-text-62); }
.portal-auth-body .portal-lede { max-width: 27rem; margin-bottom: 2.5rem; }

.portal-auth-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2.5rem;
  max-width: 32.5rem;
}
.portal-auth-fields .portal-field { margin: 0; }

.portal-auth .portal-form { max-width: none; }
.portal-auth-actions {
  display: flex;
  align-items: center;
  gap: 1.75rem;
  margin-top: 2.5rem;
}

.portal-auth-register {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.625rem;
  margin: 2.5rem 0 0;
  padding-top: 1.625rem;
  border-top: 1px solid var(--portal-rule);
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
}
.portal-auth-register a {
  font-weight: 500;
  border-bottom: 1px solid var(--portal-rule-strong);
  padding-bottom: 1px;
}

.portal-auth-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  font-size: var(--portal-text-11);
  color: var(--portal-faint);
}

.portal-auth-view { position: relative; background: var(--portal-panel); overflow: hidden; }
.portal-auth-view img { width: 100%; height: 100%; object-fit: cover; display: block; }
.portal-auth-caption {
  position: absolute;
  left: 2rem;
  bottom: 2rem;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 1rem;
  background: var(--portal-veil);
  font-size: var(--portal-text-11);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--portal-body);
}
.portal-swatch { width: 12px; height: 12px; border-radius: var(--portal-round); display: inline-block; }

/* ------------------------------------------------------------- page parts */

.portal-page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 3rem;
  margin-bottom: 2.5rem;
}
.portal-page-head p { margin: 0.75rem 0 0; color: var(--portal-muted); font-size: var(--portal-text-14); }

/* Who started a thing and when it was last touched: true, useful once, and
   never the reason anyone opened the screen. It is set small and grey and it
   stays there. */
.portal-meta { margin: 0.75rem 0 0; font-size: var(--portal-text-13); color: var(--portal-faint); }

/* One number the screen is answerable for, under its section head. */
.portal-total { margin: 0.75rem 0 2.5rem; font-size: var(--portal-text-15); color: var(--portal-body); }

.portal-split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 5rem;
  align-items: start;
}

.portal-panel { background: var(--portal-panel); padding: 1.5rem 1.625rem; }
.portal-panel .portal-eyebrow { margin-bottom: 0.875rem; }

.portal-checklist { margin: 0; padding: 0; list-style: none; }
.portal-checklist li {
  padding: 0.625rem 0;
  border-top: 1px solid var(--portal-rule);
  font-size: var(--portal-text-14);
  line-height: 1.5;
  color: var(--portal-body);
}

/* Rows, not tiles: a rule under each, nothing boxed. */
.portal-rows { border-top: 1px solid var(--portal-rule-strong); }
.portal-row {
  display: flex;
  align-items: center;
  gap: 1.375rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--portal-rule);
}
.portal-row-index { font-size: var(--portal-text-11); letter-spacing: 0.12em; color: var(--portal-ghost); }
.portal-row-name {
  width: 12rem;
  font-family: var(--portal-display);
  font-size: var(--portal-text-22);
  color: var(--portal-ink);
}
.portal-row-note { flex: 1; font-size: var(--portal-text-14); color: var(--portal-muted); }
.portal-row-state {
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-ghost);
}

.portal-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
}
.portal-section-head .portal-eyebrow { margin-bottom: 0; }
.portal-section-note { font-size: var(--portal-text-12); color: var(--portal-ghost); }

/* The look-book band: one wide photograph, the width of the page, with its
   caption on the rule beneath it. Nothing sits beside it. */
.portal-lookbook { margin: 3rem 0 0; }
.portal-lookbook img {
  width: 100%;
  height: 26rem;
  object-fit: cover;
  display: block;
  background: var(--portal-panel);
}
.portal-lookbook figcaption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: 0.75rem;
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
}

/* ---------------------------------------------------------------- footer */

.portal-footer {
  padding: 1.25rem var(--portal-gutter);
  border-top: 1px solid var(--portal-rule);
  font-size: var(--portal-text-11);
  color: var(--portal-faint);
}
.portal-footer p {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  width: 100%;
  max-width: var(--portal-measure);
  margin: 0 auto;
}

/* -------------------------------------------------------- the price list

   Rows and hairlines, like everything else here: no cards, no zebra. The two
   price columns sit hard right against each other so a margin is read in one
   glance, and they are tabular figures so the digits line up down the column. */

/* A row on Home that leads somewhere -- the module has opened -- reads as a
   link on hover; the ones still to come are plain divs and stay inert. */
a.portal-row:hover .portal-row-name,
a.portal-row:hover .portal-row-state { color: var(--portal-muted); }

.portal-browse {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 2rem 2.5rem;
  margin: 0 0 3rem;
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--portal-rule-strong);
}
.portal-browse .portal-field { margin: 0; min-width: 14rem; }
.portal-browse-actions { display: flex; align-items: center; gap: 1.5rem; }
.portal-browse .portal-button { height: var(--portal-control); }

.portal-price-source { margin: 0.75rem 0 0; font-size: var(--portal-text-13); color: var(--portal-muted); }
.portal-price-source--waiting { color: var(--portal-danger); }

.portal-price-group { margin-top: 3rem; }
.portal-price-type {
  margin: 1.5rem 0 0.5rem;
  font-size: var(--portal-text-18);
}

/* Wide content scrolls inside its own box; the page itself never does. */
.portal-scroll { overflow-x: auto; }

/* The Projects and Designs lists are the same table (`projects & designs`, below):
   one look for every list of rows the portal renders. */
.portal-price-table,
.portal-list-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--portal-text-14);
}
.portal-price-table th,
.portal-price-table td,
.portal-list-table th,
.portal-list-table td {
  padding: 0.625rem 1rem 0.625rem 0;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--portal-rule);
}
.portal-price-table thead th,
.portal-list-table thead th {
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-faint);
  border-bottom: 1px solid var(--portal-rule-strong);
  white-space: nowrap;
}
.portal-price-table tbody th,
.portal-list-table tbody th {
  font-weight: 600;
  color: var(--portal-ink);
}
.portal-price-table tbody th a,
.portal-list-table tbody th a { border-bottom: 1px solid var(--portal-rule-strong); }

/* A WLCA rep's search, under the tab's own matches: the other tabs' matches, apart. */
.portal-list-elsewhere {
  margin: 2rem 0 0.5rem;
  font-size: var(--portal-text-14);
  font-weight: 600;
  color: var(--portal-ink);
}

.portal-price-table .portal-price {
  padding-right: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.portal-price--partner { font-weight: 600; color: var(--portal-ink); }
.portal-price--retail { color: var(--portal-muted); }
.portal-price-unknown { color: var(--portal-ghost); }

/* Greyed, not gone: the cabinet is still there to be read, and the reason it
   cannot be bought today is in the row (US8). */
.portal-price-row--unavailable > * { color: var(--portal-ghost); }

/* Something the Partner user is told, not something they do: a line on the panel's
   own grey, above the table it changes the meaning of. */
.portal-notice {
  margin: 1.25rem 0 0;
  padding: 0.75rem 1rem;
  font-size: var(--portal-text-13);
  color: var(--portal-body);
  background: var(--portal-panel);
}
.portal-price-row--unavailable .portal-cabinet-picture { opacity: 0.35; }
.portal-price-unavailable { text-align: right; font-size: var(--portal-text-13); }

.portal-price-row--chosen > * { background: var(--portal-panel); }
.portal-price-row--total th { font-weight: 600; }
.portal-price-row--total > * { border-bottom: 1px solid var(--portal-rule-strong); }

/* The cabinet's own proportions, in the Color of the Door design, divided
   into the panels its Structure says its face has. The ratio, the fill and
   each panel's place are inline, because all of them come from the row. */
.portal-cabinet-picture {
  position: relative;
  display: inline-block;
  width: 2.25rem;
  max-height: 3rem;
  margin-right: 0.75rem;
  vertical-align: middle;
  background: var(--portal-panel);
  background-size: cover;
  border: 1px solid var(--portal-rule-strong);
}

/* Each panel is drawn as a hairline outline over the Color, so what a Partner user
   sees is the arrangement -- two doors, a drawer above them -- and not a
   second colour scheme of the picture's own. The outline is translucent black
   rather than a portal token, because it sits on whatever the Door design's
   Color is: a fixed ink would vanish on Navy and shout on White. */
.portal-cabinet-panel {
  position: absolute;
  box-sizing: border-box;
  border: 1px solid var(--portal-draw-line);
}
.portal-cabinet-panel--drawer { border-color: var(--portal-edge-hover); }
.portal-cabinet-panel--blind_panel,
.portal-cabinet-panel--open {
  border-style: dashed;
  background: var(--portal-draw-open);
}
.portal-cabinet-panel--toe_kick { background: var(--portal-draw-toe-kick); }
.portal-cabinet-panel--rail { border-style: solid; }
.portal-cabinet-picture-large { margin: 0 0 1rem; }
.portal-cabinet-picture-large .portal-cabinet-picture {
  width: 11rem;
  max-height: 15rem;
  margin: 0;
}

/* ---------------------------------------------------------- projects & designs

   My projects, a Project's screen and a Design's home. The table is the price list's,
   so what is here is only what these screens have of their own: a Snapshot in
   the first column, the actions on a row, and the project read as facts. */

/* Where a Design's Snapshot goes. Fixed size whether there is a picture or
   not, so the list does not jump about as Snapshots arrive. */
.portal-row-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1.5rem;
  margin: 1.5rem 0 0;
}
.portal-list-table .portal-row-actions { margin: 0; }
.portal-row-actions form { margin: 0; }
/* A row's own actions sitting above a section of their own -- a Project's, above
   the section listing its Designs -- need air, or the two rows of small caps
   read as one. */
.portal-row-actions + .portal-section-head { margin-top: 2.75rem; }

/* An action on a row: the underlined word, not a pill. The black pill is for
   the one thing a screen is for -- New design, Start this design. */
.portal-inline-button {
  padding: 0;
  font-family: inherit;
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--portal-rule-strong);
  cursor: pointer;
}
.portal-inline-button:hover { color: var(--portal-ink); }
.portal-inline-button--danger {
  color: var(--portal-danger);
  border-bottom-color: var(--portal-danger);
}

/* An action that opens a form before it does anything, and no JavaScript in
   any of it: the summary opens the panel, the button inside it acts. Renaming
   needs a field; deleting cannot be undone, and neither belongs on a stray
   click. */
.portal-disclosure summary,
.portal-danger-disclosure summary {
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
  cursor: pointer;
}
.portal-disclosure summary:hover,
.portal-danger-disclosure summary:hover { color: var(--portal-ink); }
.portal-disclosure > form,
.portal-danger-disclosure > form {
  margin: 0.75rem 0 0;
  padding: 0.875rem 1rem;
  background: var(--portal-panel);
}
.portal-disclosure > form .portal-field { margin: 0 0 1rem; min-width: 11rem; }

/* The one whose panel is the colour of the thing it does. */
.portal-danger-disclosure[open] summary { color: var(--portal-danger); }
.portal-danger-disclosure > form { background: var(--portal-danger-wash); }
.portal-danger-disclosure > form p {
  margin: 0 0 0.625rem;
  font-size: var(--portal-text-13);
  color: var(--portal-danger);
}

/* The project, as facts rather than as a form: a Design's home is read before any
   of it is edited. */
.portal-facts { margin: 0; }
.portal-facts dt {
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-faint);
}
.portal-facts dd {
  margin: 0.375rem 0 1.25rem;
  padding-bottom: 1.25rem;
  font-size: var(--portal-text-15);
  color: var(--portal-body);
  border-bottom: 1px solid var(--portal-rule);
}
.portal-facts dd:last-of-type { margin-bottom: 2rem; border-bottom: 0; }

/* A screen's other actions, folded into one word. `details` opens it, so the
   menu needs no JavaScript and closes itself on Escape like any disclosure. */
.portal-menu { position: relative; }
.portal-menu > summary {
  font-size: var(--portal-text-13);
  color: var(--portal-muted);
  cursor: pointer;
  white-space: nowrap;
}
.portal-menu > summary:hover { color: var(--portal-ink); }
.portal-menu-panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.75rem);
  right: 0;
  width: 17rem;
  padding: 1.125rem 1.25rem;
  background: var(--portal-surface);
  border: 1px solid var(--portal-rule-strong);
  text-align: left;
}
/* Stacked in the panel, one action to a line -- the row layout this partial
   wears inside a table would read as a paragraph in here. */
.portal-menu-panel .portal-row-actions {
  flex-direction: column;
  align-items: stretch;
  gap: 0.875rem;
  margin: 0.875rem 0 0;
}
.portal-menu-panel .portal-inline-button,
.portal-menu-panel summary { display: inline-block; }
.portal-menu-panel .portal-quiet { margin: 1rem 0 0; }

/* A panel over the screen, opened by `:target` and closed by the scrim, the
   Close, or the browser's own back -- no JavaScript in any of it. */
.portal-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 60;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1.5rem;
  overflow-y: auto;
}
.portal-modal:target { display: flex; }
.portal-modal-scrim {
  position: fixed;
  inset: 0;
  background: var(--portal-scrim-strong);
}
.portal-modal-panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 52rem;
  padding: 2rem 2.25rem 2.5rem;
  background: var(--portal-surface);
  border: 1px solid var(--portal-rule-strong);
}
.portal-modal-close {
  position: absolute;
  top: 1.5rem;
  right: 2.25rem;
  font-size: var(--portal-text-12);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-muted);
}
.portal-modal-close:hover { color: var(--portal-ink); }
.portal-modal-panel .portal-price-table { margin-top: 1rem; }

/* ----------------------------------------------------------------- print

   A price list a Partner user hands to a customer: the page and the numbers, and
   none of the chrome that only means something on a screen. */

@media print {
  .portal-header,
  .portal-footer,
  .portal-messages,
  .portal-browse,
  .portal-page-head .portal-quiet { display: none; }

  .portal-main { max-width: none; padding: 0; }
  .portal-scroll { overflow-x: visible; }
  .portal-price-table { font-size: var(--portal-text-12); }
  .portal-price-table tbody th a { border-bottom: 0; }
  /* A cabinet is read as a whole or on the next page, never split in half. */
  .portal-price-table tr,
  .portal-price-group { break-inside: avoid; }
  .portal-price-table thead { display: table-header-group; }
}

/* ---------------------------------------------------------------- narrow */

@media (max-width: 64rem) {
  :root { --portal-gutter: 2rem; }
  .portal-auth { grid-template-columns: minmax(0, 1fr); }
  /* The kitchen is atmosphere, not information: it goes first on a phone. */
  .portal-auth-view { order: -1; height: 14rem; }
  .portal-auth-sheet { padding: 2rem 2rem 2.5rem; }
  .portal-auth-body h1 { font-size: var(--portal-text-44); }
  .portal-split { gap: 2.5rem; grid-template-columns: minmax(0, 1fr); }
  .portal-lookbook img { height: 18rem; }
  h1 { font-size: var(--portal-text-40); }
}

/* Six tabs or more (a Reports menu counts as one tab, crm slice 56) do not fit beside
   the logo on a laptop, so there the function takes the line of its own it takes below
   60rem, rather than scroll its last tabs out of sight; a CRM screen's header band is
   that much taller. */
@media (max-width: 100rem) {
  .portal-header:has(.portal-function-tabs > :nth-child(6 of a, button)) { flex-wrap: wrap; gap: 0.5rem 1.5rem; }
  .portal-header:has(.portal-function-tabs > :nth-child(6 of a, button)) .portal-function {
    order: 3; width: 100%; margin-left: 0; padding-left: 0; border-left: 0; flex-wrap: wrap;
  }
  .portal-header:has(.portal-function-tabs > :nth-child(6 of a, button)) .portal-bell-box { margin-right: -0.75rem; }
  .portal-header:has(.portal-function-tabs > :nth-child(6 of a, button)) .portal-top-inbox { margin-right: -0.75rem; }
}
@media (min-width: 64rem) and (max-width: 100rem) {
  .portal-crm:has(.portal-function-tabs > :nth-child(6 of a, button)) { --crm-header-height: 7rem; }
}

/* Short of room for the function beside the logo and a long Partner name (a tablet, a
   narrow window), the function takes its own line under the logo, its tabs scrolling
   sideways. */
@media (max-width: 60rem) {
  .portal-header { flex-wrap: wrap; gap: 1rem 1.5rem; }
  .portal-function { order: 3; width: 100%; margin-left: 0; padding-left: 0; border-left: 0; flex-wrap: wrap; }
  .portal-partner-menu { margin-left: auto; }
  /* The header's gap is narrower here, so the bell steps in less to sit by the menu. */
  .portal-header .portal-bell-box { margin-right: -0.75rem; }
  .portal-header .portal-top-inbox { margin-right: -0.75rem; }
}

@media (max-width: 46rem) {
  .portal-user { display: none; }
  .portal-auth-fields { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .portal-auth-actions, .portal-form-actions { flex-wrap: wrap; gap: 1rem 1.5rem; }
  .portal-page-head { flex-direction: column; align-items: flex-start; gap: 1.25rem; }
  /* The head's actions move to the left edge on a phone, and the menu that
     hangs off them has to hang the same way or it opens off the screen. The
     Partner's menu stays at the right edge, where its name is. */
  .portal-menu-panel { width: min(17rem, calc(100vw - 4rem)); }
  .portal-page-head .portal-menu-panel { right: auto; left: 0; }
  .portal-modal { padding: 1.5rem 1rem; }
  .portal-modal-panel { padding: 1.5rem 1.25rem 2rem; }
  .portal-modal-close { top: 1.25rem; right: 1.25rem; }
  .portal-row { flex-wrap: wrap; gap: 0.5rem 1rem; }
  .portal-row-name { width: auto; }
  .portal-row-note { flex-basis: 100%; }
  .portal-footer p, .portal-auth-foot { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
}

/* -- A Project's designs, as cards -------------------------------------------
   One card per option (slice 47): the Snapshot, the name, the Retail total,
   when it was last edited and the newest PDF. The whole card opens the
   Planner -- the name's link is stretched over it -- and everything else sits
   in the menu in its corner, above that stretched link. */
.portal-design-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0 0;
}
.portal-design-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  padding: 1.25rem;
  border: 1px solid var(--portal-rule);
  background: var(--portal-surface, transparent);
}
.portal-design-card:hover { border-color: var(--portal-rule-strong); }
.portal-design-card-body { display: flex; flex-direction: column; gap: 0.375rem; }
/* The right padding keeps the name's corner clear of the Actions menu, which
   is lifted out of the flow so it sits above the stretched link. The name is
   the one line that reaches the top of the card, so it is the one that would
   otherwise run under it. */
.portal-design-card-name { margin: 0; padding-right: 5rem; font-size: var(--portal-text-16); }
.portal-design-card-open { color: inherit; text-decoration: none; }
/* What makes the whole card the link, without wrapping an anchor round the
   menu's buttons. */
.portal-design-card-open::after { position: absolute; inset: 0; content: ""; }
.portal-design-card-open:hover { text-decoration: underline; }
.portal-design-card-total { margin: 0; font-size: var(--portal-text-14); color: var(--portal-body); }
.portal-design-card-meta { margin: 0; font-size: var(--portal-text-13); color: var(--portal-faint); }
/* What a WLCA rep reads of a Lead's Designs without the Planner (crm ADR 0009): a
   read-only card's snapshots, and the Lead page's Designs under each Project. */
.portal-design-card-downloads { margin: 0; padding: 0; list-style: none; font-size: var(--portal-text-13); }
.portal-design-card-menu { position: absolute; top: 1rem; right: 1rem; z-index: 1; }
.portal-design-card-menu .portal-menu-panel { right: 0; }

/* A Lead whose next To-do is late (crm slice 01): the row and its date stand out. */
.portal-lead-late { background: var(--portal-danger-wash); }
.portal-late { color: var(--portal-danger); font-weight: 600; }

/* A Lead's Stage bar (crm): one segment per Stage, the last one Won or Lost.
   Passed Stages are filled, the current one is filled and named in ink, the
   rest stay grey. Segments wrap to a second row on a phone. */
.portal-stage-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: 1rem 0.375rem;
  margin: 0 0 2.5rem;
  padding: 0;
  list-style: none;
}
.portal-stage-step {
  padding-top: 0.625rem;
  border-top: 4px solid var(--portal-rule-strong);
  font-size: var(--portal-text-10);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--portal-faint);
  overflow-wrap: anywhere;
}
.portal-stage-step.is-passed { border-top-color: var(--portal-ink); color: var(--portal-muted); }
.portal-stage-step.is-current { border-top: 8px solid var(--portal-ink); margin-top: -4px; color: var(--portal-ink); font-weight: 600; }
.portal-stage-step.is-won { border-top: 8px solid var(--portal-positive); margin-top: -4px; color: var(--portal-positive); font-weight: 600; }
.portal-stage-step.is-lost { border-top: 8px solid var(--portal-danger); margin-top: -4px; color: var(--portal-danger); font-weight: 600; }

/* Air between a table and the heading of the next section. */
.portal-scroll + .portal-section-head { margin-top: 2.75rem; }
/* Scorecards: a column per figure, each heading long; they wrap rather than push the
   table sideways. */
.portal-scorecard-table thead th { white-space: normal; vertical-align: bottom; }

/* Privacy and repeats (crm slice 06). A masked contact reads as a note, not a value;
   a repeat's actions sit in its line, and a POST button there looks like a link. */
.portal-masked { color: var(--portal-faint); font-style: italic; }
.portal-repeats { margin: 0 0 1.5rem; }
.portal-repeats p { margin: 0 0 0.5rem; }
.portal-repeats ul { margin: 0; padding-left: 1.25rem; }
.portal-repeats li { margin: 0.25rem 0; }
.portal-inline-form { display: inline; margin-left: 0.5rem; }
.portal-link-button { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; }

/* ------------------------------------------------------------------- crm

   The Sales desk is worked all day, so its screens trade the showroom for a working
   look: the same fonts, header and black on white, but each subject in its own
   bordered panel, and colour only where it means something: a Stage, a clock running
   out, Won and Lost. Every rule hangs off `.portal-crm`, which `crm/desk_base.html`
   sets on `body`, or off a `portal-crm-*` class only the CRM's templates use. */

.portal-crm {
  --crm-line: var(--portal-rule);
  --crm-edge: var(--portal-rule-strong);
  --crm-label: var(--portal-ink);
  --crm-quiet: var(--portal-muted);
  --crm-radius: var(--portal-radius);
  --crm-head: var(--portal-head);
  --crm-amber: var(--portal-amber);
  --crm-amber-wash: var(--portal-amber-wash);
  --crm-teal: var(--portal-teal);
}

/* A working screen uses the whole window: the page runs edge to edge inside the same
   gutters as the header, so its edges line up with the logo and the Partner menu. */
.portal-crm .portal-main,
.portal-crm .portal-messages { max-width: none; }
/* Messages sit flush above the white band rather than under it. */
.portal-crm .portal-messages { margin-bottom: 0; }

/* A form screen and a Scorecard read as one column, not the full width. */
.portal-crm .portal-crm-column { max-width: 40rem; }
/* New Lead (crm slice 59): two fields to a row on a wide screen, so it fits with no
   scrolling; the intro, the errors, a tick box and the buttons take the whole row. */
.portal-crm .portal-form-pairs { max-width: 52rem; }
@media (min-width: 48rem) {
  .portal-form-pairs { display: grid; grid-template-columns: 1fr 1fr; column-gap: 1.5rem; align-items: start; }
  .portal-form-pairs > :is(.portal-crm-intro, .errorlist, .portal-form-actions),
  .portal-form-pairs > .portal-field:has(> .portal-tile) { grid-column: 1 / -1; }
}

/* --- The head: the title and actions, ruled off from the rest (the tabs are in the header). */

.portal-crm h1 { font-size: var(--portal-text-30); }
.portal-crm-head { margin: -1.75rem 0 1.25rem; }
.portal-crm-head .portal-page-head { margin-bottom: 1.25rem; }
.portal-crm-title { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.875rem; min-width: 0; }
.portal-crm-title h1 { margin: 0; }
/* A heading that is also the way to its record (the expanded Conversation's Lead name). */
/* A record's way back to the list it was opened from (crm/partials/desk_back.html). */
.portal-crm-back { flex: none; font-size: var(--portal-text-22); line-height: 1; color: var(--crm-quiet); text-decoration: none; }
.portal-crm-back:hover { color: var(--portal-ink); }
/* A short fact beside the title: why it was Lost, the Response deadline. */
.portal-crm-aside { font-size: var(--portal-text-13); color: var(--crm-quiet); white-space: nowrap; }

/* What the screen is for: a "?" beside the title (crm/partials/screen_help.html). */
/* Small and faint, tucked close to the title. */
.portal-crm-help { position: relative; display: inline-flex; flex: none; margin-left: -0.5rem; opacity: 0.55; }
.portal-crm-help:hover,
.portal-crm-help:focus-within { opacity: 1; }
.portal-crm-help button {
  width: 1rem;
  height: 1rem;
  padding: 0;
  font: 600 var(--portal-text-10)/1 var(--portal-ui);
  color: var(--crm-quiet);
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  border-radius: var(--portal-round);
  cursor: help;
}
.portal-crm-help button:hover,
.portal-crm-help button:focus-visible { color: var(--portal-ink); border-color: var(--portal-ink); }
.portal-crm-help-text {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  z-index: 20;
  width: max-content;
  max-width: 22rem;
  padding: 0.625rem 0.75rem;
  font-size: var(--portal-text-12);
  font-weight: 400;
  line-height: 1.5;
  white-space: normal;
  color: var(--portal-surface);
  background: var(--portal-ink);
  border-radius: var(--portal-radius);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.12s;
}
.portal-crm-help:hover .portal-crm-help-text,
.portal-crm-help:focus-within .portal-crm-help-text { visibility: visible; opacity: 1; }

/* --- Buttons: squared and sentence case, sized for a toolbar. The black button is
   the screen's next step; `portal-crm-action` is every other one, link or button,
   outlined, and green for Won, red for Lost. */

.portal-crm .portal-button,
.portal-crm-action {
  height: var(--portal-control-sm);
  padding: 0 1.125rem;
  font-size: var(--portal-text-13);
  letter-spacing: 0;
  text-transform: none;
  border-radius: var(--portal-radius);
}
.portal-crm-action {
  display: inline-flex;
  align-items: center;
  font-family: var(--portal-ui);
  font-weight: 600;
  color: var(--portal-ink);
  text-decoration: none;
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  cursor: pointer;
}
.portal-crm-action:hover { color: var(--portal-ink); border-color: var(--portal-ink); }
/* A Lead page's rarer moves (Give to a Partner, Make Partner, Claim back) behind a small ⋯ beside its
   Stage buttons (crm/lead_detail.html), the same height as they are. */
.portal-lead-menu > summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: var(--portal-control-sm);
  font-size: var(--portal-text-18);
  color: var(--portal-ink);
  list-style: none;
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  border-radius: var(--portal-radius);
}
.portal-lead-menu > summary::-webkit-details-marker { display: none; }
.portal-lead-menu > summary:hover,
.portal-lead-menu[open] > summary { border-color: var(--portal-ink); }
.portal-lead-menu .portal-add-menu-item { text-decoration: none; }
.portal-crm-action.is-lost { color: var(--portal-danger); border-color: var(--portal-danger); }
.portal-crm .portal-page-head-actions { gap: 0.625rem; flex-wrap: wrap; }
.portal-crm .portal-page-head-actions form { margin: 0; }

/* --- Colour that means something. */

/* A Stage as a tag (crm/partials/stage_tag.html): each its own colour, and each colour
   also its own lightness. */
.portal-stage-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.125rem 0.625rem;
  font-size: var(--portal-text-12);
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  border-radius: var(--portal-radius);
  color: var(--portal-stone);
  background: var(--portal-stone-wash);
}
.portal-stage-tag::before { content: ""; width: 7px; height: 7px; border-radius: var(--portal-round); background: currentColor; }
.portal-stage-tag.is-new { color: var(--portal-blue); background: var(--portal-blue-wash); }
.portal-stage-tag.is-contacted { color: var(--crm-teal); background: var(--portal-teal-wash); }
.portal-stage-tag.is-designing { color: var(--portal-purple); background: var(--portal-purple-wash); }
.portal-stage-tag.is-quoted { color: var(--crm-amber); background: var(--crm-amber-wash); }
.portal-stage-tag.is-won { color: var(--portal-positive); background: var(--portal-positive-wash); }
.portal-stage-tag.is-lost { color: var(--portal-stone); background: var(--portal-stone-wash); }

/* Working time left on a Response deadline: amber while it runs, red once it is up. */
.portal-time-left {
  display: inline-block;
  padding: 0.125rem 0.5rem;
  font-size: var(--portal-text-12);
  font-weight: 600;
  white-space: nowrap;
  color: var(--crm-amber);
  background: var(--crm-amber-wash);
  border-radius: var(--portal-radius);
}
.portal-time-left.is-up { color: var(--portal-danger); background: var(--portal-danger-tint); }

/* A Stage bar as a progress bar (crm/partials/stage_bar.html): short, on the left, a
   thin segment per Stage over its name. */
.portal-crm .portal-stage-bar {
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: 0.5rem 3px;
  max-width: 34rem;
  margin: 0 0 1.5rem;
}
.portal-crm .portal-stage-step {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: var(--portal-text-12);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--crm-quiet);
}
.portal-crm .portal-stage-step::before {
  content: "";
  display: block;
  height: 6px;
  margin-bottom: 0.375rem;
  border-radius: var(--portal-radius);
  background: var(--crm-edge);
}
.portal-crm .portal-stage-step.is-passed::before,
.portal-crm .portal-stage-step.is-current::before { background: var(--crm-teal); }
.portal-crm .portal-stage-step.is-current { color: var(--crm-teal); font-weight: 700; }
.portal-crm .portal-stage-step.is-won { color: var(--portal-positive); font-weight: 700; }
.portal-crm .portal-stage-step.is-won::before { background: var(--portal-positive); }
.portal-crm .portal-stage-step.is-lost { color: var(--portal-danger); font-weight: 700; }
.portal-crm .portal-stage-step.is-lost::before { background: var(--portal-danger); }

/* --- Tables sit in a white panel, their heads on a band. */

.portal-crm .portal-scroll {
  margin-bottom: 1.5rem;
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  border-radius: var(--crm-radius);
}
.portal-crm .portal-list-table th,
.portal-crm .portal-list-table td { padding: 0.625rem 0.875rem; border-bottom-color: var(--crm-line); }
.portal-crm .portal-list-table thead th {
  font-size: var(--portal-text-11);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--crm-label);
  background: var(--crm-head);
  border-bottom: 0;
  /* The rule is drawn inside the cell: a collapsed border stays behind when it sticks. */
  box-shadow: inset 0 -1px 0 var(--crm-edge);
}
.portal-crm .portal-list-table tbody tr:last-child > * { border-bottom: 0; }
.portal-crm .portal-list-table tbody th a { border-bottom: 0; }
.portal-crm .portal-list-table tbody th a:hover { text-decoration: underline; color: var(--portal-ink); }
.portal-crm .portal-late { margin-left: 0.375rem; }

/* Section heads between tables, and the head of a card: a label in small capitals. */
.portal-crm .portal-section-head { margin: 0 0 0.625rem; align-items: center; }
.portal-crm .portal-scroll + .portal-section-head { margin-top: 1rem; }
.portal-crm .portal-section-head h2,
.portal-crm-card-head,
.portal-crm-card-head h2 {
  margin: 0;
  font-family: var(--portal-ui);
  font-size: var(--portal-text-12);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--crm-label);
}
.portal-crm .portal-section-head p { margin: 0; font-size: var(--portal-text-13); color: var(--crm-quiet); }

/* --- A card: one subject in a panel, a head on a band, then its rows. */

.portal-crm-card {
  margin-bottom: 1.25rem;
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  border-radius: var(--crm-radius);
  overflow: hidden;
}
.portal-crm-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--crm-head);
  border-bottom: 1px solid var(--crm-edge);
}
.portal-crm-card-head form { margin: 0; }
.portal-crm-card-head .portal-inline-button { font-size: var(--portal-text-12); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--portal-ink); }
.portal-crm-card-body { padding: 1rem; font-size: var(--portal-text-13); }
.portal-crm-card-body > * { margin: 0 0 1rem; }
.portal-crm-card-body > :last-child { margin-bottom: 0; }
.portal-crm-card-body .portal-quiet { margin: 0.375rem 0 0; }
.portal-crm-empty { margin: 0; padding: 0.875rem 1rem; }

/* A Project's lanes: its Designs, its Quotes, its Order. */
.portal-project-lane { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.portal-project-lane h4 { margin: 0; font-size: var(--portal-text-12); font-weight: 600; color: var(--crm-quiet); }
.portal-project-item {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.625rem 0.75rem;
  font-size: var(--portal-text-13);
  color: var(--portal-ink);
  text-decoration: none;
  border: 1px solid var(--crm-edge);
  border-radius: var(--crm-radius);
}
a.portal-project-item:hover { border-color: var(--portal-ink); }
a.portal-project-item:focus-visible { outline: 2px solid var(--portal-ink); outline-offset: 2px; }
.portal-project-item-line { display: flex; align-items: baseline; gap: 0.625rem; }
.portal-project-item-name { font-weight: 600; }
.portal-project-amount { margin-left: auto; font-weight: 600; white-space: nowrap; }
.portal-project-meta { font-size: var(--portal-text-12); color: var(--crm-quiet); }
.portal-project-empty { margin: 0; padding: 0.625rem 0.75rem; font-size: var(--portal-text-13); color: var(--crm-quiet); border: 1px dashed var(--crm-edge); border-radius: var(--crm-radius); }
.portal-project-status { padding: 0.0625rem 0.5rem; font-size: var(--portal-text-11); font-weight: 600; color: var(--crm-teal); background: var(--portal-teal-wash); border-radius: var(--portal-radius); }
.portal-project-status--draft { color: var(--portal-body); background: var(--portal-panel); }
.portal-project-status--confirmed { color: var(--portal-surface); background: var(--crm-teal); }
.portal-project-status--declined,
.portal-project-status--expired { color: var(--portal-danger); background: var(--portal-danger-wash); }
.portal-project-earlier { margin: 0.25rem 0 0; font-size: var(--portal-text-12); color: var(--crm-quiet); }
.portal-project-earlier summary { padding: 0.25rem 0.75rem; cursor: pointer; }
.portal-project-earlier ul { margin: 0; padding: 0.25rem 0.75rem; list-style: none; }
.portal-project-earlier li { padding: 0.125rem 0; }
/* A sent Quote's PDF, a small link under its row, beside the earlier Revisions (crm slice 35). */
.portal-project-quote-pdf { display: inline-block; padding: 0.125rem 0.75rem; font-size: var(--portal-text-12); color: var(--crm-quiet); }
.portal-project-quote-pdf:hover { color: var(--portal-ink); }

/* The Projects tab (crm slice 51): four figures, then each Project a card folded to its label,
   Stage and Design -> Quote -> Order line; Won and Lost ones under Closed projects. */
.portal-projects-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: 1px;
  margin: 0;
  background: var(--crm-line);
  border-bottom: 1px solid var(--crm-line);
}
.portal-projects-figure { padding: 0.625rem 1rem; background: var(--portal-surface); }
.portal-projects-figure dt { font-size: var(--portal-text-11); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--crm-quiet); }
.portal-projects-figure dd { margin: 0.125rem 0 0; display: flex; flex-direction: column; }
/* The UI font with tabular numbers: in the display font a 1 reads as an I and a 0 as a circle. */
.portal-projects-figure strong { font-family: var(--portal-ui); font-size: var(--portal-text-20); font-weight: 600; font-variant-numeric: tabular-nums lining-nums; line-height: 1.3; color: var(--portal-ink); }
.portal-projects-figure-words { font-size: var(--portal-text-12); color: var(--crm-quiet); }
/* Each Project one card that opens its page: its label with its Stage at the right, then its
   progress line. */
.portal-project {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  padding: 0.875rem 1rem;
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--crm-line);
}
.portal-project:last-child { border-bottom: 0; }
.portal-project:hover { background: var(--portal-panel); }
.portal-project:hover h3 { text-decoration: underline; }
.portal-project:focus-visible { outline: 2px solid var(--portal-ink); outline-offset: -2px; }
.portal-project-title { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.portal-project-title h3 { margin: 0; min-width: 0; font-family: var(--portal-display); font-size: var(--portal-text-20); font-weight: 400; color: var(--portal-ink); }
.portal-project-title .portal-stage-tag { flex: none; }
@media (max-width: 40rem) {
  .portal-project-progress { column-gap: 0.875rem; }
  .portal-progress-step { padding: 0.375rem 0.5rem; }
  .portal-progress-step + .portal-progress-step::before { left: -0.875rem; width: 0.875rem; }
}
/* Design, Quote and Order in three equal columns, an arrow in the gap between. */
.portal-project-progress {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.25rem 1.125rem;
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--portal-text-12);
}
.portal-progress-step { position: relative; display: flex; flex-wrap: wrap; align-content: flex-start; column-gap: 0.3rem; min-width: 0; padding: 0.375rem 0.625rem; color: var(--crm-quiet); border: 1px solid var(--crm-edge); border-radius: var(--portal-radius); }
.portal-progress-step + .portal-progress-step::before { content: "\2192"; position: absolute; top: 50%; left: -1.1rem; width: 1rem; text-align: center; color: var(--crm-quiet); transform: translateY(-50%); }
.portal-progress-name { font-weight: 600; }
/* The amount on its own line under the step's words. */
.portal-progress-amount { flex-basis: 100%; font-size: var(--portal-text-13); font-weight: 600; font-variant-numeric: tabular-nums; }
/* The Leads list's Est. value (crm slice 58): the total over its Cabinets alone, quiet. */
.portal-est-value-head, .portal-est-value { text-align: right; white-space: nowrap; }
.portal-est-total, .portal-est-cabinets { display: block; font-variant-numeric: tabular-nums; }
.portal-est-cabinets { font-size: var(--portal-text-12); color: var(--portal-faint); }
.portal-progress-step.is-done { color: var(--crm-teal); background: var(--portal-teal-wash); border-color: transparent; }
.portal-progress-step.is-current { color: var(--portal-ink); border-color: var(--portal-ink); }
.portal-progress-step.is-ahead,
.portal-progress-step.is-skipped { border-style: dashed; }
.portal-progress-step.is-stopped { color: var(--portal-danger); background: var(--portal-danger-wash); border-color: transparent; }
.portal-closed-projects { border-top: 1px solid var(--crm-line); }
.portal-closed-projects > summary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 1rem;
  list-style: none;
  font-size: var(--portal-text-12);
  font-weight: 600;
  color: var(--crm-quiet);
  cursor: pointer;
}
.portal-closed-projects > summary:hover { color: var(--portal-ink); }
.portal-closed-projects[open] > summary { border-bottom: 1px solid var(--crm-line); }
.portal-closed-projects > .portal-project:last-child { border-bottom: 0; }

/* A Project's own screen (planner/project_detail.html): three columns, Designs, Quotes and
   Order, under a head each. Every Design is a row, the Quotes made from it beside it and
   the Order beside the Quote it follows: each row and its Quotes take the columns as a
   subgrid, so a Quote lines up with its Design and an Order with its Quote. One column
   on a narrow window. A design card's Actions menu hangs out of its card, so nothing
   clips. */
.portal-project-page-lanes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 1rem;
  align-items: start;
}
.portal-project-board-head { border: 1px solid var(--crm-edge); border-radius: var(--crm-radius); }
.portal-project-board-row,
.portal-project-board-quotes { display: grid; grid-template-columns: subgrid; row-gap: 0.75rem; }
.portal-project-board-row { grid-column: 1 / -1; padding: 0.75rem 0; border-bottom: 1px solid var(--crm-line); }
.portal-project-board-design { grid-column: 1; min-width: 0; }
.portal-project-board-quotes { grid-column: 2 / -1; }
.portal-project-board-quote,
.portal-project-board-order { min-width: 0; }
/* The cards of one row stand as tall as each other: a Design as tall as its Quotes, a
   Quote as tall as the Order beside it. Here a Quote's border takes in its PDF link and
   earlier Revisions too, so its whole card stretches. */
.portal-project-board-design,
.portal-project-board-quote,
.portal-project-board-order,
.portal-project-board-quote > .portal-project-quote { display: flex; flex-direction: column; }
.portal-project-board-design > .portal-design-card,
.portal-project-board-quote > .portal-project-quote,
.portal-project-board-quote .portal-project-quote > .portal-project-item,
.portal-project-board-order > .portal-order-card { flex: 1 1 auto; }
.portal-project-board-quote .portal-project-quote { border: 1px solid var(--crm-edge); border-radius: var(--crm-radius); }
.portal-project-board-quote .portal-project-quote:has(> a.portal-project-item:hover) { border-color: var(--portal-ink); }
.portal-project-board-quote .portal-project-item { border: 0; }
.portal-project-board-quote .portal-project-quote-pdf {
  align-self: flex-start;
  margin: 0 0.75rem 0.625rem;
  padding: 0.125rem 0.625rem;
  font-weight: 600;
  color: var(--portal-ink);
  text-decoration: none;
  border: 1px solid var(--crm-edge);
  border-radius: var(--portal-radius);
}
.portal-project-board-quote .portal-project-quote-pdf:hover { border-color: var(--portal-ink); }
.portal-project-board-order.is-alone { grid-column: 3; }
.portal-project-board-typed { margin: 0; padding: 0.625rem 0; }
.portal-project-board-note { grid-column: 1; margin: 0.75rem 0 0; }
.portal-project-page-lanes .portal-design-card { border-radius: var(--crm-radius); }
.portal-project-page-lanes .portal-project-empty > p { margin: 0 0 0.75rem; }
.portal-project-page-lanes .portal-project-lane > * { margin: 0; }
.portal-order-card { padding: 0.75rem; border: 1px solid var(--crm-edge); border-radius: var(--crm-radius); }
/* A heading for whoever cannot see the columns it sits in. */
.portal-hidden-title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* A Project's Files card (planner/partials/project_files.html, crm slice 41): the kinds as
   tabs, the add form, then a grid of thumbnails; a document shows its type in the tile. */
.portal-project-files { margin-top: 1.5rem; }
.portal-project-files.is-dropping { outline: 2px dashed var(--crm-teal); outline-offset: -4px; }
.portal-project-files .portal-subtabs { flex-wrap: wrap; }
.portal-file-add { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; margin: 0 0 1rem; }
.portal-file-add .portal-form-errors { flex-basis: 100%; color: var(--portal-danger); }
.portal-file-kind-pick { display: inline-flex; align-items: center; gap: 0.5rem; font-size: var(--portal-text-14); }
.portal-file-pick { position: relative; cursor: pointer; }
.portal-file-pick input[type="file"] { position: absolute; inset: 0; width: 100%; opacity: 0; cursor: pointer; }
.portal-file-drop-hint { flex-basis: 100%; margin: 0; }
@media (hover: hover) and (pointer: fine) { .portal-file-camera { display: none; } }
.portal-project-file-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: 0.75rem; margin: 0; padding: 0; list-style: none; }
.portal-project-file { display: flex; flex-direction: column; min-width: 0; border: 1px solid var(--crm-line); border-radius: var(--crm-radius); overflow: hidden; }
.portal-project-file-thumb { display: flex; align-items: center; justify-content: center; aspect-ratio: 4 / 3; background: var(--portal-panel); color: var(--portal-muted); font-weight: 600; text-decoration: none; }
.portal-project-file-thumb img { width: 100%; height: 100%; object-fit: cover; }
.portal-project-file-about { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.5rem 0.625rem; font-size: var(--portal-text-13); }
.portal-project-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.portal-project-file-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.75rem; }
.portal-project-file-actions form { display: inline-flex; align-items: center; gap: 0.375rem; margin: 0; }
@media (max-width: 56rem) {
  .portal-project-page-lanes { grid-template-columns: minmax(0, 1fr); row-gap: 0.5rem; }
  .portal-project-board-row,
  .portal-project-board-quotes { grid-column: 1; }
  .portal-project-board-order.is-alone { grid-column: 1; }
}

/* The way up from a Quote or a Design (planner/partials/project_trail.html): the Lead, then
   the Project, whose menu reaches its other Designs and Quotes and the Lead's other Projects. */
.portal-trail { display: flex; flex: 0 1 auto; align-items: center; gap: 0.375rem; min-width: 0; font-size: var(--portal-text-13); white-space: nowrap; }
.portal-trail a { color: var(--portal-muted); text-decoration: none; }
.portal-trail a:hover { color: var(--portal-ink); text-decoration: underline; }
.portal-trail-lead { display: inline-flex; align-items: center; gap: 0.375rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.portal-trail-lead svg { flex: none; }
.portal-trail-split { color: var(--portal-faint); }
.portal-trail-project { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.portal-column-menu.portal-revisions-menu { width: 18rem; }
.portal-revisions-menu ul { margin: 0; padding: 0; list-style: none; }
.portal-revisions-menu li { display: flex; justify-content: space-between; gap: 0.75rem; padding: 0.25rem 0; }
.portal-revisions-menu li span { color: var(--portal-faint); }
.portal-revisions-menu [aria-current] { font-weight: 600; color: var(--portal-ink); }
.portal-crm-aside .portal-column-button { margin: 0; padding: 0; font: inherit; color: inherit; }

/* --- Facts read as a record: labels are row heads in semibold, values in plain text. */

.portal-crm .portal-facts {
  display: grid;
  grid-template-columns: minmax(8rem, 34%) minmax(0, 1fr);
  margin-bottom: 1.25rem;
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  border-radius: var(--crm-radius);
  overflow: hidden;
}
.portal-crm .portal-facts dt,
.portal-crm .portal-facts dd {
  margin: 0;
  padding: 0.625rem 0.875rem;
  font-size: var(--portal-text-13);
  border-bottom: 1px solid var(--crm-line);
}
.portal-crm .portal-facts dt {
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--crm-label);
  border-right: 1px solid var(--crm-line);
}
.portal-crm .portal-facts dd { font-weight: 400; color: var(--portal-body); }
.portal-crm .portal-facts dd:last-of-type,
.portal-crm .portal-facts dt:last-of-type { margin: 0; border-bottom: 0; }
.portal-crm-card .portal-facts { margin: 0; border: 0; border-radius: 0; }

/* --- Forms sit in a panel; inside a card the card is the panel. */

.portal-crm .portal-form {
  padding: 1.5rem;
  background: var(--portal-surface);
  border: 1px solid var(--crm-edge);
  border-radius: var(--crm-radius);
}
.portal-crm .portal-form + .portal-scroll,
.portal-crm .portal-form + .portal-lede { margin-top: 1.25rem; }
.portal-crm .portal-form-actions { margin-top: 1.5rem; }
/* What to fill in, at the top of a form screen's panel. */
.portal-crm-intro { margin: 0 0 1.25rem; font-size: var(--portal-text-13); line-height: 1.6; color: var(--crm-quiet); }
.portal-crm-card .portal-form { max-width: none; margin: 0; padding: 1rem; border: 0; border-bottom: 1px solid var(--crm-line); border-radius: 0; }
.portal-crm-card .portal-form:last-child { border-bottom: 0; }
.portal-crm-card .portal-form .portal-field { margin-bottom: 0.75rem; }
.portal-crm-card .portal-form .portal-form-actions { margin-top: 0; justify-content: flex-end; }
.portal-crm .portal-split { gap: 1.25rem; }

/* --- On a wide screen the top of a CRM screen stays put while the rest scrolls: the
   portal header with the desk's tabs, then the title row, then a table's column heads.
   Each band gets a fixed height so the next knows where to stop, and the bands are
   kept short: one line of title beside its actions. Narrower, the
   bands wrap and everything scrolls away, and a table scrolls sideways with its heads. */

@media (min-width: 64rem) {
  .portal-crm {
    --crm-header-height: 4.75rem;
    --crm-title-height: 3.75rem;
    --crm-gap: 1.25rem;
  }
  /* The header and the title read as one white block, edge to edge, with a rule
     under the header and none under the title. */
  .portal-crm .portal-header {
    position: sticky;
    top: 0;
    z-index: 10;
    height: var(--crm-header-height);
    padding-top: 0;
    padding-bottom: 0;
    background: var(--portal-surface);
    border-bottom: 1px solid var(--crm-edge);
  }
  /* Under the title's rule the block keeps a strip of white, so even stuck there is
     air between the title and the first table. */
  .portal-crm-head {
    position: sticky;
    top: var(--crm-header-height);
    z-index: 9;
    margin: -3.5rem 0 0;
    padding-bottom: var(--crm-gap);
    background: var(--portal-surface);
    border-bottom: 0;
  }
  /* The white runs out to both window edges without widening the page.
     It lives on a layer behind the block, so its clip leaves the "?" free to hang
     below. */
  .portal-crm-head::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    z-index: -1;
    clip-path: inset(0 -100vmax);
  }
  .portal-crm-head::before { top: 0; bottom: 0; background: var(--portal-surface); box-shadow: 0 0 0 100vmax var(--portal-surface); }
  .portal-crm-head .portal-page-head {
    height: var(--crm-title-height);
    margin: 0;
    align-items: center;
  }
  .portal-crm-head h1 { font-size: var(--portal-text-24); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Short of room, the fact beside the title gives way first, then the title. */
  .portal-crm-title { flex-wrap: nowrap; }
  .portal-crm-title h1 { flex: 0 1 auto; min-width: 8rem; }
  .portal-crm-title .portal-stage-tag { flex: none; }
  .portal-crm-title .portal-crm-aside { flex: 0 100 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .portal-crm .portal-scroll { overflow: clip; }
  .portal-crm .portal-list-table thead th {
    position: sticky;
    /* Flush under the block's strip of white. */
    top: calc(var(--crm-header-height) + var(--crm-title-height) + var(--crm-gap));
    z-index: 1;
  }
}

@media (max-width: 46rem) {
  .portal-crm .portal-facts { grid-template-columns: minmax(0, 1fr); }
  .portal-crm .portal-facts dt { border-right: 0; border-bottom: 0; padding-bottom: 0.25rem; }
  .portal-crm .portal-facts dd { padding-top: 0.25rem; }
}

/* ------------------------------------------------------------ list search

   One box over a Sales desk list (crm/partials/list_search.html): a name, or a
   whole phone number or email. Sent by POST, so a contact never sits in an
   address. */

.portal-search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin: 0 0 1.5rem;
}
/* A desk list's toolbar: its search on the left, its New button on the right, on one line. */
.portal-list-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1rem; margin: 0 0 1.5rem; }
.portal-list-bar .portal-search { flex: 1 1 28rem; margin: 0; }
.portal-list-bar > .portal-button { margin-left: auto; }
/* The Leads list's Won, not ordered filter (orders slice 12): off, a quiet outline; on, filled. */
.portal-filter-switch {
  display: inline-flex; align-items: center; gap: 0.375rem; height: var(--portal-control-sm); padding: 0 0.875rem;
  font-size: var(--portal-text-14); white-space: nowrap; color: var(--portal-ink); text-decoration: none;
  background: var(--portal-surface); border: 1px solid var(--portal-rule-strong); border-radius: var(--portal-pill);
}
.portal-filter-switch:hover { border-color: var(--portal-ink); }
.portal-filter-switch.is-on { color: var(--portal-surface); background: var(--portal-ink); border-color: var(--portal-ink); }
.portal-filter-switch.is-on::before { content: "\2713"; }
/* The Leads list's Saved filters: the switch above as a button, opening a menu of them. */
.portal-saved-filters-button { font: inherit; font-size: var(--portal-text-14); cursor: pointer; }
.portal-saved-filters-button.is-on .portal-column-caret { color: inherit; }
.portal-column-menu.portal-saved-filters { width: 14rem; }
/* My Leads' quick filters and its order, under the bar (crm slice 54). */
.portal-list-quick { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 1rem; margin: -0.75rem 0 1rem; }
.portal-list-quick-group { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.portal-list-order { font-size: var(--portal-text-13); gap: 0.25rem 0.75rem; }
.portal-list-order a { color: var(--portal-muted); text-decoration: none; }
.portal-list-order a:hover { color: var(--portal-ink); text-decoration: underline; }
.portal-list-order a[aria-current] { color: var(--portal-ink); font-weight: 600; }
/* A row's Waiting on me, after its customer; its Last contact, red past its window. */
.portal-row-waiting { margin-left: 0.375rem; }
.portal-last-contact { white-space: nowrap; }
.portal-last-contact.is-late { color: var(--portal-danger); font-weight: 600; }
/* A row's next To-do (crm slice 55): when, red once late; then its kind and what to do,
   cut to one line, the whole of it on hover. */
.portal-next-to-do { white-space: nowrap; }
.portal-next-to-do.is-late { color: var(--portal-danger); font-weight: 600; }
.portal-next-to-do-details {
  display: block;
  max-width: 18rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* A WLCA rep's "Takes Leads in turn" switch (crm slice 40): a track and its words, one button. */
.portal-round-switch { display: inline-flex; margin: 0; }
.portal-round-toggle {
  display: inline-flex; align-items: center; gap: 0.625rem; height: var(--portal-control-sm); padding: 0 0.25rem;
  font: inherit; font-size: var(--portal-text-14); white-space: nowrap; color: var(--portal-muted);
  background: none; border: 0; border-radius: var(--portal-pill); cursor: pointer;
}
.portal-round-toggle.is-on { color: var(--portal-ink); }
.portal-round-toggle:focus-visible { outline: 2px solid var(--portal-ink); outline-offset: 2px; }
.portal-round-track {
  position: relative; flex: none; width: 2.25rem; height: 1.25rem;
  background: var(--portal-edge-disabled); border-radius: var(--portal-pill); transition: background-color 160ms ease;
}
.portal-round-track::after {
  content: ""; position: absolute; top: 0.125rem; left: 0.125rem; width: 1rem; height: 1rem;
  background: var(--portal-surface); border-radius: 50%; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.24); transition: transform 160ms ease;
}
.portal-round-toggle:hover .portal-round-track { background: var(--portal-edge); }
.portal-round-toggle.is-on .portal-round-track { background: var(--portal-positive); }
.portal-round-toggle.is-on:hover .portal-round-track { filter: brightness(0.88); }
.portal-round-toggle.is-on .portal-round-track::after { transform: translateX(1rem); }
.portal-round-state { font-weight: 600; }
/* In the user menu: a settings line of its own, its words left and the track right. */
.portal-menu-setting { margin: 0 0 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid var(--portal-rule); }
.portal-menu-setting .portal-round-switch { display: flex; }
.portal-menu-setting .portal-round-toggle {
  flex: 1; flex-direction: row-reverse; justify-content: space-between; height: auto; padding: 0.125rem 0;
  font-size: var(--portal-text-13); border-radius: 0;
}
.portal-menu-setting .portal-round-state { font-weight: 500; }
@media (prefers-reduced-motion: reduce) { .portal-round-track, .portal-round-track::after { transition: none; } }
.portal-search-input {
  flex: 0 1 28rem;
  min-width: 0;
  height: var(--portal-control-sm);
  padding: 0 0.75rem;
  font: inherit;
  font-size: var(--portal-text-14);
  color: var(--portal-ink);
  background: var(--portal-surface);
  border: 1px solid var(--portal-edge);
  border-radius: var(--portal-radius);
}
.portal-search-input:hover { border-color: var(--portal-edge-hover); }
.portal-search-input:focus { border-color: var(--portal-teal); box-shadow: var(--portal-focus-ring); outline: 0; }
.portal-search-input::placeholder { color: var(--portal-faint); }

/* ------------------------------------------------------------ column menus

   Stage, Source and Salesperson on the Leads list each open a menu from their head
   (crm/partials/lead_column_head.html): sort, group, and values to show. The menu
   is a popover, so the table's rounded panel never clips it. */

.portal-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.portal-column-button {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin: -0.25rem -0.375rem;
  padding: 0.25rem 0.375rem;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: var(--portal-radius);
  cursor: pointer;
}
.portal-column-button:hover { background: var(--portal-hover); }
.portal-column-caret { font-size: var(--portal-text-10); color: var(--portal-faint); }
.portal-column-mark { font-size: var(--portal-text-12); letter-spacing: 0; color: var(--crm-teal, var(--portal-ink)); }
.portal-column-head.is-active .portal-column-caret { color: var(--portal-ink); }

.portal-column-menu {
  width: 15rem;
  max-height: min(28rem, calc(100vh - 2rem));
  margin: auto;
  padding: 0.875rem 1rem 1rem;
  overflow: auto;
  font: 400 var(--portal-text-13)/1.5 var(--portal-ui);
  letter-spacing: 0;
  text-transform: none;
  color: var(--portal-body);
  background: var(--portal-surface);
  border: 1px solid var(--portal-rule-strong);
  border-radius: var(--portal-radius);
  box-shadow: var(--portal-shadow-menu);
}
/* Placed by crm/js/column-menu.js under its head; otherwise it opens centred. */
.portal-column-menu.is-placed { position: fixed; inset: auto; margin: 0; }
.portal-column-menu-label {
  margin: 0.875rem 0 0.375rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--portal-faint);
}
.portal-column-menu-label:first-child { margin-top: 0; }
.portal-column-choices,
.portal-column-ticks { margin: 0; padding: 0; list-style: none; }
.portal-column-choices a { display: block; padding: 0.25rem 0; }
.portal-column-choices a[aria-current="true"] { font-weight: 600; }
.portal-column-choices a[aria-current="true"]::before { content: "✓ "; }
.portal-group-order { margin: 0; padding: 0 0 0 1.25rem; }
.portal-group-order li { display: flex; align-items: center; gap: 0.375rem; padding: 0.188rem 0; }
.portal-group-order li > span { flex: 1 1 auto; }
.portal-group-order a { padding: 0 0.375rem; border-radius: var(--portal-radius); }
.portal-group-order a:hover { background: var(--portal-hover); }
.portal-column-ticks label { display: flex; align-items: center; gap: 0.5rem; padding: 0.188rem 0; cursor: pointer; }
.portal-column-ticks input { margin: 0; accent-color: var(--portal-ink); }
.portal-column-menu-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--portal-rule);
}
.portal-column-close { margin-left: auto; padding: 0; background: none; border: 0; cursor: pointer; font: inherit; }

/* Small tabs inside one screen (the Leads list's My Leads / All Leads). */
.portal-subtabs { display: flex; gap: 0.25rem; margin: 0 0 1rem; }
.portal-subtabs a {
  padding: 0.25rem 0.75rem;
  border-radius: var(--portal-pill);
  font-size: var(--portal-text-13);
  font-weight: 500;
  color: var(--portal-muted);
}
.portal-subtabs a:hover { color: var(--portal-ink); }
.portal-subtabs a[aria-current="page"] { font-weight: 600; color: var(--portal-ink); background: var(--portal-panel); }
.portal-view-summary { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; margin: -0.75rem 0 0.75rem; font-size: var(--portal-text-13); color: var(--portal-muted); }

/* A grouped list: each band opens with what its rows share, and how many there are. */
.portal-crm .portal-list-table .portal-group-row th {
  font-size: var(--portal-text-12);
  font-weight: 600;
  color: var(--portal-ink);
  background: var(--portal-raised);
  border-top: 1px solid var(--crm-edge);
}
.portal-crm .portal-list-table tbody:first-of-type .portal-group-row.is-depth-0 th { border-top: 0; }
.portal-group-count { margin-left: 0.375rem; font-weight: 400; color: var(--portal-muted); }
/* Groups inside groups (`is-nested`): the outermost head stands out most, each deeper one is stepped
   in under the head it sits in, and quieter. */
.portal-crm .portal-list-table.is-nested .portal-group-row.is-depth-0 th { font-size: var(--portal-text-13); background: var(--portal-head); }
.portal-crm .portal-list-table .portal-group-row.is-depth-1 th { padding-left: 2rem; background: var(--portal-raised); border-top-color: var(--crm-line); }
.portal-crm .portal-list-table .portal-group-row.is-depth-2 th { padding-left: 3.25rem; font-weight: 500; background: var(--portal-surface); border-top-color: var(--crm-line); }
.portal-crm .portal-list-table .portal-group-row.is-depth-3 th,
.portal-crm .portal-list-table .portal-group-row.is-depth-4 th { padding-left: 4.5rem; font-weight: 500; background: var(--portal-surface); border-top-color: var(--crm-line); }
.portal-group-toggle {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: default;
}
/* Folding needs script; without it the head is a plain label. */
.portal-group-caret { display: none; font-size: var(--portal-text-10); color: var(--portal-faint); transition: transform 0.15s; }
.is-foldable .portal-group-toggle { cursor: pointer; }
.is-foldable .portal-group-caret { display: inline-block; }
.portal-group-toggle[aria-expanded="false"] .portal-group-caret { transform: rotate(-90deg); }
@media (min-width: 64rem) {
  /* The outermost head stays under the column heads while its rows scroll by, and is
     pushed up out of the way when its group ends. */
  body.portal-list-page .portal-lead-table thead th { z-index: 2; }
  body.portal-list-page .portal-lead-table tr.is-depth-0 {
    position: sticky;
    top: var(--lead-heads-height, 2.25rem);
    z-index: 1;
  }
}

/* --- A Lead's page: its To-dos and the customer in the left two-fifths, the
   Conversation alone in the right three-fifths (crm slice 49). */

@media (min-width: 64.0625rem) {
  .portal-record-split { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
}

/* The pencil in a card's head that turns the card into a form. */
.portal-card-edit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: var(--portal-control-xs);
  margin: -0.25rem -0.375rem -0.25rem 0;
  color: var(--crm-quiet);
  border-radius: var(--portal-radius);
}
.portal-card-edit:hover { color: var(--portal-ink); background: var(--portal-hover); }

/* An earlier Stage on the bar is a button: clicking it asks why, then moves back. */
.portal-crm .portal-stage-back {
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.portal-crm .portal-stage-back:hover,
.portal-crm .portal-stage-back:focus-visible { color: var(--portal-ink); text-decoration: underline; }

/* A pop-up holding one form (crm/partials/pop_up_form.html). crm/js/pop-up.js opens it
   beside the button that opened it; without script it opens centred. */
.portal-pop-up {
  width: min(30rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  margin: auto;
  padding: 0;
  overflow: auto;
  color: var(--portal-body);
  background: var(--portal-surface);
  border: 0;
  border-radius: var(--portal-radius-pop);
  box-shadow: var(--portal-shadow-pop);
}
.portal-pop-up::backdrop { background: var(--portal-scrim); }
.portal-pop-up.is-placed { position: fixed; inset: auto; margin: 0; }
.portal-pop-up.is-placing { visibility: hidden; }
.portal-pop-up > .portal-form,
.portal-crm .portal-pop-up .portal-form { max-width: none; margin: 0; padding: 1.375rem 1.5rem 0; border: 0; border-radius: 0; }
/* A title in the display face, one line on what happens, the fields, then a footer with
   Cancel and the one action, always at the bottom right. Short fields that belong
   together (a To-do's date and time) share a row. */
.portal-pop-up .portal-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 1rem;
}
.portal-pop-up .portal-form > * { grid-column: 1 / -1; }
.portal-pop-up .portal-form > .portal-field:has(input[type="date"]):has(+ .portal-field input[type="time"]),
.portal-pop-up .portal-form > .portal-field:has(input[type="date"]) + .portal-field:has(input[type="time"]) { grid-column: auto; align-self: end; }
.portal-pop-up .portal-form > .portal-field:has(input[type="date"]):has(+ .portal-field input[type="time"]) { align-self: end; }
@media (max-width: 30rem) {
  .portal-pop-up .portal-form > .portal-field:has(input[type="date"]):has(+ .portal-field input[type="time"]),
  .portal-pop-up .portal-form > .portal-field:has(input[type="date"]) + .portal-field:has(input[type="time"]) { grid-column: 1 / -1; }
}
.portal-pop-up-title { margin: 0 0 0.375rem; font: 400 var(--portal-text-22)/1.25 var(--portal-display); color: var(--portal-ink); }
.portal-pop-up .portal-crm-intro { margin: 0 0 1.25rem; font-size: var(--portal-text-14); line-height: 1.5; color: var(--portal-body); }
.portal-pop-up .portal-pop-up-title + .portal-field,
.portal-pop-up .portal-pop-up-title + input + .portal-field { margin-top: 0.875rem; }
.portal-pop-up .portal-form-actions {
  justify-content: flex-end;
  margin: 1.5rem -1.5rem 0;
  padding: 0.75rem 1.5rem;
  border-top: 1px solid var(--portal-rule);
}
.portal-pop-up-cancel { cursor: pointer; }

/* Activities (crm/partials/activities.html): what to add in the head, a row of kinds to
   narrow by, then one entry each, newest first. */
/* What the Activities card's + offers: one line per kind, its mark coloured as the kind. */
.portal-add-menu { width: auto; min-width: 12rem; padding: 0.375rem; }
.portal-add-menu-item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  padding: 0.375rem 0.625rem 0.375rem 0.375rem;
  font: inherit;
  font-size: var(--portal-text-13);
  color: var(--portal-ink);
  text-align: left;
  background: none;
  border: 0;
  border-radius: var(--portal-radius);
  cursor: pointer;
}
.portal-add-menu-item:hover,
.portal-add-menu-item:focus-visible { background: var(--crm-head); }
/* A Lead's Conversation (conversations slice 21): the stream scrolls on its own under the
   card's head, stacked from the bottom so it opens at its newest item. */
.portal-conversation { display: flex; flex-direction: column; }
.portal-stream-scroll {
  display: flex;
  flex-direction: column-reverse;
  flex: 1 1 auto;
  min-height: 0;
  max-height: 32rem;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.portal-stream { margin: 0; padding: 0.25rem 1rem 1rem; list-style: none; }
.portal-stream-day { display: flex; justify-content: center; margin: 1.5rem 0 0.25rem; }
.portal-stream-day span {
  padding: 0.1875rem 0.75rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  color: var(--crm-quiet);
  background: var(--portal-surface);
  border: 1px solid var(--crm-line);
  border-radius: var(--portal-pill);
}
.portal-stream > li[hidden] { display: none; }
/* Its filter (conversations slice 22): the kinds as one row of chips, the Lead events
   switch beside them; Apply only where no script shows and hides in place. */
.portal-stream-filter {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; margin: 0;
  padding: 0.5rem 0.875rem; border-bottom: 1px solid var(--crm-line); font-size: var(--portal-text-12);
}
.portal-stream-show { display: flex; flex-wrap: wrap; gap: 0.25rem; margin: 0; padding: 0; border: 0; }
.portal-stream-show-choice span {
  display: inline-flex; align-items: center; height: 1.5rem; padding: 0 0.625rem;
  color: var(--crm-label); border: 1px solid var(--crm-line); border-radius: var(--portal-pill); cursor: pointer;
}
.portal-stream-show-choice span:hover { color: var(--portal-ink); border-color: var(--portal-ink); }
.portal-stream-show-choice input:checked + span { font-weight: 600; color: var(--portal-surface); background: var(--portal-ink); border-color: var(--portal-ink); }
.portal-stream-show-choice input:focus-visible + span { outline: 2px solid var(--portal-ink); outline-offset: 2px; }
.portal-stream-events { display: inline-flex; align-items: center; gap: 0.375rem; color: var(--crm-label); cursor: pointer; }
.portal-stream-filter.is-live .portal-stream-filter-apply { display: none; }
/* Every item the same shape: its small line, the item, its state. The customer's on the
   left, WLCA's on the right. */
.portal-stream-item { display: flex; flex-direction: column; max-width: min(85%, 36rem); margin-top: 1rem; font-size: var(--portal-text-13); }
.portal-stream-item.is-customer { align-items: flex-start; margin-right: auto; }
.portal-stream-item.is-wlca { align-items: flex-end; margin-left: auto; }
.portal-stream-item.is-burst { margin-top: 0.1875rem; }
.portal-stream-head { display: flex; align-items: center; gap: 0.375rem; min-width: 0; max-width: 100%; margin: 0 0.375rem 0.3125rem; }
.portal-stream-head .portal-activity-icon,
.portal-stream-thin .portal-activity-icon { flex: none; width: 1.125rem; height: 1.125rem; }
.portal-stream-head .portal-activity-icon svg,
.portal-stream-thin .portal-activity-icon svg { width: 0.625rem; height: 0.625rem; }
.portal-stream-kind { font-size: var(--portal-text-11); font-weight: 600; color: var(--crm-label); white-space: nowrap; }
.portal-stream-head .portal-row-who { overflow: hidden; font-size: var(--portal-text-11); text-overflow: ellipsis; }
.portal-stream-head .portal-row-at { flex: none; margin-left: 0; }
.portal-stream-edit { width: 1.5rem; height: 1.5rem; }
/* A Text: a bubble with one small corner, toward its sender. A burst's later bubbles lose
   the top one on that side too, so the run reads as one. */
.portal-stream-bubble {
  margin: 0;
  padding: 0.5625rem 0.875rem;
  overflow-wrap: anywhere;
  font-size: var(--portal-text-14);
  line-height: 1.45;
  color: var(--portal-ink);
  background: var(--portal-bubble);
  border-radius: var(--portal-radius-chat) var(--portal-radius-chat) var(--portal-radius-chat) var(--portal-radius-tail);
}
.portal-stream-item.is-wlca .portal-stream-bubble {
  color: var(--portal-surface);
  background: var(--portal-teal);
  border-radius: var(--portal-radius-chat) var(--portal-radius-chat) var(--portal-radius-tail) var(--portal-radius-chat);
}
.portal-stream-item.is-customer.is-burst .portal-stream-bubble { border-top-left-radius: var(--portal-radius-tail); }
.portal-stream-item.is-wlca.is-burst .portal-stream-bubble { border-top-right-radius: var(--portal-radius-tail); }
/* An Email, a Call, a meeting or a note: a card washed in its kind's colour, with the same
   small corner. A note's edge is dashed, as the composer's is in Note: it is never sent. */
.portal-stream-card {
  --stream-tone: var(--crm-edge);
  min-width: 14rem;
  max-width: 100%;
  padding: 0.75rem 0.875rem;
  line-height: 1.5;
  background: var(--portal-surface);
  border: 1px solid color-mix(in srgb, var(--stream-tone) 24%, transparent);
  border-radius: var(--portal-radius-chat) var(--portal-radius-chat) var(--portal-radius-chat) var(--portal-radius-tail);
}
.portal-stream-item.is-wlca .portal-stream-card { border-radius: var(--portal-radius-chat) var(--portal-radius-chat) var(--portal-radius-tail) var(--portal-radius-chat); }
.portal-stream-item.is-call .portal-stream-card { --stream-tone: var(--portal-blue); background: var(--portal-blue-wash); }
.portal-stream-item.is-email .portal-stream-card { --stream-tone: var(--portal-purple); background: var(--portal-purple-wash); }
.portal-stream-item.is-meeting .portal-stream-card { --stream-tone: var(--portal-brown); background: var(--portal-brown-wash); }
.portal-stream-item.is-note .portal-stream-card {
  --stream-tone: var(--portal-teal);
  color: var(--portal-note-ink);
  background: var(--portal-note);
  border-style: dashed;
  border-color: color-mix(in srgb, var(--portal-teal) 55%, transparent);
}
.portal-stream-item.is-missed .portal-stream-card { --stream-tone: var(--portal-danger); background: var(--portal-danger-wash); }
.portal-stream-item.is-missed .portal-stream-state { font-weight: 600; color: var(--portal-danger); }
.portal-stream-card > :first-child { margin-top: 0; }
.portal-stream-subject { margin: 0; font-size: var(--portal-text-14); font-weight: 600; }
.portal-stream-words { margin: 0.25rem 0 0; overflow-wrap: anywhere; }
.portal-stream-files { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-top: 0.625rem; }
.portal-stream-file {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  padding: 0.125rem 0.625rem;
  font-size: var(--portal-text-12);
  background: var(--portal-surface);
  border: 1px solid var(--crm-line);
  border-radius: var(--portal-pill);
}
.portal-stream-file-save { display: inline-flex; align-items: center; gap: 0.25rem; margin: 0; }
.portal-stream-file-save .portal-input { height: var(--portal-control-xs); font-size: var(--portal-text-12); }
/* Reply, Open the email, Play, Transcript: small white pills on the card. */
.portal-stream-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; margin: 0.75rem 0 0; font-size: var(--portal-text-12); }
.portal-stream-actions > a,
.portal-call-play summary {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: 1.625rem;
  padding: 0 0.75rem;
  font-weight: 600;
  color: var(--portal-ink);
  text-decoration: none;
  list-style: none;
  background: var(--portal-surface);
  border: 1px solid color-mix(in srgb, var(--stream-tone) 28%, transparent);
  border-radius: var(--portal-pill);
  cursor: pointer;
}
.portal-call-play summary::-webkit-details-marker { display: none; }
.portal-stream-actions > a:hover,
.portal-call-play summary:hover { border-color: var(--portal-ink); }
.portal-stream-actions > a:focus-visible,
.portal-call-play summary:focus-visible { outline: 2px solid var(--portal-teal); outline-offset: 2px; }
.portal-stream-actions > .portal-stream-thread { padding: 0 0.25rem; font-weight: 400; color: var(--crm-quiet); background: none; border: 0; }
.portal-stream-try-again { margin: 0.375rem 0 0; font-size: var(--portal-text-12); color: var(--crm-amber); }
.portal-stream-score { margin: 0.375rem 0 0; font-size: var(--portal-text-12); color: var(--crm-quiet); }
.portal-call-play[open] { flex-basis: 100%; }
.portal-call-play audio { display: block; width: 100%; max-width: 100%; margin-top: 0.5rem; }
.portal-stream-state { margin: 0.25rem 0.375rem 0; font-size: var(--portal-text-11); color: var(--crm-quiet); }
/* A Lead event: one thin line across the middle. */
.portal-stream-item.is-thin { max-width: none; align-items: center; margin-top: 0.625rem; }
.portal-stream-thin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.25rem 0.5rem;
  margin: 0;
  font-size: var(--portal-text-12);
  color: var(--crm-quiet);
  text-align: center;
}
.portal-stream-thin-body:empty { display: none; }
.portal-stream-thin-body::before { content: "\2014\00a0"; }
/* A round mark per kind, coloured as the kind. */
.portal-activity-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: var(--portal-control-xs);
  color: var(--crm-quiet);
  background: var(--crm-head);
  border-radius: var(--portal-round);
}
.portal-stream-item.is-stage .portal-stream-kind,
.portal-stream-item.is-stage .portal-activity-icon { color: var(--crm-teal); }
.portal-stream-item.is-stage .portal-activity-icon { background: var(--portal-teal-wash); }
.portal-stream-item.is-move-back .portal-stream-kind,
.portal-stream-item.is-move-back .portal-activity-icon { color: var(--crm-amber); }
.portal-stream-item.is-move-back .portal-activity-icon { background: var(--crm-amber-wash); }
/* A Lead claimed back from a Partner (crm slice 25): a change of hands, marked like a move back. */
.portal-stream-item.is-claim .portal-stream-kind,
.portal-stream-item.is-claim .portal-activity-icon { color: var(--crm-amber); }
.portal-stream-item.is-claim .portal-activity-icon { background: var(--crm-amber-wash); }
.portal-stream-item.is-call .portal-activity-icon,
.portal-add-menu-item.is-call .portal-activity-icon { color: var(--portal-blue); background: var(--portal-blue-wash); }
.portal-stream-item.is-text .portal-activity-icon,
.portal-add-menu-item.is-text .portal-activity-icon { color: var(--portal-teal); background: var(--portal-teal-wash); }
.portal-stream-item.is-email .portal-activity-icon,
.portal-add-menu-item.is-email .portal-activity-icon { color: var(--portal-purple); background: var(--portal-purple-wash); }
.portal-stream-item.is-meeting .portal-activity-icon,
.portal-add-menu-item.is-meeting .portal-activity-icon { color: var(--portal-brown); background: var(--portal-brown-wash); }
.portal-stream-item.is-task .portal-activity-icon { color: var(--portal-positive); background: var(--portal-positive-wash); }

/* Two lines per To-do -- what it is, who and when; then what it says,
   cut to the line -- and the whole of it opens its pop-up, which shows it all. */
.portal-row-open {
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr);
  gap: 0.125rem 0.75rem;
  align-items: center;
  width: 100%;
  padding: 0.625rem 1rem;
  font: inherit;
  font-size: var(--portal-text-13);
  color: var(--portal-ink);
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.portal-row-open:hover,
.portal-row-open:focus-visible { background: var(--crm-head); }
.portal-row-open > .portal-activity-icon { grid-row: span 2; align-self: start; }
.portal-row-head { display: flex; align-items: baseline; gap: 0.5rem; min-width: 0; }
.portal-row-head > * { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.portal-row-text { grid-column: 2; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.portal-row-text:empty { display: none; }
.portal-row-who { font-size: var(--portal-text-12); color: var(--crm-quiet); white-space: nowrap; }
.portal-row-at { flex: none; margin-left: auto; }

/* A small round button that is only its mark: + adds a To-do, the tick marks one done. */
.portal-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: var(--portal-control-xs);
  padding: 0;
  color: var(--crm-quiet);
  background: none;
  border: 0;
  border-radius: var(--portal-round);
  cursor: pointer;
}
.portal-icon-button:hover,
.portal-icon-button:focus-visible { color: var(--crm-teal); background: var(--portal-teal-wash); }
.portal-to-do-tick:hover,
.portal-to-do-tick:focus-visible { color: var(--portal-positive); background: var(--portal-positive-wash); }

/* A To-do's pop-up: what it is, who and when, above its form. */
.portal-to-do-pop-up { padding-top: 1.25rem; }
.portal-to-do-pop-up > .portal-pop-up-title,
.portal-to-do-pop-up > p { margin-left: 1.5rem; margin-right: 1.5rem; }
.portal-to-do-pop-up > .portal-meta { margin-top: -0.5rem; margin-bottom: 0; font-size: var(--portal-text-12); }
.portal-crm .portal-to-do-pop-up .portal-form { padding-top: 1rem; }
.portal-pop-up-planned { margin-top: 0.75rem; margin-bottom: 0; font-size: var(--portal-text-13); color: var(--crm-teal); }
.portal-pop-up-body { margin-top: 0.75rem; font-size: var(--portal-text-13); overflow-wrap: anywhere; }
.portal-crm .portal-to-do-done-form { padding-top: 1.25rem; }

/* On a wide screen the card stays in view under the title band and fills the window
   below it, its stream scrolling inside. */
@media (min-width: 64rem) {
  .portal-conversation {
    position: sticky;
    top: calc(var(--crm-header-height) + var(--crm-title-height) + var(--crm-gap));
    max-height: calc(100vh - var(--crm-header-height) - var(--crm-title-height) - 2 * var(--crm-gap));
  }
  .portal-stream-scroll { max-height: none; }
}

/* A details card edited in place (a Lead's Customer): the same rows
   in the same places, each editable value now a light box at the value's size, so the
   card reads the same and shows what can change. Save and Cancel take the pencil's place. */
.portal-card-edit-actions { display: flex; align-items: center; gap: 0.875rem; }
.portal-card-edit-actions .portal-quiet { font-size: var(--portal-text-12); font-weight: 500; letter-spacing: 0; text-transform: none; }
.portal-crm .portal-card-edit-actions .portal-button { height: var(--portal-control-xs); padding: 0 0.875rem; font-size: var(--portal-text-12); }
.portal-crm-card.is-editing .portal-facts dt label { font: inherit; color: inherit; cursor: pointer; }
.portal-crm-card.is-editing .portal-facts dd:has(.portal-fact-input) { padding-top: 0.25rem; padding-bottom: 0.25rem; }

/* A Lead's Customer card and its tabs (crm slice 50): Overview, Contacts, Price list and
   Projects. Each tab's card sits flat inside it, its head a quiet line holding its own
   actions. Without script every panel shows, one after another, each under its own head;
   with it the strip shows, one panel at a time, and the strip names it. */
.portal-customer-tabs {
  display: flex;
  gap: 1.25rem;
  padding: 0 1rem;
  overflow-x: auto;
  scrollbar-width: thin;
  border-bottom: 1px solid var(--crm-edge);
}
.portal-customer-tabs[hidden] { display: none; }
.portal-customer-tab {
  margin: 0;
  padding: 0.625rem 0 0.5rem;
  font: inherit;
  font-size: var(--portal-text-13);
  font-weight: 500;
  color: var(--portal-muted);
  white-space: nowrap;
  cursor: pointer;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
}
.portal-customer-tab:hover { color: var(--portal-ink); }
.portal-customer-tab[aria-selected="true"] { font-weight: 600; color: var(--portal-ink); border-bottom-color: var(--portal-ink); }
.portal-customer-tab .portal-group-count { margin-left: 0.25rem; }
.portal-customer-panel[hidden] { display: none; }
.portal-customer-panel > .portal-crm-card { margin: 0; border: 0; border-top: 1px solid var(--crm-edge); border-radius: 0; }
.portal-customer-card.is-tabbed .portal-customer-panel > .portal-crm-card:first-child { border-top: 0; }
.portal-customer-panel > .portal-crm-card > .portal-crm-card-head { background: none; }
/* With the strip naming the tab, a tab's own card head keeps only its actions. */
.portal-customer-card.is-tabbed .portal-customer-panel:not([data-tab="overview"]) > .portal-crm-card > .portal-crm-card-head { justify-content: flex-end; }
.portal-customer-card.is-tabbed .portal-customer-panel:not([data-tab="overview"]) > .portal-crm-card > .portal-crm-card-head > h2 {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.portal-customer-card.is-tabbed .portal-customer-panel:not([data-tab="overview"]) > .portal-crm-card > .portal-crm-card-head:not(:has(> :not(h2))) { display: none; }
/* The pencil edits the Overview's facts, so it shows beside that tab alone. */
.portal-customer-card.is-tabbed:not([data-tab="overview"]) .portal-crm-card-head [data-tab-only="overview"] { visibility: hidden; }
.portal-customer-edit { display: inline-flex; }
/* More details: the facts a rep rarely needs while talking, folded under the key ones. */
.portal-more-details { border-top: 1px solid var(--crm-line); }
.portal-more-details > summary {
  padding: 0.5rem 0.875rem;
  font-size: var(--portal-text-12);
  font-weight: 600;
  color: var(--crm-quiet);
  cursor: pointer;
}
.portal-more-details > summary:hover { color: var(--portal-ink); }
.portal-more-details[open] > summary { border-bottom: 1px solid var(--crm-line); }
.portal-fact-input input,
.portal-fact-input select,
.portal-fact-input textarea {
  display: block;
  width: 100%;
  min-height: 2rem;
  margin: 0;
  padding: 0.25rem 0.5rem;
  font: inherit;
  font-size: var(--portal-text-13);
  line-height: 1.5;
  color: var(--portal-ink);
  background: var(--portal-surface);
  border: 1px solid var(--portal-edge);
  border-radius: var(--portal-radius);
  resize: vertical;
}
.portal-fact-input input:hover,
.portal-fact-input select:hover,
.portal-fact-input textarea:hover { border-color: var(--portal-edge-hover); }
.portal-fact-input input:focus,
.portal-fact-input select:focus,
.portal-fact-input textarea:focus { outline: none; border-color: var(--portal-teal); box-shadow: var(--portal-focus-ring); }
.portal-fact-input.is-invalid input,
.portal-fact-input.is-invalid select,
.portal-fact-input.is-invalid textarea { border-color: var(--portal-danger); }
.portal-fact-input .errorlist { margin: 0.25rem 0 0; padding: 0; list-style: none; font-size: var(--portal-text-12); color: var(--portal-danger); }
.portal-crm-card.is-editing > form > .errorlist,
.portal-customer-panel > form > .errorlist { margin: 0; padding: 0.625rem 1rem; list-style: none; font-size: var(--portal-text-13); color: var(--portal-danger); background: var(--portal-danger-wash); }

/* Days without contact, beside the Activities title: green inside its Stage's Contact
   window, red past it, grey when no window is set. */
.portal-activity-title { display: flex; align-items: center; gap: 0.625rem; flex-wrap: wrap; }
.portal-contact-quiet {
  padding: 0.125rem 0.5rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--crm-quiet);
  background: var(--portal-badge);
  border-radius: var(--portal-pill);
  white-space: nowrap;
}
.portal-contact-quiet.is-safe { color: var(--portal-positive); background: var(--portal-positive-wash); }
.portal-contact-quiet.is-late { color: var(--portal-danger); background: var(--portal-danger-tint); }

/* Waiting on you, beside it: amber while the customer's message is the newest, with Done
   beside it; who pressed Done last, to a WLCA sales manager. */
.portal-waiting {
  padding: 0.125rem 0.5rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  color: var(--portal-amber);
  background: var(--portal-amber-wash);
  border-radius: var(--portal-pill);
  white-space: nowrap;
}
.portal-waiting-done { display: inline; margin: 0; }
.portal-waiting-last-done { font-size: var(--portal-text-11); }
.portal-conversation-waiting { display: contents; }
.portal-inbox-live { display: contents; }

/* The To-dos card, first in the Lead page's left column: one line per open To-do, amber when due
   today, red when late, with its tick. A long list scrolls inside the card. */
.portal-to-dos { position: relative; }
.portal-to-do-list { margin: 0; padding: 0; list-style: none; max-height: 16rem; overflow-y: auto; }
.portal-to-do { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; padding-right: 0.5rem; }
.portal-to-do + .portal-to-do { border-top: 1px solid var(--crm-edge); }
.portal-to-do form { margin: 0; }
.portal-to-do-when { font-size: var(--portal-text-12); font-weight: 600; color: var(--crm-teal); white-space: nowrap; }
.portal-to-do .portal-activity-icon { color: var(--crm-teal); background: var(--portal-teal-wash); }
.portal-to-do.is-due { background: var(--portal-amber-faint); }
.portal-to-do.is-due .portal-to-do-when,
.portal-to-do.is-due .portal-activity-icon { color: var(--crm-amber); }
.portal-to-do.is-due .portal-activity-icon { background: var(--crm-amber-wash); }
.portal-to-do.is-late { background: var(--portal-danger-wash); }
.portal-to-do.is-late .portal-to-do-when,
.portal-to-do.is-late .portal-activity-icon { color: var(--portal-danger); }
.portal-to-do.is-late .portal-activity-icon { background: var(--portal-danger-tint); }
.portal-to-do .portal-row-open:hover { background: var(--portal-hover-faint); }
.portal-to-do-none { padding: 0.75rem 1rem; font-size: var(--portal-text-13); }
/* The Price list card's price check (price-lists slice 23): a code in, its prices out. */
.portal-price-check { display: grid; gap: 0.5rem; margin: 0.25rem 0 0; padding: 0.875rem 1rem 0; border-top: 1px solid var(--crm-line); font-size: var(--portal-text-13); }
.portal-price-check label { font-weight: 600; color: var(--crm-label); }
/* One joined field: the glass, the code, and Check sitting inside its right end. */
.portal-price-check-row {
  position: relative;
  display: flex;
  align-items: center;
  height: var(--portal-control-sm);
  padding: 0.1875rem 0.1875rem 0.1875rem 2rem;
  background: var(--portal-surface);
  border: 1px solid var(--portal-edge);
  border-radius: var(--portal-radius-pop);
}
.portal-price-check-row:hover { border-color: var(--portal-edge-hover); }
.portal-price-check-row:focus-within { border-color: var(--portal-teal); box-shadow: var(--portal-focus-ring); }
.portal-price-check-icon { position: absolute; left: 0.6875rem; top: 50%; transform: translateY(-50%); color: var(--crm-quiet); pointer-events: none; }
.portal-price-check-row input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  padding: 0;
  font: inherit;
  font-size: var(--portal-text-14);
  color: var(--portal-ink);
  background: transparent;
  border: 0;
  outline: none;
}
.portal-price-check-row input::placeholder { color: var(--portal-ghost); }
.portal-price-check-row input::-webkit-search-cancel-button { cursor: pointer; }
.portal-price-check-go {
  flex: none;
  height: 100%;
  padding: 0 0.875rem;
  font: inherit;
  font-size: var(--portal-text-13);
  font-weight: 600;
  color: var(--portal-surface);
  background: var(--portal-ink);
  border: 0;
  border-radius: calc(var(--portal-radius-pop) - 0.1875rem);
  cursor: pointer;
}
.portal-price-check-go:hover { background: var(--portal-ink-hover); }
.portal-price-check-go:focus-visible { outline: 2px solid var(--portal-teal); outline-offset: 2px; }
.portal-price-check-answer { padding: 0.625rem 1rem 0.875rem; font-size: var(--portal-text-13); }
.portal-price-check-answer:empty { display: none; }
.portal-price-check-table { width: 100%; border-collapse: collapse; }
.portal-price-check-table thead th { padding: 0 0 0.375rem; font-size: var(--portal-text-11); font-weight: 600; text-align: left; color: var(--crm-quiet); border-bottom: 1px solid var(--crm-line); }
.portal-price-check-table thead th:not(:first-child) { padding-left: 0.75rem; text-align: right; }
.portal-price-check-table tbody th,
.portal-price-check-table td { padding: 0.5rem 0; text-align: left; vertical-align: top; border-bottom: 1px solid var(--crm-line); }
.portal-price-check-table tbody tr:last-child > * { border-bottom: 0; padding-bottom: 0; }
.portal-price-check-table td { padding-left: 0.75rem; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.portal-price-check-table td small { font-size: var(--portal-text-11); color: var(--crm-quiet); }
.portal-price-check-table tbody th { font-weight: 400; }
.portal-price-check-code { display: block; font-weight: 600; color: var(--portal-ink); }
.portal-price-check-name { display: block; font-size: var(--portal-text-12); color: var(--crm-quiet); }
.portal-price-check-selling { font-weight: 600; color: var(--portal-ink); }
.portal-price-check-retail { color: var(--crm-quiet); }
.portal-price-check-none { margin: 0 0 0.25rem; }
/* A Quote just Sent offers its follow-up Call, under the To-dos (quotes slice 22). */
.portal-follow-up-offer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin: 0;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--crm-edge);
  font-size: var(--portal-text-13);
}
.portal-follow-up-offer p { flex: 1 1 12rem; margin: 0; }
/* A Project's standing Quote in words, under its progress line (quotes slice 22). */
.portal-project-quote { display: block; margin-top: 0.375rem; font-size: var(--portal-text-13); color: var(--portal-muted); }
/* A Lead's Contact persons (crm slice 43): two lines each, like a To-do; the main one marked. */
.portal-contact-person-list { margin: 0; padding: 0; list-style: none; }
.portal-contact-person + .portal-contact-person { border-top: 1px solid var(--crm-edge); }
.portal-contact-person .portal-activity-icon { color: var(--crm-teal); background: var(--portal-teal-wash); }
.portal-contact-person-name { font-weight: 600; }
.portal-contact-person-main {
  flex: none;
  padding: 0 0.5rem;
  font-size: var(--portal-text-12);
  font-weight: 600;
  color: var(--crm-teal);
  background: var(--portal-teal-wash);
  border-radius: var(--portal-pill);
}
.portal-row-open.is-static { cursor: default; }
.portal-row-open.is-static:hover { background: none; }
/* A Contact person's phone dials through Ringover (conversations slice 06): a link can sit
   in no button, so its name is the button, stretched over the whole row, and the link
   sits above it -- the row still opens its pop-up anywhere but on the number. */
.portal-row-open.is-opened-by-its-name { position: relative; }
.portal-row-open.is-opened-by-its-name:hover,
.portal-row-open.is-opened-by-its-name:focus-within { background: var(--crm-head); }
.portal-contact-person-open {
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.portal-contact-person-open::after { content: ""; position: absolute; inset: 0; }
.portal-contact-person-open:focus-visible { outline: none; }
.portal-contact-person-dial { position: relative; z-index: 1; color: var(--crm-teal); }
.portal-contact-person-moves { justify-content: flex-start; gap: 1.25rem; margin: 1rem 1.5rem 0; }
.portal-contact-person-moves form { margin: 0; }
.portal-contact-person-remove { color: var(--portal-danger); }
/* A number that is an Opt-out (conversations slice 12): never texted. */
.portal-contact-person-opt-out {
  padding: 0 0.5rem;
  font-size: var(--portal-text-12);
  font-weight: 600;
  color: var(--portal-danger-strong);
  border: 1px solid currentColor;
  border-radius: var(--portal-pill);
}
.portal-contact-person-opt-out-change { margin: 1rem 1.5rem 1.25rem; padding-top: 0.75rem; border-top: 1px solid var(--crm-edge); }
.portal-contact-person-opt-out-change p { margin: 0 0 0.5rem; }
.portal-contact-person-opt-out-change form { margin: 0; }
.portal-fact-input + .portal-fact-input { margin-top: 0.375rem; }
/* A pop-up's To-do sits apart from what was said: it is optional. */
.portal-pop-up .portal-field:has([name="to_do_kind"]) { margin-top: 1.25rem; padding-top: 1rem; border-top: 1px dashed var(--crm-edge); }

/* What a change said, as a banner over the top of the Conversation that fades after
   a few seconds; a refusal stays until the next page. */
.portal-conversation { position: relative; }
.portal-activity-toasts {
  position: absolute;
  top: 3.25rem;
  left: 0.75rem;
  right: 0.75rem;
  z-index: 2;
  margin: 0;
  padding: 0;
  list-style: none;
  pointer-events: none;
}
.portal-activity-toasts li {
  margin-bottom: 0.375rem;
  padding: 0.625rem 0.875rem;
  font-size: var(--portal-text-13);
  font-weight: 500;
  color: var(--portal-surface);
  background: var(--crm-teal);
  border-radius: var(--portal-radius);
  box-shadow: var(--portal-shadow-lift);
  animation: portal-toast 4s ease forwards;
}
.portal-activity-toasts li.error { background: var(--portal-danger); animation: none; pointer-events: auto; }
@keyframes portal-toast {
  0% { opacity: 0; transform: translateY(-4px); }
  8%, 80% { opacity: 1; transform: none; }
  100% { opacity: 0; visibility: hidden; }
}

/* The Brief card: one standing text, edited in place. */
.portal-brief { margin: 0; padding: 0.875rem 1rem; font-size: var(--portal-text-13); line-height: 1.6; }
form.portal-brief { padding: 0.625rem 0.75rem; }

/* A Sales desk list on a wide screen (Leads, Queue, Scorecards): everything
   down to the table's column heads stays put -- the header, the title, the tabs, the
   search -- and only the rows scroll, inside `.portal-list-body`, under heads stuck to
   its top. The Queue's two tables scroll as one, each head sticking in turn.
   Narrower, the page scrolls as one. */
@media (min-width: 64rem) {
  body.portal-list-page { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
  body.portal-list-page > .portal-header { flex: none; }
  body.portal-list-page > .portal-footer { display: none; }
  body.portal-list-page > .portal-main {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    padding-bottom: 1.25rem;
  }
  body.portal-list-page > .portal-main > * { flex: none; }
  body.portal-list-page > .portal-main > .portal-list-body {
    flex: 0 1 auto;
    min-height: 0;
    margin-bottom: 0;
    overflow: auto;
    overscroll-behavior: contain;
  }
  body.portal-list-page .portal-list-table thead th { top: 0; }
}

/* A Lead's page on a wide screen: everything down to the Stage bar stays
   put, and each column scrolls on its own -- the cards on the left, the Conversation
   on the right. Narrower, the page scrolls as one, its tabs a phone's (crm slice 53). */
@media (min-width: 64.0625rem) {
  body.portal-record-page { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
  body.portal-record-page > .portal-header { flex: none; }
  body.portal-record-page > .portal-footer { display: none; }
  body.portal-record-page > .portal-main {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    padding-bottom: 1.25rem;
  }
  body.portal-record-page .portal-crm-head,
  body.portal-record-page .portal-stage-bar { flex: none; }
  /* A long repeats notice scrolls inside itself, so it never squeezes the columns
     below to nothing and leaves the Projects card out of reach. */
  body.portal-record-page .portal-repeats { flex: none; max-height: 30vh; overflow-y: auto; }
  body.portal-record-page .portal-record-split { flex: 1 1 auto; min-height: 0; align-items: stretch; }
  body.portal-record-page .portal-record-split > div { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
  body.portal-record-page .portal-record-cards { padding-right: 0.25rem; }
  body.portal-record-page .portal-record-cards > :last-child { margin-bottom: 0; }
  body.portal-record-page .portal-record-conversation { display: flex; flex-direction: column; overflow: hidden; }
  body.portal-record-page .portal-conversation { position: relative; top: auto; flex: 1 1 auto; max-height: none; min-height: 0; margin-bottom: 0; }
}

/* Orders: the Order card beside the Quote it follows, and Place order's two lanes. */
.portal-project-status--placed { color: var(--crm-teal); background: var(--portal-teal-wash); }
.portal-order-card .portal-order-place { align-self: flex-start; }
.portal-order-lanes { display: grid; grid-template-columns: minmax(0, 3fr) minmax(18rem, 2fr); gap: 1.5rem; align-items: start; }
.portal-order-lines { width: 100%; }
/* A short list inside a card: its heads never stick as a Sales desk list's do. */
.portal-crm .portal-order-lines thead th { position: static; }
.portal-order-lines .portal-order-quantity { text-align: right; white-space: nowrap; }
.portal-order-line--cabinet td { font-weight: 600; }
.portal-order-line--part td:first-child { padding-left: 1.5rem; }
.portal-order-form { max-width: none; }
@media (max-width: 900px) {
  .portal-order-lanes { grid-template-columns: minmax(0, 1fr); }
}
/* Orders: each line's Purchase price and the total, for the Partner manager (slice 04). */
.portal-order-lines .portal-order-amount { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.portal-order-lines .portal-order-total th { text-align: right; }
.portal-order-lines .portal-order-total th,
.portal-order-lines .portal-order-total td { font-weight: 600; border-top: 1px solid var(--portal-rule-strong); }
.portal-order-reveal { margin-top: 0.5rem; font-size: var(--portal-text-13); color: var(--portal-muted); }
.portal-order-reveal form { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.portal-order-reveal .portal-pop-up { color: var(--portal-ink); font-size: var(--portal-text-16); }
.portal-order-lines-scroll { overflow-x: auto; }
.portal-order-lines td:first-child { white-space: nowrap; }
.portal-order-card .portal-order-lines { font-size: var(--portal-text-13); }
.portal-order-card .portal-order-lines th,
.portal-order-card .portal-order-lines td { padding-left: 0.5rem; padding-right: 0.5rem; }
.portal-order-card .portal-order-lines thead th { white-space: normal; letter-spacing: 0.02em; }
/* The Order card's state, deliveries and invoices, read from Odoo (orders slice 05). */
.portal-project-status--paid { color: var(--portal-surface); background: var(--crm-teal); }
.portal-project-status--delivered { color: var(--portal-surface); background: var(--portal-ink); }
.portal-project-status--cancelled { color: var(--portal-danger); background: var(--portal-danger-wash); }
.portal-order-unread { margin: 0.25rem 0 0; font-size: var(--portal-text-13); color: var(--portal-danger); }
.portal-order-deliveries { margin: 0; padding: 0; list-style: none; font-size: var(--portal-text-13); color: var(--portal-muted); }
.portal-order-deliveries li + li { margin-top: 0.125rem; }
.portal-order-delivery-name { margin-right: 0.375rem; color: var(--portal-ink); font-weight: 600; }
.portal-order-subhead { margin: 0.5rem 0 0.25rem; font-size: var(--portal-text-13); font-weight: 600; }
.portal-order-lines .portal-order-day { white-space: nowrap; }
/* A revision waiting to be sent onto the Order (orders slice 09). */
.portal-order-revision { display: flex; flex-direction: column; gap: 0.375rem; padding: 0.5rem 0.75rem; border-left: 3px solid var(--portal-ink); background: var(--portal-panel); }
.portal-order-revision-note { margin: 0; font-size: var(--portal-text-14); }
.portal-order-revision .portal-order-lock { margin: 0; }
.portal-order-card .portal-order-revise { align-self: flex-start; }
.portal-order-cancel, .portal-order-waive { display: flex; }

/* Push on this device (notifications slice 05): the bell panel's card, and its section
   on Notification choices. */
.portal-bell-panel-slot:not(:has(> :not([hidden]))) { display: none; }
.portal-push-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.75rem;
  padding: 0.75rem;
  background: var(--portal-panel);
  border-radius: var(--portal-radius-pop);
}
.portal-push-card[hidden] { display: none; }
.portal-push-card-icon { margin-top: 0.125rem; color: var(--portal-muted); }
.portal-push-card-words p { margin: 0 0 0.375rem; font-size: var(--portal-text-13); color: var(--portal-body); }
.portal-push-card-words p[hidden] { display: none; }
.portal-push-card-words .portal-push-card-title { font-weight: 600; color: var(--portal-ink); }
.portal-push-card-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }
.portal-push-card-actions[hidden] { display: none; }
.portal-push-card-actions .portal-button[hidden] { display: none; }
.portal-push-card-actions .portal-button { padding: 0.375rem 0.875rem; font-size: var(--portal-text-13); }
.portal-push-device { display: grid; gap: 0.75rem; justify-items: start; margin-top: 2.5rem; }
.portal-push-device h2 { margin: 0; font: 400 var(--portal-text-22)/1.2 var(--portal-display); }
.portal-push-device h3 { margin: 0.75rem 0 0; font-size: var(--portal-text-13); font-weight: 600; }
.portal-push-device [data-push-device] { display: grid; gap: 0.5rem; justify-items: start; }
.portal-push-device [data-push-device] > div:not([hidden]) { display: grid; gap: 0.5rem; justify-items: start; }
.portal-push-device [hidden] { display: none; }
.portal-push-device p { margin: 0; }
.portal-push-on { color: var(--portal-positive); font-weight: 500; }
.portal-push-blocked { max-width: 40rem; padding: 0.625rem 0.875rem; color: var(--portal-danger-strong); background: var(--portal-danger-wash); border-radius: var(--portal-radius-pop); }
.portal-push-home-screen { max-width: 40rem; padding: 0.625rem 0.875rem; background: var(--portal-blue-wash); border-radius: var(--portal-radius-pop); }
.portal-push-devices { display: grid; gap: 0.375rem; margin: 0; padding: 0; list-style: none; }
.portal-push-devices li { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* A Call opened whole (conversations/call_detail.html): its recording and transcript. */
.portal-call-recording { display: block; width: 100%; }
.portal-call-transcript { margin: 0; line-height: 1.6; overflow-wrap: anywhere; }

/* Conversations slice 07: a Call's AI summary and its Call score. */
.portal-call-summary { margin: 0; line-height: 1.6; }
.portal-call-score { display: grid; gap: 0.75rem; margin: 0; padding: 0; list-style: none; }
.portal-call-score li { display: flex; gap: 0.75rem; align-items: flex-start; line-height: 1.5; }
.portal-call-score-mark { flex: none; min-width: 2.75rem; padding: 0.125rem 0.5rem; border-radius: var(--portal-radius-pop); font-size: var(--portal-text-12); font-weight: 600; text-align: center; }
.portal-call-score .is-passed .portal-call-score-mark { color: var(--portal-positive); background: var(--portal-positive-wash); }
.portal-call-score .is-failed .portal-call-score-mark { color: var(--portal-danger-strong); background: var(--portal-danger-wash); }

/* Conversations slice 05: the House Account Leads an Unmatched may be filed on. */
.portal-unmatched-leads { list-style: none; margin: 1rem 0 0; padding: 0; }
.portal-unmatched-leads > li { padding: 0.75rem 0; }
.portal-unmatched-leads > li + li { border-top: 1px solid var(--portal-rule); }
.portal-unmatched-leads p { margin: 0 0 0.5rem; }
#unmatched tr.is-new-number > * { border-top: 2px solid var(--portal-rule); }
#partner-leads form + form { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--portal-rule); }

/* Conversations slice 15: an Email's words kept as written, its files, and Send email
   offered as a link in the Conversation's + menu. */
.portal-email-words { margin: 0; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.portal-email-signature { display: grid; gap: 0.25rem; padding: 0.75rem; background: var(--portal-stone-wash); border-radius: var(--portal-radius); }
.portal-email-signature p { margin: 0; }
.portal-email-files { display: grid; gap: 0.5rem; margin: 0; padding: 0; list-style: none; }
/* An Email's file saved to one of the Lead's Projects (conversations slice 18). */
.portal-email-file { display: grid; gap: 0.35rem; overflow-wrap: anywhere; }
.portal-email-file-save { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.portal-email-file-save select { width: auto; min-width: 0; max-width: 100%; }
.portal-email-answering { display: grid; gap: 0.25rem; padding: 0.75rem; border-left: 3px solid var(--portal-teal-wash); background: var(--portal-stone-wash); border-radius: var(--portal-radius); }
.portal-email-answering p { margin: 0; }
a.portal-add-menu-item { text-decoration: none; }

/* The composer at the foot of a Lead's Conversation (conversations slices 23, 24, 31): one
   box, kept low, and one height in every mode (slice 31): the words take what the other
   rows leave, so switching mode never moves the page. Its top row holds Text, Email or Note on a segmented switch, To and ⋯;
   then the words with Send beside them, growing as they are written; then one small
   line -- the counter or where it goes from, and Quick replies. Email adds a thin subject
   row (and CC, behind its switch on the top row) over the words, a clip for files and
   Full editor. In Note the box turns dashed and
   note-coloured, as a note in the stream is: it is never sent. Which part shows for
   which mode is the chosen switch's, so it works with no script. */
.portal-composer {
  --composer-edge: var(--portal-edge-soft);
  --composer-paper: var(--portal-surface);
  --composer-rule: var(--crm-line);
  --composer-track: var(--portal-head);
  --composer-on: var(--portal-ink);
  --composer-corner: calc(2.5 * var(--portal-radius));
  --composer-height: 9.25rem;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0.5rem 1rem 0.625rem;
  background: var(--portal-surface);
  border-top: 1px solid var(--crm-line);
}
/* On a phone To drops under the switch, so the one height is taller. */
@media (max-width: 40rem) {
  .portal-composer { --composer-height: 11.75rem; }
}
.portal-composer:has(.portal-composer-box:focus-within) { --composer-edge: var(--portal-teal); }
.portal-composer:has(input[name="mode"][value="note"]:checked) {
  --composer-edge: color-mix(in srgb, var(--portal-teal) 55%, transparent);
  --composer-paper: var(--portal-note);
  --composer-rule: color-mix(in srgb, var(--portal-teal) 30%, transparent);
  --composer-track: color-mix(in srgb, var(--portal-teal) 12%, var(--portal-note));
  --composer-on: var(--portal-note-ink);
}
.portal-composer-box {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: var(--composer-height);
  background: var(--composer-paper);
  border: 1px solid var(--composer-edge);
  border-radius: var(--composer-corner);
  transition: border-color 0.15s, background-color 0.15s;
}
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-box { border-style: dashed; }
/* The top row: the switch, To (or Note's hint) taking what is left, ⋯ at the end. Too
   narrow for a name beside the switch, To drops under it. */
.portal-composer-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.375rem;
  padding: 0 0.25rem 0 0.3125rem;
  border-bottom: 1px solid var(--composer-rule);
}
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-bar { border-bottom-style: dashed; }
.portal-composer-modes {
  flex: none;
  display: inline-flex;
  margin: 0;
  padding: 2px;
  background: var(--composer-track);
  border: 0;
  border-radius: calc(1.75 * var(--portal-radius));
}
.portal-composer-mode span {
  display: inline-flex;
  align-items: center;
  height: 1.875rem;
  padding: 0 0.75rem;
  font-size: var(--portal-text-12);
  font-weight: 600;
  color: var(--portal-muted);
  border-radius: var(--portal-radius);
  cursor: pointer;
}
.portal-composer-mode span:hover { color: var(--portal-ink); }
.portal-composer-mode input:checked + span { color: var(--portal-surface); background: var(--composer-on); }
.portal-composer-mode input:focus-visible + span { outline: 2px solid var(--portal-teal); outline-offset: 1px; }
.portal-composer-more { flex: none; width: 2.125rem; height: 2.125rem; margin-left: auto; border-radius: var(--portal-radius-pop); }
.portal-composer-to { flex: 1 1 9rem; display: flex; align-items: center; gap: 0.375rem; min-width: 0; font-size: var(--portal-text-12); color: var(--crm-quiet); }
.portal-composer-to > span { flex: none; }
/* Email's CC switch, on the To row: CC's line shows while it is on. */
.portal-composer-cc-open { flex: none; display: inline-flex; }
.portal-composer-cc-open span {
  display: inline-flex;
  align-items: center;
  height: 1.5rem;
  padding: 0 0.5rem;
  font-size: var(--portal-text-11);
  font-weight: 600;
  color: var(--crm-quiet);
  border: 1px solid var(--composer-rule);
  border-radius: var(--portal-radius);
  cursor: pointer;
}
.portal-composer-cc-open span:hover { color: var(--portal-ink); }
.portal-composer-cc-open input:checked + span { color: var(--crm-teal); background: var(--portal-teal-wash); border-color: transparent; }
.portal-composer-cc-open input:focus-visible + span { outline: 2px solid var(--portal-teal); outline-offset: 1px; }
.portal-composer:not(:has(input[name="mode"][value="email"]:checked)) .portal-composer-cc-open,
.portal-composer:not(:has([data-composer-cc-open]:checked)) .portal-composer-cc { display: none; }
.portal-composer-bar > .portal-composer-note-hint { flex: 1 1 9rem; min-width: 0; font-size: var(--portal-text-12); color: var(--portal-note-ink); }
/* Email's lines: a label, then a field with no box of its own, a hairline under each. */
.portal-composer-email { display: flex; flex-direction: column; margin: 0; font-size: var(--portal-text-13); }
.portal-composer-line {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 1.75rem;
  padding: 0 0.75rem;
  font-size: var(--portal-text-12);
  color: var(--crm-quiet);
  border-bottom: 1px solid var(--composer-rule);
}
.portal-composer-line > span { flex: none; min-width: 3rem; }
.portal-composer .portal-composer-to .portal-input,
.portal-composer .portal-composer-line .portal-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 1.625rem;
  padding: 0;
  font-size: var(--portal-text-13);
  font-weight: 500;
  background-color: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.portal-composer .portal-composer-to select.portal-input { padding-right: 1.5rem; background-position: right 0.25rem center; cursor: pointer; }
.portal-composer-replying { margin: 0; padding: 0.375rem 0.75rem; font-size: var(--portal-text-12); color: var(--crm-label); background: var(--portal-raised); border-bottom: 1px solid var(--composer-rule); }
/* The words, with the clip and Full editor (Email) and Send beside them, at their foot.
   They stretch to fill the box, and grow past it as they are written, up to 15rem. */
.portal-composer-write { flex: 1 1 auto; display: flex; flex-direction: column; }
.portal-composer-words { flex: 1 1 auto; display: flex; align-items: flex-end; gap: 0.375rem; padding: 0.25rem 0.375rem 0.25rem 0.75rem; }
.portal-composer .portal-composer-body {
  flex: 1 1 auto;
  align-self: stretch;
  min-width: 0;
  height: auto;
  min-height: 1.75rem;
  max-height: 15rem;
  padding: 0.25rem 0;
  font-size: var(--portal-text-14);
  line-height: 1.45;
  color: var(--portal-ink);
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  outline: none;
  resize: vertical;
  field-sizing: content;
}
@supports (field-sizing: content) {
  .portal-composer .portal-composer-body { resize: none; }
}
.portal-composer-body::placeholder { color: var(--portal-ghost); }
.portal-composer-files { flex: none; width: 2.25rem; height: 2.25rem; border-radius: var(--portal-radius-pop); }
.portal-composer-files:has(input:focus-visible) { outline: 2px solid var(--portal-teal); outline-offset: 1px; }
.portal-composer-full-editor { flex: none; width: 2.25rem; height: 2.25rem; border-radius: var(--portal-radius-pop); }
.portal-composer:not(:has(input[name="mode"][value="email"]:checked)) .portal-composer-files,
.portal-composer:not(:has(input[name="mode"][value="email"]:checked)) .portal-composer-full-editor { display: none; }
/* Send: black, an arrow after its word; in Note a plus, in the note's ink. */
.portal-composer-send {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: 2.25rem;
  padding: 0 0.75rem 0 0.875rem;
  font: 600 var(--portal-text-13)/1 var(--portal-ui);
  color: var(--portal-surface);
  white-space: nowrap;
  cursor: pointer;
  background: var(--composer-on);
  border: 0;
  border-radius: var(--portal-radius-pop);
}
.portal-composer-send::after {
  content: "";
  width: 0.875rem;
  height: 0.875rem;
  background: currentColor;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m13 6 6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.portal-composer-send:hover { background: var(--portal-ink-hover); }
.portal-composer-send:focus-visible { outline: 2px solid var(--portal-teal); outline-offset: 2px; }
.portal-composer-send:disabled { color: var(--portal-ghost); background: var(--portal-badge); cursor: default; }
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-send:hover { background: var(--portal-teal); }
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-send::after {
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M12 5v14'/%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
}
/* The small line under the words: always one line, where it goes from cut short if need be
   (its title says it whole). */
.portal-composer-foot { display: flex; align-items: center; gap: 0.75rem; min-height: 1.25rem; padding: 0 0.75rem 0.3125rem; }
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-foot { display: none; }
.portal-composer-hint { flex: 1 1 12rem; font-size: var(--portal-text-11); line-height: 1.4; color: var(--crm-quiet); }
.portal-composer-foot > .portal-composer-hint { display: flex; align-items: center; min-width: 0; white-space: nowrap; }
.portal-composer-from { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.portal-composer-counter { flex: none; margin-left: 0.25rem; padding: 0.0625rem 0.375rem; font-variant-numeric: tabular-nums; white-space: nowrap; background: var(--portal-head); border-radius: var(--portal-radius); }
.portal-composer-counter.is-over { font-weight: 600; color: var(--portal-amber); background: var(--portal-amber-wash); }
.portal-composer-file-names:not(:empty) { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; margin-right: 0.375rem; font-weight: 600; color: var(--crm-teal); }
/* Quick replies (slice 25): one button, opening a menu of them beside it. */
.portal-composer-quick-open {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  height: 1.25rem;
  margin-left: auto;
  padding: 0 0.375rem;
  font: 600 var(--portal-text-11) var(--portal-ui);
  color: var(--crm-teal);
  background: none;
  border: 0;
  border-radius: var(--portal-radius);
  cursor: pointer;
}
.portal-composer-quick-open::after {
  content: "";
  width: 0.75rem;
  height: 0.75rem;
  background: currentColor;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 15 6-6 6 6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.portal-composer-quick-open:hover { background: var(--portal-teal-wash); }
.portal-composer-quick-open:focus-visible { outline: 2px solid var(--portal-teal); outline-offset: 1px; }
.portal-composer-quick-open[hidden] { display: none; }
.portal-composer-quick-replies { max-width: min(24rem, calc(100vw - 2rem)); }
.portal-composer-quick-reply { padding-left: 0.625rem; }
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-quick-open { display: none; }
.portal-composer-banner,
.portal-composer-error { margin: 0; padding: 0.5rem 0.75rem; font-size: var(--portal-text-12); line-height: 1.45; }
.portal-composer-banner { flex: 1 1 auto; color: var(--portal-danger); background: var(--portal-danger-wash); border-radius: 0 0 var(--composer-corner) var(--composer-corner); }
.portal-composer-error { margin-top: 0.5rem; color: var(--portal-danger); background: var(--portal-danger-tint); border-radius: var(--portal-radius); }
/* In a card of fixed height the composer keeps its size and the stream gives way; every
   mode is one height (slice 31), so Email needs no rule of its own. */
.portal-conversation > .portal-stream-scroll { min-height: 8rem; }
.portal-conversation > .portal-composer { flex: none; }
.portal-composer [hidden] { display: none; }
.portal-composer:not(:has(input[name="mode"][value="text"]:checked)) .portal-composer-text-hint,
.portal-composer:not(:has(input[name="mode"][value="text"]:checked)) .portal-composer-banner,
.portal-composer:not(:has(input[name="mode"][value="note"]:checked)) .portal-composer-note-hint,
.portal-composer:not(:has(input[name="mode"][value="email"]:checked)) .portal-composer-email,
.portal-composer:not(:has(input[name="mode"][value="email"]:checked)) .portal-composer-email-hint,
.portal-composer:has(input[name="mode"][value="note"]:checked) .portal-composer-to { display: none; }
.portal-composer-dial { color: var(--portal-blue); }
.portal-composer-dial[hidden] { display: none; }
.portal-stream-missed > a { color: var(--portal-danger); border-color: color-mix(in srgb, var(--portal-danger) 35%, transparent); }

/* The Inbox (conversations slice 27): the rows on the left, the picked Lead's
   Conversation beside them. Each row its Lead, its time, the newest exchange's channel
   (the channel's colour) and first words; one Waiting on you is edged amber. On a wide
   screen the list and the Conversation each scroll on their own. */
.portal-inbox { display: grid; gap: 1.25rem; align-items: start; }
.portal-inbox:not(.has-open) { grid-template-columns: minmax(0, 48rem); }
.portal-inbox-list { display: flex; flex-direction: column; min-width: 0; }
.portal-inbox-list .portal-search { margin-bottom: 0.75rem; }
.portal-inbox-rep { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; font-size: var(--portal-text-13); }
.portal-inbox-rep select { min-width: 12rem; }
.portal-inbox-rep-name { font-size: var(--portal-text-11); white-space: nowrap; }
.portal-inbox-filters { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-bottom: 0.75rem; font-size: var(--portal-text-12); }
.portal-inbox-filter {
  display: inline-flex; align-items: center; height: 1.5rem; padding: 0 0.625rem;
  color: var(--crm-label); text-decoration: none; border: 1px solid var(--crm-line); border-radius: var(--portal-pill);
}
.portal-inbox-filter:hover { color: var(--portal-ink); border-color: var(--portal-ink); }
.portal-inbox-filter[aria-current] { font-weight: 600; color: var(--portal-surface); background: var(--portal-ink); border-color: var(--portal-ink); }
.portal-inbox-rows { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--crm-line); }
.portal-inbox-row { border-bottom: 1px solid var(--crm-line); }
.portal-inbox-row > a {
  display: grid; gap: 0.125rem; padding: 0.625rem 0.75rem; color: inherit; text-decoration: none;
  border-left: 3px solid transparent;
}
.portal-inbox-row > a:hover { background: var(--portal-hover-faint); }
.portal-inbox-row > a:focus-visible { outline: 2px solid var(--portal-ink); outline-offset: -2px; }
.portal-inbox-row.is-waiting > a { border-left-color: var(--portal-amber); }
.portal-inbox-row.is-picked > a { background: var(--portal-chosen); }
.portal-inbox-row-head { display: flex; align-items: baseline; gap: 0.5rem; }
.portal-inbox-name { font-weight: 600; overflow-wrap: anywhere; }
.portal-inbox-lost { font-size: var(--portal-text-11); }
.portal-inbox-time { margin-left: auto; font-size: var(--portal-text-11); color: var(--crm-quiet); white-space: nowrap; }
.portal-inbox-channel { font-size: var(--portal-text-12); font-weight: 600; }
.portal-inbox-channel.is-call { color: var(--portal-blue); }
.portal-inbox-channel.is-email { color: var(--portal-purple); }
.portal-inbox-channel.is-text { color: var(--crm-teal); }
.portal-inbox-words { font-size: var(--portal-text-13); color: var(--crm-label); overflow-wrap: anywhere; }
.portal-inbox-waiting { justify-self: start; margin-top: 0.25rem; }
.portal-inbox-pages { display: flex; align-items: center; gap: 1rem; padding: 0.75rem; font-size: var(--portal-text-13); }
.portal-inbox-picked { display: flex; flex-direction: column; min-width: 0; }
.portal-inbox-picked-name { margin: 0 0 0.5rem; font-weight: 600; }
@media (min-width: 64rem) {
  /* The list is as wide as its search box and Search button (slice 32): only the search
     sizes its column -- everything else in it takes no width of its own -- and the
     Conversation takes the rest. Narrower than that, the box gives way. */
  .portal-inbox.has-open { grid-template-columns: fit-content(50%) minmax(0, 1fr); }
  .portal-inbox.has-open .portal-inbox-list > :not(.portal-search, .portal-inbox-live),
  .portal-inbox.has-open .portal-inbox-live > *,
  .portal-inbox.has-open .portal-inbox-list .portal-search > :not(input, button) { contain: inline-size; }
  .portal-inbox.has-open .portal-inbox-list .portal-search > :not(input, button) { flex-basis: 100%; }
  .portal-inbox.has-open .portal-inbox-list > .portal-search > .portal-search-input { width: 28rem; }
  body.portal-inbox-page > .portal-main > .portal-inbox { flex: 1 1 auto; min-height: 0; align-items: stretch; }
  body.portal-inbox-page .portal-inbox-list,
  body.portal-inbox-page .portal-inbox-picked { min-height: 0; }
  body.portal-inbox-page .portal-inbox-rows { flex: 0 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
  body.portal-inbox-page .portal-inbox-picked .portal-conversation { position: relative; top: auto; flex: 1 1 auto; max-height: none; min-height: 0; margin-bottom: 0; }
}

/* The Unmatched in the Inbox (conversations slice 32): rows like the rest, at the top,
   washed amber, with a To match tag and a black Match; picked, one shows whole beside
   the list, the match box at its foot where the composer would be. */
.portal-inbox-row.is-to-match > a { position: relative; background: var(--portal-amber-faint); border-left-color: var(--portal-amber); }
.portal-inbox-row.is-to-match .portal-inbox-row-head { flex-wrap: wrap; row-gap: 0.125rem; }
.portal-inbox-row.is-to-match .portal-inbox-words { padding-right: 5rem; }
.portal-inbox-row.is-to-match > a:hover { background: var(--portal-amber-wash); }
.portal-inbox-row.is-to-match.is-picked > a { background: var(--portal-amber-wash); }
.portal-to-match-tag {
  padding: 0 0.4375rem; font-size: var(--portal-text-11); font-weight: 600; line-height: 1.125rem; white-space: nowrap;
  color: var(--portal-amber); background: var(--portal-amber-wash); border: 1px solid color-mix(in srgb, var(--portal-amber) 30%, transparent); border-radius: var(--portal-pill);
}
.portal-to-match-button {
  display: inline-flex; align-items: center; height: var(--portal-control-xs); padding: 0 0.875rem; font: inherit; font-size: var(--portal-text-12); font-weight: 600;
  color: var(--portal-surface); background: var(--portal-ink); border: 0; border-radius: var(--portal-pill); cursor: pointer; white-space: nowrap;
}
.portal-to-match-button:hover { background: var(--portal-ink-hover); }
.portal-to-match-button:focus-visible { outline: none; box-shadow: var(--portal-focus-ring); }
.portal-inbox-row > a > .portal-to-match-button { position: absolute; right: 0.75rem; bottom: 0.625rem; }
.portal-match { display: flex; flex-direction: column; min-height: 0; }
.portal-match-head { display: flex; align-items: center; gap: 0.5rem; }
.portal-match-title { margin: 0; font-size: var(--portal-text-14); font-weight: 600; overflow-wrap: anywhere; }
.portal-match-body { display: grid; align-content: start; gap: 0.75rem; flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1rem; font-size: var(--portal-text-13); }
.portal-match-message { padding: 0.75rem 0.875rem; background: var(--portal-bubble); border-radius: var(--portal-radius-chat); }
.portal-match-message p { margin: 0; }
.portal-match-message p + p, .portal-match-message details { margin-top: 0.375rem; }
.portal-match-subject { font-weight: 600; }
.portal-match-words { overflow-wrap: anywhere; color: var(--portal-body); }
.portal-match-others ol { margin: 0.25rem 0 0; padding-left: 1.25rem; }
.portal-match-box { display: grid; gap: 0.75rem; padding: 0.875rem 1rem 1rem; font-size: var(--portal-text-13); border-top: 1px solid var(--crm-line); background: var(--portal-amber-faint); }
.portal-match-label { display: block; margin-bottom: 0.375rem; font-weight: 600; color: var(--portal-ink); }
.portal-match-search-row { display: flex; gap: 0.5rem; }
.portal-match-search-row .portal-search-input { flex: 1 1 auto; }
.portal-match-search-row .portal-button { height: var(--portal-control-sm); padding: 0 1.25rem; }
.portal-match-leads { margin: 0 0 0.5rem; padding: 0; list-style: none; border-top: 1px solid var(--portal-rule); }
.portal-match-leads > li { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.5rem 0; border-bottom: 1px solid var(--portal-rule); overflow-wrap: anywhere; }
.portal-match-contact { display: flex; align-items: center; gap: 0.5rem; }
.portal-match-partner { padding: 0.625rem 0.75rem; background: var(--portal-surface); border: 1px solid var(--portal-rule); border-radius: var(--portal-radius); }
.portal-match-partner p { margin: 0 0 0.375rem; }
.portal-match-make > summary { font-weight: 600; color: var(--portal-ink); cursor: pointer; }
.portal-crm .portal-match-make .portal-form { max-width: none; margin: 0.5rem 0 0; padding: 0; border: 0; background: none; }
@media (min-width: 64rem) {
  body.portal-inbox-page .portal-inbox-picked .portal-match { flex: 1 1 auto; margin-bottom: 0; }
}

/* The Conversation's head: 📞 beside its title. */
.portal-conversation-actions { display: flex; align-items: center; gap: 0.25rem; }

/* A Lead's page on a phone (crm slice 53): it opens on its Conversation, full height,
   with tabs under its head -- Conversation, To-dos, Customer and Projects. Without script
   everything shows, the Conversation first; with it (`crm/js/record-tabs.js`) the columns
   carry the tab chosen and show its part alone. The Customer tab shows the Customer
   card's Overview, Contacts and Price list one after another, each under its own head;
   Projects, its Projects alone. */
.portal-record-tabs {
  display: flex;
  gap: 1.25rem;
  margin: 0 0 1rem;
  overflow-x: auto;
  scrollbar-width: thin;
  border-bottom: 1px solid var(--crm-edge);
}
.portal-record-tabs[hidden] { display: none; }
.portal-record-tab {
  margin: 0;
  padding: 0.625rem 0 0.5rem;
  font: inherit;
  font-size: var(--portal-text-13);
  font-weight: 500;
  color: var(--portal-muted);
  white-space: nowrap;
  cursor: pointer;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
}
.portal-record-tab:hover { color: var(--portal-ink); }
.portal-record-tab[aria-selected="true"] { font-weight: 600; color: var(--portal-ink); border-bottom-color: var(--portal-ink); }
.portal-record-tab .portal-group-count { margin-left: 0.25rem; }
@media (max-width: 64rem) {
  .portal-record-split > .portal-record-conversation { order: -1; }
  .portal-record-split[data-phone-tab] > div { display: none; }
  .portal-record-split[data-phone-tab="conversation"] > .portal-record-conversation,
  .portal-record-split[data-phone-tab="to-dos"] > .portal-record-cards,
  .portal-record-split[data-phone-tab="customer"] > .portal-record-cards,
  .portal-record-split[data-phone-tab="projects"] > .portal-record-cards { display: block; }
  .portal-record-split[data-phone-tab="conversation"] .portal-conversation { height: calc(100dvh - 1.5rem); margin-bottom: 0; scroll-margin-top: 0.75rem; }
  .portal-record-split[data-phone-tab="conversation"] .portal-conversation > .portal-stream-scroll { max-height: none; }
  .portal-record-split[data-phone-tab="to-dos"] #customer,
  .portal-record-split[data-phone-tab="customer"] #to-dos,
  .portal-record-split[data-phone-tab="projects"] #to-dos { display: none; }
  .portal-record-split[data-phone-tab] .portal-customer-tabs { display: none; }
  .portal-record-split[data-phone-tab="customer"] .portal-customer-panel { display: block; }
  .portal-record-split[data-phone-tab="customer"] .portal-customer-panel[data-tab="projects"],
  .portal-record-split[data-phone-tab="projects"] .portal-customer-panel { display: none; }
  .portal-record-split[data-phone-tab="projects"] .portal-customer-panel[data-tab="projects"] { display: block; }
  .portal-record-split[data-phone-tab="projects"] .portal-customer-card > .portal-crm-card-head { display: none; }
  .portal-record-split[data-phone-tab="customer"] .portal-customer-card.is-tabbed .portal-customer-panel > .portal-crm-card:first-child { border-top: 1px solid var(--crm-edge); }
  .portal-record-split[data-phone-tab="customer"] .portal-customer-card.is-tabbed .portal-customer-panel > .portal-crm-card > .portal-crm-card-head { display: flex; justify-content: space-between; }
  .portal-record-split[data-phone-tab="customer"] .portal-customer-card.is-tabbed .portal-customer-panel > .portal-crm-card > .portal-crm-card-head > h2 {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    white-space: normal;
  }
  .portal-record-split[data-phone-tab="customer"] .portal-customer-card.is-tabbed .portal-crm-card-head [data-tab-only="overview"] { visibility: visible; }
}

/* A Lead's head on a phone (crm slice 53): short, so the Conversation's tabs come early. The
   name keeps its Stage tag beside it, the actions sit on the same row where they fit (else
   the next, at the right), facts beside the title take a row of their own, and the Stage bar
   stays one row, each Stage's name small and cut short rather than wrapped. */
@media (max-width: 64rem) {
  body.portal-record-page .portal-crm-head { margin-bottom: 0.75rem; }
  body.portal-record-page .portal-crm-head .portal-page-head {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-bottom: 0.75rem;
  }
  /* The title runs as one line of text -- Back, the name, its Stage tag -- wrapping as words
     do, so the tag stays after the name's last word. */
  body.portal-record-page .portal-crm-title { display: block; flex: 1 1 12rem; min-width: 0; }
  body.portal-record-page .portal-crm-title > * { vertical-align: middle; }
  body.portal-record-page .portal-crm-back { margin-right: 0.375rem; }
  body.portal-record-page .portal-crm-title h1 {
    display: inline;
    font-size: var(--portal-text-22);
    line-height: 1.3;
    overflow-wrap: anywhere;
  }
  body.portal-record-page .portal-crm-title .portal-stage-tag { margin-left: 0.5rem; white-space: nowrap; }
  body.portal-record-page .portal-crm-title .portal-crm-aside { display: block; margin-top: 0.25rem; white-space: normal; font-size: var(--portal-text-12); }
  body.portal-record-page .portal-page-head-actions { margin-left: auto; gap: 0.5rem; }
  body.portal-record-page .portal-page-head .portal-lead-menu .portal-menu-panel { left: auto; right: 0; }
  body.portal-record-page .portal-stage-bar {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    max-width: none;
    margin-bottom: 0.75rem;
  }
  body.portal-record-page .portal-stage-step {
    font-size: var(--portal-text-11);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  body.portal-record-page .portal-stage-step::before { height: 4px; margin-bottom: 0.25rem; }
  body.portal-record-page .portal-stage-back { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
}

/* The Inbox on a phone (slice 30): only its list; with no script a picked Lead's
   Conversation takes the screen instead, with Back to the list. */
.portal-inbox-back { display: none; margin-bottom: 0.5rem; font-size: var(--portal-text-13); }
@media (max-width: 64rem) {
  .portal-inbox.has-picked > .portal-inbox-list { display: none; }
  /* The Lead the Inbox opened by itself waits for its row to be tapped (slice 32). */
  .portal-inbox.is-auto-picked > .portal-inbox-picked { display: none; }
  .portal-inbox.has-picked .portal-inbox-back { display: inline-block; }
  .portal-inbox.has-picked .portal-inbox-picked .portal-conversation { height: calc(100dvh - 1.5rem); }
  .portal-inbox.has-picked .portal-inbox-picked .portal-stream-scroll { max-height: none; }
}
