/* Link State — staff dashboard only. */
:root {
  --accent: #1a7f8e;
  --accent-dark: #146370;
  --accent-tint: #e3f2f4;
  --green: #2f9e63;
  --red: #c0392b;
  --amber: #f5c451;
  --ink: #1c2226;
  --grey: #6b7680;
  --grey-light: #dfe4e8;
  --bg: #f4f6f8;
  --white: #ffffff;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans Thai", "Sarabun", sans-serif;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2 { line-height: 1.35; margin: 0 0 12px; }
a { color: var(--accent); }
input, textarea, select { font-family: inherit; }
.wrap { max-width: 560px; margin: 0 auto; padding: 24px 16px 48px; }
/* WO-016 C4: 1040px was drawn when the customer table had SEVEN columns. It has
   nine since WO-015 split the phone, the passport number and the country apart,
   and the two extra columns are what pushed the customer link — and half the
   Copy button with it — out past the right edge of the card.
   1240px is the width at which all nine fit inside the card at 1280px, the
   narrowest screen this is used on, with the page itself still not scrolling
   sideways. It is a container width, not a table redesign: no column moved and
   none was dropped. */
.wrap--wide { max-width: 1240px; }
.card {
  background: var(--white);
  border-radius: 14px;
  box-shadow: 0 1px 3px rgba(20,30,40,.08), 0 6px 18px rgba(20,30,40,.06);
  padding: 20px;
  margin-bottom: 16px;
}
.btn, .btn--ghost, .btn--danger {
  display: inline-block;
  border-radius: 8px;
  padding: 9px 14px;
  font-size: inherit;
  text-decoration: none;
  cursor: pointer;
}
.btn { background: var(--accent); color: var(--white); border: none; }
.btn:hover { background: var(--accent-dark); }
.btn--ghost { background: transparent; color: var(--ink); border: 1px solid var(--grey-light); }
.btn--ghost:hover { background: var(--bg); }
.btn--danger { background: var(--white); color: var(--red); border: 1px solid var(--red); }
.btn--danger:hover { background: var(--red); color: var(--white); }
.btn:focus-visible, .btn--ghost:focus-visible, .btn--danger:focus-visible {
  outline: 2px solid var(--accent-dark);
  outline-offset: 2px;
}
.muted { font-size: .85rem; color: var(--grey); }
.progress {
  width: 100%; height: 10px; border-radius: 999px;
  background: var(--grey-light); overflow: hidden; margin: 14px 0;
}
.progress-bar { background: var(--accent); height: 100%; border-radius: 999px; transition: width .3s ease; }
.admin-head { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.field { margin-bottom: 10px; }
.field label { display: block; font-size: .85rem; font-weight: 700; margin-bottom: 4px; }
/* WO-016: `select` joined `input` and `textarea` here. A select with no width
   is as wide as its longest OPTION, and C1 made the service options long — the
   add-customer picker grew to 378px, burst out of its grid column and gave the
   whole page a horizontal scrollbar at 1280px. Constrained to its column it
   truncates the visible label, which costs nothing: the open dropdown still
   shows every option in full, and the company now comes FIRST in the label, so
   the half that survives truncation is the half that tells the two same-named
   services apart. */
.field input, .field textarea, .field select {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--grey-light);
  border-radius: 8px;
  font: inherit;
  box-sizing: border-box;
}
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.table-scroll { overflow-x: auto; }
table.customers { width: 100%; border-collapse: collapse; font-size: .93rem; }
table.customers th {
  text-align: left;
  font-size: .78rem;
  color: var(--grey);
  text-transform: uppercase;
  letter-spacing: .03em;
  border-bottom: 2px solid var(--grey-light);
  padding: 8px;
}
table.customers td { padding: 10px 8px; border-bottom: 1px solid var(--grey-light); vertical-align: top; }
.row-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.stage-form { display: inline-flex; gap: 6px; align-items: center; }
.stage-form select { padding: 6px; border-radius: 6px; border: 1px solid var(--grey-light); font: inherit; }
.linkbox { display: flex; gap: 6px; }
/* WO-016 C4: the customer-link column, given a width of its own.
   It was the widest column on the page (292px) and it was the widest for a bad
   reason: a flex item's min-width defaults to `auto`, so the link input refused
   to shrink below the intrinsic size of a text input — about 178px of URL — and
   the column carried that minimum into the table's own minimum. The whole
   table then could not fit the card, and the Copy button, last thing in the
   last column, was the half that fell off.
   `min-width: 0` lets the input shrink, so the long URL truncates INSIDE the
   cell — the WO's stated preference, and harmless here: the field selects its
   whole value on click and the Copy button beside it copies the whole link,
   neither of which cares how much of it is on screen. The 240px `width` is a
   preference, not a cap: in an auto-layout table it is what the column is given
   when there is room, and the column may still shrink toward its minimum on a
   narrow screen rather than pushing the table sideways. */
.link-col { width: 240px; }
.link-input {
  flex: 1;
  /* Both of these, and neither is decoration. A text input carries an intrinsic
     width of about 178px (twenty characters), and that intrinsic width is what
     the table asked the column for. `min-width: 0` undoes the automatic minimum
     every flex item gets; `width: 0` is what actually removes the 178px from
     the column's minimum, measured in the engine — with min-width alone the
     column stayed at 292px and the Copy button stayed half off the card.
     The input does not render at 0: `flex: 1` gives it everything left over in
     the cell, which is about 121px at both 1280px and 1440px. */
  min-width: 0;
  width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .8rem;
  padding: 6px;
  border: 1px solid var(--grey-light);
  border-radius: 6px;
  background: var(--bg);
}
.btn--copy { white-space: nowrap; flex: 0 0 auto; min-width: 92px; }
.btn.copy-ok { background: var(--green); border-color: var(--green); color: var(--white); }
.warn { background: #fdf6e0; border-left: 4px solid var(--amber); padding: 12px; border-radius: 8px; color: var(--ink); }
.c-name { font-weight: 700; }
.by { font-size: .78rem; color: var(--grey); }
.mini { min-width: 132px; }
.mini-badge {
  display: inline-block; background: var(--accent-tint); color: var(--accent-dark);
  font-weight: 700; font-size: .8rem; padding: 2px 8px; border-radius: 6px; margin-bottom: 6px;
}
.progress--mini { height: 6px; margin: 0 0 4px; }
/* WO-014: the search box sits directly above the service chips, because the
   two are one control between them — the chips say which service, the box says
   which customer, and they narrow together. */
.searchbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 10px; }
.search-input {
  flex: 1 1 260px; max-width: 420px;
  padding: 9px 12px; border: 1px solid var(--grey-light); border-radius: 8px;
  font: inherit; background: var(--white); color: var(--ink);
}
.search-input:focus-visible { outline: 2px solid var(--accent-dark); outline-offset: 1px; }
.filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.chip {
  display: inline-block; padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--grey-light); background: var(--white);
  color: var(--ink); text-decoration: none; font-size: .85rem;
}
.chip:hover { background: var(--bg); }
.chip--on { background: var(--accent); border-color: var(--accent); color: var(--white); font-weight: 700; }
/* WO-016 C1: how many customers are on that service. It sits at the END of the
   chip and is set apart, because the chip's label now ends in the father's own
   type number in brackets — `... (9, CHANGE VISA IN CHIANG MAI)` — and a second
   bracketed number straight after it would read as part of the same thing. It
   is ordinary text inside the link, so it is still read out and still searched
   for on the page; only its box is different. */
.chip-count {
  display: inline-block;
  margin-left: 8px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--grey-light);
  color: var(--grey);
  font-size: .78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.chip--on .chip-count { background: rgba(255, 255, 255, .2); border-color: rgba(255, 255, 255, .45); color: var(--white); }
.chip:focus-visible { outline: 2px solid var(--accent-dark); outline-offset: 2px; }
.note-input {
  padding: 6px 8px; border: 1px solid var(--grey-light); border-radius: 6px;
  font: inherit; font-size: .85rem; min-width: 120px;
}
.stage-form { flex-wrap: wrap; }
.hist { margin-top: 8px; }
.hist summary {
  cursor: pointer; font-size: .82rem; color: var(--accent-dark);
  font-weight: 700; padding: 2px 0;
}
.hist summary:focus-visible { outline: 2px solid var(--accent-dark); outline-offset: 2px; }
.hist-list {
  list-style: none; margin: 8px 0 0; padding: 8px 0 0;
  border-top: 1px solid var(--grey-light); font-size: .8rem; color: var(--grey);
}
.hist-list li { padding: 3px 0; }
.hist-at { font-variant-numeric: tabular-nums; }
.hist-by { color: var(--ink); font-weight: 700; }
.hist-list strong { color: var(--ink); }
.arrow { color: var(--grey); }
.hist-note { display: block; padding-left: 2px; font-style: italic; }
.warn--err { background: #fdecea; border-left-color: var(--red); }
/* Two-level stage control */
.stage-form select { max-width: 260px; }
.stage-form optgroup { font-style: normal; }
/* ADR-004: CANCEL / RENEW 1 YEAR STAMP are terminal STATES, never a percent
   bar — a status pill instead, styled so it reads as an outcome, not a step.
   CANCEL and RENEW look different from each other on purpose: one is bad,
   one is good. */
.status-pill {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .01em;
}
.status-pill--bad { background: #fdecea; color: var(--red); border: 1px solid var(--red); }
.status-pill--good { background: #e8f6ee; color: var(--green); border: 1px solid var(--green); }
.hist-legacy { font-style: italic; color: var(--grey); }
/* A record pointing at a service id that no longer exists in config — a loud
   row, not a crash. */
.row--unknown { background: #fdecea; }
.svc-unknown { color: var(--red); font-weight: 700; }
/* WO-011 — the step date on the stage form, and the panel that sets or
   corrects one without moving the customer. Same shape as the existing
   .hist <details> so the row gains a second fold, not a second look. */
.date-input {
  padding: 6px 8px; border: 1px solid var(--grey-light); border-radius: 6px;
  font: inherit; font-size: .85rem;
}
.dates { margin-top: 8px; }
.dates summary {
  cursor: pointer; font-size: .82rem; color: var(--accent-dark);
  font-weight: 700; padding: 2px 0;
}
.dates summary:focus-visible { outline: 2px solid var(--accent-dark); outline-offset: 2px; }
.date-list {
  list-style: none; margin: 8px 0 0; padding: 8px 0 0;
  border-top: 1px solid var(--grey-light); font-size: .8rem; color: var(--grey);
}
.date-list li { padding: 3px 0; }
.date-step { color: var(--ink); }
.date-val { font-variant-numeric: tabular-nums; }
/* A date later than today is an appointment, not finished work. The WORD says
   so; the colour only agrees with it (never red — red is not a status here). */
.date-sched {
  display: inline-block; background: #fdf3d8; color: #8a6400;
  font-size: .7rem; font-weight: 700; padding: 1px 6px; border-radius: 999px;
}
.date-form {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px;
}
.date-form select {
  padding: 6px; border-radius: 6px; border: 1px solid var(--grey-light);
  font: inherit; max-width: 260px;
}
.hist-date { display: block; padding-left: 2px; color: var(--ink); }

/* WO-012: who is signed in, the way to the accounts screen, and the way out.
   Sits in the dashboard header beside the record count. Its two children are a
   link and a one-button form, so the form's default block layout has to be
   undone or the button drops onto its own line. */
.whobar { display: flex; align-items: center; gap: .6rem; margin-left: auto; flex-wrap: wrap; }
.whobar form { display: inline; margin: 0; }
