/* crm.css — the CRM's own layout only.
 *
 * RULES THIS FILE FOLLOWS, from STYLE-GUIDE.md section 0:
 *   1. Tokens only. Not one hex, radius, shadow or font-family that a var()
 *      already covers. Search this file for '#' and you will find nothing.
 *   2. golfer.css owns every component. This file adds LAYOUT for screens that
 *      do not exist on the consumer site: the Today list, the bucket board, the
 *      club drawer.
 *   3. Everything new is prefixed `crm-`, so it cannot collide with any of
 *      golfer.css's 1,490 lines.
 *
 * Components taken from golfer.css and NOT redefined here:
 *   .btn .btn-primary .btn-outline .btn-sm .btn-dark
 *   .seg  .panel .panel-head .panel-pad .side-card .lrow
 *   .state-chip (.ok .warn .off)  .tag  .chips .chip  .fchip
 *   .ffield  .switch .switch .knob  table.ptab  .table-scroll
 *   .stat .k .v  .fillbar  .no-results  .eyebrow  header.site .bar  .wrap
 *   .modal-overlay .modal  .cart-overlay .cart-panel  .toast
 */

/* ---------------------------------------------------------------- shell --- */
/* THE HEADER HEIGHT, which the sticky topbar has to sit exactly below.
 *
 * It used to be two hard-coded numbers copied out of golfer.css, 72 and 56. That
 * was wrong the moment the header gained a second row on a phone: the topbar
 * stuck at 56px while the header was 100px tall, so the topbar sat underneath it
 * and the filters were unreachable on the road. The values below are only a
 * first paint fallback. app.js measures the real header and writes the true
 * number here, so nothing has to be kept in step by hand. */
.crm-body { background: var(--alt); --crm-header-h: 72px; }

/* A small neutral label: rep name, product short code.
 * NOT `.tag`: in golfer.css a bare `.tag` does not exist, and `.ccard .tag` is
 * an absolutely positioned red badge. Using it here would have been wrong in
 * two ways at once. */
.crm-tag {
  display: inline-block; font-size: 11px; font-weight: 700;
  padding: 3px 7px; border-radius: 4px;
  border: 1px solid var(--line); color: var(--body-c); white-space: nowrap;
}
.crm-tag.is-prod { font-family: var(--font-display); font-weight: 800; font-size: 10px; }

/* THE STICKY HEADER.
 *
 * golfer.css line 61 makes `header.site` position:relative on desktop and only
 * sticky at <=920px. That is right for a marketing page and wrong for a CRM,
 * where the product lens and the tab row have to stay reachable while you scroll
 * a 200 row list. So the CRM sticks it, scoped to .crm-body so no consumer page
 * is affected. This is layout, which is the one thing STYLE-GUIDE rule 2 allows
 * a page to add.
 *
 * The heights below are golfer.css's own: `header.site .wrap` is 72px on
 * desktop and 56px at <=920 (line 626). If those change, these change.
 */
.crm-body header.site {
  position: sticky; top: 0; z-index: 40;
  /* No border here on purpose. Adding one made the header 73px against a topbar
   * stuck at 72px, so the two overlapped by a pixel. The topbar below carries
   * the dividing line for both. */
}

.crm-topbar {
  position: sticky; top: var(--crm-header-h); z-index: 30;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 24px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
/* An author `display:flex` beats the browser's own [hidden]{display:none}, so
 * without this the topbar stayed on screen on the change log even though app.js
 * had set hidden. The identical mistake as the sign-in card, made again, and
 * caught the same way: by looking at a screenshot rather than at the code. */
.crm-topbar[hidden] { display: none; }
.crm-topbar .ffield { margin: 0; }
.crm-topbar .ffield label { margin-bottom: 2px; }
.crm-topbar .ffield input,
.crm-topbar .ffield select { padding: 8px 10px; font-size: 13px; }
.crm-grow { flex: 1 1 auto; }

/* THE HEADER, James 21 Aug: logo top left, both toggles right aligned.
 *
 * Two zones rather than four items in a row. golfer.css's .wrap is already
 * justify-content:space-between, which does exactly this with two children, so
 * the override is only the gap.
 *
 * The wordmark block that used to sit here went with it: it said "Golfer CRM"
 * next to a logo that says Golfer, and repeated the product lens that the
 * active pill and every view heading already say. */
.crm-body header.site .wrap { gap: 18px; }
.crm-body header.site .seg { flex: 0 0 auto; }

/* The logo, plus the one word that says which Golfer thing this is. Baseline
 * aligned with the wordmark rather than centred, because the logo's own
 * artwork sits low in its box. */
.crm-logo { display: inline-flex; align-items: center; gap: 9px; flex: 0 0 auto; }
.crm-logo-sub {
  font-family: var(--font-display); font-weight: 800; font-size: 13px;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
  padding-left: 9px; border-left: 1px solid var(--line);
}

/* The two segmented controls, as one unit. On desktop this behaves exactly as
 * they did when they were siblings. Its reason for existing is the phone: see
 * the 920 block at the bottom of this section. */
.crm-hsegs { display: flex; align-items: center; gap: 18px; min-width: 0; }

.crm-main { max-width: var(--wrap); margin: 0 auto; padding: 22px 24px 56px; }
.crm-view { display: none; }
.crm-view.is-on { display: block; }

.crm-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; margin-bottom: 18px; }
.crm-head h1 { font-size: 26px; margin: 0; }
.crm-sub { color: var(--muted); font-size: 13px; line-height: 1.5; max-width: 74ch; margin-top: 4px; }

/* -------------------------------------------------- the import age bar ---
 * SPEC 9. The cheapest thing in the document and the easiest to leave out.
 * `is-stale` is what stops "nothing sold in the last 7 days" quietly lying.  */
.crm-agebar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 18px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--bg); font-size: 13px; color: var(--body-c);
}
.crm-agebar.is-stale {
  border-color: var(--brand); background: var(--brand-tint); color: var(--ink);
}
.crm-agebar.is-stale b { color: var(--brand); }

/* ---------------------------------------------------------- the 5 cards --- */
.crm-cards {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px;
  margin-bottom: 22px;
}
.crm-card {
  text-align: left; cursor: pointer; font-family: inherit;
  padding: 14px 16px 16px;
  background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--shadow);
  transition: .2s;
}
.crm-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-hover); }
.crm-card .crm-card-k {
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted);
}
.crm-card .crm-card-v {
  font-family: var(--font-display); font-weight: 800; font-size: 26px;
  line-height: 1.1; margin: 6px 0 2px; color: var(--ink);
}
.crm-card .crm-card-t { font-size: 12px; color: var(--muted); line-height: 1.4; }
.crm-card .crm-card-also {
  display: block; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--line); font-size: 12px; color: var(--muted);
}
.crm-card .crm-card-also b { font-family: var(--font-display); color: var(--body-c); }
.crm-card.is-hot .crm-card-v { color: var(--brand); }
.crm-card.is-on { border-color: var(--ink); box-shadow: var(--shadow-hover); }
/* An information card is not work. No pointer, no hover lift, never red. */
.crm-card.is-info { cursor: default; background: var(--alt); }
.crm-card.is-info:hover { transform: none; box-shadow: var(--shadow); }

/* ------------------------------------------------------- the task list --- */
.crm-sec { margin-bottom: 22px; }
.crm-sec-h {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 8px 2px;
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .1em; color: var(--muted);
}
.crm-sec-h .crm-n {
  font-family: var(--font-display); font-weight: 700; letter-spacing: 0;
  color: var(--body-c);
}

.crm-task {
  display: grid; grid-template-columns: 84px minmax(0, 1fr) auto;
  gap: 14px; align-items: center;
  padding: 11px 14px;
  background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  margin-bottom: 6px; cursor: pointer;
  transition: .15s;
}
.crm-task:hover { border-color: var(--ink); }
.crm-task.is-late { border-left: 3px solid var(--brand); }
.crm-task.is-off { opacity: .45; }

.crm-when { text-align: right; }
.crm-when .crm-d {
  font-family: var(--font-display); font-weight: 700; font-size: 14px; color: var(--ink);
}
.crm-when .crm-r { font-size: 11px; color: var(--muted); }
.crm-task.is-late .crm-when .crm-r { color: var(--brand); font-weight: 700; }

.crm-tbody { min-width: 0; }
.crm-tbody b { display: block; font-size: 14px; }
.crm-tbody small { display: block; color: var(--body-c); font-size: 12.5px; line-height: 1.45; }
.crm-tbody .crm-why { color: var(--muted); }

.crm-end { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

/* ------------------------------------------------------------ the ignore ---
 * SPEC 7. The quietest control on the row, because it is the one that hides
 * work: grey, no border until hovered, and it never competes with the overdue
 * date or the money. Red is reserved (STYLE-GUIDE rule 4) and an ignore is not
 * an emergency.                                                             */
.crm-ign {
  font-size: 11px; font-weight: 700; color: var(--muted);
  padding: 3px 8px; border-radius: 4px;
  border: 1px solid transparent; background: none;
  transition: .15s;
}
.crm-task:hover .crm-ign { border-color: var(--line); }
.crm-ign:hover, .crm-ign.is-on { color: var(--ink); border-color: var(--ink); }

.crm-ignbox {
  grid-column: 1 / -1;
  margin-top: 10px; padding-top: 11px;
  border-top: 1px solid var(--line);
  cursor: default;
}
.crm-ignrow { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.crm-ignrow .ffield { margin: 0; }
.crm-ignrow .ffield input,
.crm-ignrow .ffield select { padding: 8px 10px; font-size: 13px; }
.crm-ignbox .crm-sub { margin-top: 7px; }
.crm-ignerr {
  margin-top: 7px; font-size: 12.5px; font-weight: 600; color: var(--brand);
}
/* A row on its way out. Not removed by hand: the cards count the same rows, so
 * the whole list reloads. This is just the half second in between. */
.crm-task.is-going { opacity: .4; }

/* The hidden list. A count and a disclosure, not a filter: hidden rows are not
 * part of today's work, they are a thing to check on occasionally. */
.crm-hidden {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: -4px 0 14px;
}
.crm-hidden .crm-hidopen { font-size: 13px; }
.crm-hidlist {
  margin: -6px 0 18px;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
  overflow: hidden;
}
/* Three ignores of the same check is not an ignore any more, so the count stops
 * being grey. The only red on this table. */
.crm-hidlist .crm-warnc { color: var(--brand); font-weight: 700; }

/* -------------------------------------------------------- the change log ---
 * Its own filter row rather than the shared topbar: the rep lens and the
 * product lens do not narrow a change log, and a control that looks like it
 * filters and does not is worse than no control.                            */
.crm-logbar {
  display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap;
  margin-bottom: 16px;
}
.crm-logbar .ffield { margin: 0; }
.crm-logbar .ffield input,
.crm-logbar .ffield select { padding: 8px 10px; font-size: 13px; }

/* A date heading inside the table, so a run of edits reads as an afternoon's
 * work rather than 40 identical timestamps. */
.crm-logday td {
  background: var(--alt);
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted);
  padding-top: 9px; padding-bottom: 7px;
}
.crm-logt { font-family: var(--font-display); font-weight: 700; color: var(--muted); }
/* The one column allowed to wrap. Everything else in table.ptab is nowrap, and
 * a sentence is not a value. */
.crm-logs { white-space: normal; line-height: 1.45; }
.crm-logmore { margin-top: 12px; font-size: 13px; color: var(--muted); }
/* A note is the rep's own words. Quoted, so it cannot be mistaken for the
 * database describing a field change. */
.crm-lognote { color: var(--muted); }
.crm-logs q { font-style: normal; }
.crm-logs q:before { content: '\201C'; }
.crm-logs q:after  { content: '\201D'; }
.crm-logerr { color: var(--brand); font-weight: 600; white-space: normal; }

/* --------------------------------------------------- the admin dashboard ---
 * Three panels behind one tab. The calendar is a real month grid rather than a
 * heat strip, because James asked for a calendar and because "the 14th was
 * quiet" is easier to see in the shape of a month.                          */
.crm-apane { display: none; }
.crm-apane.is-on { display: block; }

.crm-calhead {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px;
}
.crm-calhead b { font-family: var(--font-display); font-size: 17px; }

.crm-cal {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px;
}
.crm-cal-h {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted); padding: 0 0 2px 2px;
}
.crm-cal-c {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  min-height: 84px; padding: 8px 9px; text-align: left; font-family: inherit;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
  cursor: pointer; transition: .15s;
}
.crm-cal-c:hover { border-color: var(--ink); }
.crm-cal-c.is-pad { background: none; border: none; cursor: default; min-height: 0; }
/* A quiet day is not an error and not missing data. Flat, not red. */
.crm-cal-c.is-quiet { background: var(--alt); }
.crm-cal-c.is-weekend .crm-cal-d { color: var(--muted); }
.crm-cal-c.is-on { border-color: var(--ink); box-shadow: var(--shadow-hover); }
.crm-cal-c[data-today="1"] .crm-cal-d { text-decoration: underline; text-underline-offset: 3px; }
.crm-cal-d { font-family: var(--font-display); font-weight: 800; font-size: 13px; color: var(--ink); }
.crm-cal-t { font-size: 11px; color: var(--body-c); font-weight: 700; }
.crm-cal-n { font-size: 12px; color: var(--ink); }
.crm-cal-n b { font-family: var(--font-display); }
.crm-cal-s { font-size: 11px; color: var(--muted); }
.crm-cal-z { font-size: 12px; color: var(--muted); }

/* People. A departed row is dimmed rather than hidden: their name still appears
 * on old notes and pretending they never existed is how an author goes blank. */
#utab tr.is-off { opacity: .55; }
.crm-pwform { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.crm-pwform .ffield { margin: 0; }
.crm-pwform input { padding: 8px 10px; font-size: 13px; font-family: var(--font-display); }
.crm-pwrow td { background: var(--alt); white-space: normal; }
.crm-pwmsg { margin-top: 8px; font-size: 12.5px; font-weight: 600; }
.crm-pwmsg.is-bad  { color: var(--brand); }
.crm-pwmsg.is-good { color: var(--green); }

/* ------------------------------------------------------ in person notes ---
 * James, 21 Aug. A note can be marked as an in-person meeting, and the club
 * record shows how long it has been. No red and no threshold: there is no
 * agreed interval for it to be over.                                        */
.crm-visitbox {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 600; color: var(--body-c);
  cursor: pointer; white-space: nowrap;
}
.crm-visitbox input { accent-color: var(--ink); }
/* A visited note keeps the timeline's shape and gains a left edge, so it is
 * findable by eye when scrolling a long thread without shouting. */
.crm-msg.is-visit { border-left: 2px solid var(--ink); padding-left: 10px; }
.crm-msg.is-visit .crm-tag { margin-left: 6px; }
.crm-sortseen { font: inherit; color: inherit; }

/* golfer.css sets .toast pointer-events:none, since its own toasts hold no
 * controls. This one holds Undo. */
.crm-toast {
  pointer-events: auto;
  display: inline-flex; align-items: center; gap: 12px;
}
/* golfer.css tints `.toast a` pink, but this is a button rather than a link and
 * copying the literal would be the first hex value in this file. Underlined and
 * inheriting the toast's own white reads as a control without inventing a
 * colour that is not in the system. */
.crm-toast .lnk {
  color: inherit; font-weight: 800; text-decoration: underline;
  text-underline-offset: 2px;
}

/* -------------------------------------------------------------- pips ---
 * Every club shows its state on all three lines, always, even while you are
 * working one. SPEC 7: the whole picture stays visible.                    */
.crm-pips { display: inline-flex; gap: 3px; }
.crm-pip {
  font-family: var(--font-display); font-size: 9.5px; font-weight: 800;
  letter-spacing: .04em;
  padding: 3px 5px; border-radius: 4px;
  border: 1px solid var(--line); background: var(--alt); color: var(--muted);
  cursor: help;
}
.crm-pip.s-client { background: var(--green); border-color: var(--green); color: var(--bg); }
.crm-pip.s-talks  { background: var(--ink);   border-color: var(--ink);   color: var(--bg); }
.crm-pip.s-parked { background: var(--brand-tint); border-color: var(--brand); color: var(--brand); }
.crm-pip.is-now   { outline: 2px solid var(--ink); outline-offset: 1px; }

/* A gap in the contact details. Per James: never blocked, always highlighted.
 * The dot carries the red so the words do not have to. Twenty-six of these in a
 * column, all in red text, would make red mean nothing (STYLE-GUIDE rule 4). */
.crm-gap {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 700; color: var(--muted); white-space: nowrap;
}
.crm-gap i { color: var(--brand); font-style: normal; font-size: 15px; line-height: 1; }

/* ------------------------------------------------------------- footer --- */
.crm-foot {
  margin-top: 34px; padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 12px; color: var(--muted); line-height: 1.6;
}
.crm-foot b { color: var(--body-c); }

/* ------------------------------------------------------ dev-only badge --- */
.crm-devbadge {
  position: fixed; bottom: 10px; right: 10px; z-index: 120;
  padding: 6px 10px; border-radius: 999px;
  background: var(--ink); color: var(--bg);
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
}

/* ------------------------------------------------------------ 920 / 600 ---
 * Two breakpoints, not a spectrum. STYLE-GUIDE rule 5.                     */
@media (max-width: 920px) {
  /* Fallback only, until app.js measures the two-row header. */
  .crm-body { --crm-header-h: 96px; }

  /* THE 819px BUG. golfer.css gives `.wrap` display:flex, no flex-wrap, and a
   * fixed 56px height at this width. Four children (mark, product lens, tab
   * row, logo) came to 819px, so at 390 and at 768 the entire page scrolled
   * sideways: every card, every board column and the drawer were cut off, and
   * a rep on a phone could not read a club. Fixed at the source rather than by
   * shrinking the things inside it:
   *   row one   the logo
   *   row two   both segmented controls, scrolling sideways as a pair
   * The segs keep their real size, so no label is ever squeezed to two lines. */
  .crm-body header.site .wrap {
    flex-wrap: wrap; height: auto; row-gap: 0; padding-bottom: 7px;
  }
  .crm-body header.site .wrap .crm-logo { min-height: 56px; }
  .crm-body header.site .crm-hsegs {
    order: 3; flex: 1 0 100%; min-width: 0;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    /* A scrollbar gutter inside a 34px strip is noise, and this scrolls by
     * touch. Kept keyboard reachable: the buttons still tab. */
    scrollbar-width: none;
  }
  .crm-body header.site .crm-hsegs::-webkit-scrollbar { display: none; }

  /* The filter bar stops sticking below 920. On a phone the header is two rows
   * and the filters wrap to three, so the two of them stuck together held 343px
   * of an 844px screen: two fifths of the phone was chrome before a single club
   * appeared. The header stays (the lens and the tab row have to be reachable
   * while scrolling a long list); the filters scroll away, which is what filters
   * do everywhere else on a phone. */
  .crm-body .crm-topbar { position: static; top: auto; }
  .crm-topbar { padding: 10px 16px; }
  .crm-main { padding: 18px 16px 48px; }
  .crm-cards { grid-template-columns: repeat(2, 1fr); }
  .crm-task { grid-template-columns: 68px minmax(0, 1fr); }
  .crm-end { grid-column: 1 / -1; justify-content: flex-start; }
}
@media (max-width: 600px) {
  .crm-body { --crm-header-h: 136px; }  /* fallback; app.js measures the real one */

  /* At 390 the two segs come to 599px against 358px of usable width, so on one
   * scrolling row the tab switcher sat entirely off screen: a rep could see the
   * product lens and had no way of knowing Buckets and Clients existed without
   * dragging sideways. A control you have to discover by accident is not a
   * control. One row each instead, both fully visible, no horizontal scroll. */
  .crm-body header.site .crm-hsegs { flex-wrap: wrap; row-gap: 7px; }
  /* Each pill keeps its natural width and hugs its own buttons, rather than
   * being stretched to the full row with dead space on the right. overflow-x
   * stays auto from the 920 block, so on a 320px phone where the four product
   * buttons are wider than the row, that one pill scrolls instead of the page. */
  .crm-body header.site .crm-hsegs > .seg { flex: 0 0 auto; }

  .crm-cards { grid-template-columns: 1fr; }
  .crm-head { flex-direction: column; align-items: flex-start; }
  .crm-head h1 { font-size: 22px; }
}

/* ------------------------------------------------------------- sign in ---
 * The whole of auth on the client. The checking is login(), a Postgres
 * function; this is a form and a red error line.                          */
.crm-signin {
  position: fixed; inset: 0; z-index: 130;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; background: var(--alt);
}
/* An author `display:flex` beats the browser's own [hidden]{display:none}, so
 * without this line the sign-in card stays on screen over the app forever after
 * a successful sign-in. Caught in a real browser, not by reading the code. */
.crm-signin[hidden] { display: none; }
.crm-signin-card {
  width: 100%; max-width: 360px;
  display: flex; flex-direction: column; gap: 14px;
  padding: 28px;
  background: var(--bg);
  border: 1px solid var(--line); border-radius: 16px;
  box-shadow: var(--shadow-hover);
}
.crm-signin-mark {
  font-family: var(--font-display); font-weight: 800; font-size: 20px;
  letter-spacing: -.02em;
}
.crm-signin-card .crm-sub { margin: -12px 0 4px; }
.crm-signin-card .ffield input { width: 100%; }
.crm-signin-card .btn { justify-content: center; }
.crm-signin-err {
  font-size: 12.5px; font-weight: 700; color: var(--brand);
  padding: 9px 11px; border-radius: var(--r-sm);
  background: var(--brand-tint); border: 1px solid var(--brand);
}

/* who is signed in, and out again */
.crm-who {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--muted); white-space: nowrap;
}
.crm-who b { color: var(--ink); }
.crm-who .crm-role {
  font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; padding: 2px 6px; border-radius: 999px;
  background: var(--alt); color: var(--muted);
}

/* ------------------------------------------------- the club record drawer ---
 * Shell is golfer.css's .cart-overlay / .cart-panel. Only the width and the
 * inner layout are ours: a club record needs more room than a shopping cart. */
.crm-drawer-panel { width: 560px; }
.crm-dhead { min-width: 0; }
.crm-dhead h3 { font-size: 17px; line-height: 1.25; }
.crm-dhead .crm-sub { margin-top: 3px; font-size: 12px; }

.crm-drawer-panel .cart-items { padding: 0 20px 24px; }
.crm-dsec {
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .1em; color: var(--muted);
  margin: 20px 0 8px;
}
.crm-drow {
  display: flex; gap: 12px; align-items: baseline;
  padding: 9px 0; border-top: 1px solid var(--line); font-size: 13px;
}
.crm-drow .crm-dk { flex: 0 0 116px; color: var(--muted); font-size: 11.5px; }
.crm-drow .crm-dv { flex: 1 1 auto; min-width: 0; }
.crm-miss { color: var(--brand); font-weight: 700; }

/* one block per product line */
.crm-pblock {
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 11px 13px; margin-bottom: 8px; background: var(--bg);
}
.crm-pblock.is-now { border-color: var(--ink); }
.crm-pblock .crm-ph {
  display: flex; align-items: center; gap: 8px; justify-content: space-between;
}
.crm-pblock .crm-ph b { font-size: 13.5px; }
/* the state chip as a control. Same shape as the label it replaces, so the block
 * does not jump when it becomes clickable. */
button.crm-statebtn {
  font-family: inherit; cursor: pointer;
  border: 1px solid transparent; transition: .12s;
}
button.crm-statebtn i { font-style: normal; opacity: .6; margin-left: 1px; }
button.crm-statebtn:hover { border-color: currentColor; }

/* the picker, in place under the chip */
.crm-spick {
  margin-top: 9px; padding: 10px 11px;
  border: 1px solid var(--ink); border-radius: var(--r-sm); background: var(--bg);
}
.crm-spick .crm-dk {
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); margin-bottom: 5px;
}
.crm-spick .crm-ed + .crm-ed { margin-top: 6px; }
.crm-pblock .crm-pwhy { font-size: 12px; color: var(--body-c); margin-top: 4px; }
.crm-pblock .crm-pm {
  font-size: 12px; color: var(--muted); margin-top: 5px;
  font-family: var(--font-display); font-weight: 600;
}
.crm-deal {
  border-top: 1px solid var(--line); margin-top: 9px; padding-top: 8px;
  font-size: 12px;
}
.crm-deal .crm-dt { font-weight: 700; line-height: 1.35; }
.crm-deal .crm-dmeta {
  display: flex; gap: 12px; flex-wrap: wrap; color: var(--muted); margin-top: 3px;
}
.crm-deal .crm-dmeta b { font-family: var(--font-display); color: var(--body-c); }

/* qualification: an unconfirmed value is never shown as fact (SPEC 10.1) */
.crm-drawer-panel .chips { margin-bottom: 6px; }
.crm-drawer-panel .chip i { font-style: normal; color: var(--muted); font-weight: 600; }
.crm-drawer-panel .chip.is-unset { color: var(--muted); border-style: dashed; }
.crm-drawer-panel .chip.is-parsed { border-color: var(--star); }
.crm-drawer-panel .chip.is-parsed em {
  font-style: normal; font-weight: 800; color: var(--star); margin-left: 4px;
}

/* the note timeline */
.crm-thread { border-top: 1px solid var(--line); padding: 11px 0; }
.crm-thread .crm-th { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.crm-thread .crm-th b { font-size: 12.5px; }
.crm-thread .crm-tid { font-size: 11px; color: var(--muted); }
.crm-pin {
  background: var(--alt); border-radius: var(--r-sm);
  padding: 8px 10px; margin: 7px 0; font-size: 12px; line-height: 1.5;
  white-space: pre-wrap;
}
.crm-msg { padding: 7px 0 7px 10px; border-left: 2px solid var(--line); margin-top: 7px; }
.crm-msg .crm-mh {
  display: flex; gap: 8px; font-size: 11px; color: var(--muted); margin-bottom: 2px;
}
.crm-msg .crm-mh b { color: var(--ink); }
.crm-msg .crm-mt { font-size: 12.5px; line-height: 1.5; white-space: pre-wrap; }

@media (max-width: 600px) {
  .crm-drawer-panel { width: 100%; }
  .crm-drow { flex-direction: column; gap: 2px; }
  .crm-drow .crm-dk { flex: none; }
}

/* ----------------------------------------------------------- editing ---
 * SPEC 8: every field editable, one at a time, and a conflict prompt rather
 * than a lock. The row shows the value until you ask to change it, so a record
 * still reads as a record and not as a form. */
.crm-editable .crm-dv {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.crm-editable .crm-shown { flex: 1 1 auto; min-width: 0; }
.crm-pencil {
  flex: 0 0 auto; opacity: 0;
  font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 3px 7px; background: var(--bg); transition: .12s;
}
.crm-editable:hover .crm-pencil,
.crm-editable:focus-within .crm-pencil { opacity: 1; }
.crm-pencil:hover { border-color: var(--ink); color: var(--ink); }
.crm-editable.is-editing { background: var(--alt); }

.crm-ed {
  width: 100%; font-family: inherit; font-size: 13.5px;
  padding: 8px 10px; border: 1px solid var(--ink); border-radius: var(--r-sm);
  background: var(--bg); color: var(--ink); outline: none;
}
.crm-ed:focus { box-shadow: 0 0 0 3px rgba(26, 26, 26, .12); }
textarea.crm-ed { resize: vertical; }

.crm-edbtns { display: flex; gap: 6px; align-items: center; margin-top: 7px; flex-wrap: wrap; }
.crm-edbtns select {
  font-family: inherit; font-size: 12.5px; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg);
}

/* The conflict prompt. Red because losing somebody else's edit is a money-grade
 * mistake, which is the one thing STYLE-GUIDE rule 4 keeps red for. */
.crm-ederr {
  margin-top: 7px; padding: 8px 10px; font-size: 12px; line-height: 1.45;
  border: 1px solid var(--brand); border-radius: var(--r-sm);
  background: var(--brand-tint); color: var(--ink);
}

/* a qualification chip being edited, in place */
.crm-qedit {
  flex: 1 1 100%; margin: 6px 0 2px;
  border: 1px solid var(--ink); border-radius: var(--r-sm);
  padding: 10px 12px; background: var(--bg);
}
.crm-qedit .crm-qhint { margin: -2px 0 7px; }
.crm-checks {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 220px; overflow-y: auto;
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: 6px 8px;
}
.crm-check {
  display: flex; align-items: center; gap: 7px;
  font-size: 12.5px; padding: 4px 2px; cursor: pointer; line-height: 1.3;
}
.crm-check input { accent-color: var(--brand); flex: 0 0 auto; margin: 0; }
.crm-checks + .crm-ed { margin-top: 7px; }
.crm-qedit .crm-dk {
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); margin-bottom: 5px;
}

/* the note composer. Append only, and it says so on the placeholder. */
.crm-composer {
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 11px 12px; margin-bottom: 12px; background: var(--bg);
}
.crm-composer textarea {
  width: 100%; font-family: inherit; font-size: 13px; line-height: 1.5;
  padding: 9px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
  resize: vertical; outline: none; color: var(--ink);
}
.crm-composer textarea:focus { border-color: var(--ink); }

/* the change log */
.crm-hrow {
  display: flex; gap: 12px; padding: 8px 0;
  border-top: 1px solid var(--line); font-size: 12.5px;
}
.crm-hwhen {
  flex: 0 0 96px; color: var(--muted); font-size: 11px;
  font-family: var(--font-display);
}
.crm-hbody { flex: 1 1 auto; min-width: 0; line-height: 1.45; }
.crm-hnote {
  margin-top: 4px; padding: 7px 9px; background: var(--alt);
  border-radius: var(--r-sm); white-space: pre-wrap; line-height: 1.5;
}

/* "you saved something, the list behind is older than that" */
.crm-stalebar {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
  z-index: 121; max-width: 92vw;
  background: var(--ink); color: var(--bg);
  font-size: 12.5px; font-weight: 600;
  padding: 11px 18px; border-radius: 999px;
  box-shadow: var(--shadow-hover);
}
.crm-stalebar .lnk {
  color: var(--bg); font-weight: 800; text-decoration: underline;
  font-family: inherit; font-size: 12.5px;
}

/* one-click accept of the cadence's suggestion */
.crm-accept {
  font-size: 11px; font-weight: 800; font-family: inherit;
  border: 1px solid var(--ink); border-radius: var(--r-sm);
  padding: 3px 8px; background: var(--bg); color: var(--ink);
}
.crm-accept:hover { background: var(--ink); color: var(--bg); }

/* ------------------------------------------------------------- buckets ---
 * Four columns, per SPEC 7. Each scrolls on its own so a 814-card column does
 * not push the other three off the screen. */
.crm-board {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px;
  align-items: start;
}
.crm-col {
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md);
  display: flex; flex-direction: column; min-width: 0;
  max-height: calc(100vh - 240px);
}
.crm-col.is-parked { background: var(--alt); }
.crm-col.is-over { border-color: var(--ink); box-shadow: var(--shadow-hover); }
.crm-col-h {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 11px 13px; border-bottom: 1px solid var(--line);
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); position: sticky; top: 0; background: inherit;
  border-radius: var(--r-md) var(--r-md) 0 0;
}
.crm-col-h .crm-n {
  font-family: var(--font-display); font-weight: 700; letter-spacing: 0;
  font-size: 13px; color: var(--ink);
}
.crm-col-body { overflow-y: auto; padding: 9px; display: flex; flex-direction: column; gap: 8px; }
.crm-col-empty {
  border: 1px dashed var(--line); border-radius: var(--r-sm);
  padding: 16px; text-align: center; font-size: 12px; color: var(--muted);
}
.crm-more {
  font-family: inherit; font-size: 12px; font-weight: 700;
  border: 1px dashed var(--line); border-radius: var(--r-sm);
  padding: 9px; background: var(--bg); color: var(--muted);
}
.crm-more:hover { border-color: var(--ink); color: var(--ink); }

/* a club card on the board */
.crm-card-club {
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--bg); padding: 9px 10px; cursor: pointer;
  transition: .15s;
}
.crm-card-club:hover { border-color: var(--ink); }
.crm-card-club.is-dragging { opacity: .4; }
.crm-card-club[draggable="true"] { cursor: grab; }
.crm-cc-nm { font-size: 13px; font-weight: 700; line-height: 1.3; }
.crm-cc-loc { font-size: 11px; color: var(--muted); margin-top: 2px; }
.crm-cc-row {
  display: flex; gap: 5px; align-items: center; flex-wrap: wrap; margin-top: 6px;
}
.crm-cc-why {
  font-size: 11.5px; color: var(--body-c); margin-top: 5px; line-height: 1.4;
}
.crm-cc-due { font-size: 11.5px; color: var(--body-c); margin-top: 7px; }
.crm-cc-due.is-late { color: var(--brand); }
.crm-cc-due b { font-family: var(--font-display); }

/* ------------------------------------------------------------- the modal ---
 * golfer.css owns .modal-overlay / .modal; this sizes it and moves it up the
 * z-index ladder.
 *
 * STYLE-GUIDE 4.5 puts .modal-overlay at 100 and .cart-overlay at 110, because
 * on the consumer site a slide-out cart opens over a modal. Here it is the other
 * way round: the club record IS the drawer, and the park dialog opens from
 * inside it, so at 100 it rendered behind the thing that launched it and the
 * Save button could not be clicked. Found by a click timing out in a real
 * browser, not by reading the CSS.
 *
 * 115 slots between the drawer (110) and the toast layer (120), per the ladder's
 * own instruction not to invent a 999. */
.crm-modal { z-index: 115; }
/* golfer.css's .modal is a flex column with overflow:hidden, meant for a
 * scrolling body. This dialog is six short rows, so block layout is simpler. */
.crm-modal-box { max-width: 420px; padding: 24px; display: block; overflow: visible; }
.crm-modal-box h3 { font-size: 17px; margin: 0 0 4px; }
.crm-modal-box .crm-sub { margin-bottom: 16px; }
.crm-modal-box .ffield { margin-bottom: 13px; }
.crm-modal-box .ffield input { width: 100%; }

/* ------------------------------------------------------------- 920 / 600 --- */
@media (max-width: 920px) {
  .crm-board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .crm-col { max-height: none; }
}
@media (max-width: 600px) {
  .crm-board { grid-template-columns: 1fr; }
}
