/* operate.css - the surfaces people use once they are IN.
 *
 * The operator console, and the family's and carer's own lists: queue tables,
 * state badges, record cards, the contact reveal and the message thread.
 *
 * A SECOND FILE, not an addition to neo.css. neo.css is the design system and
 * the page shell; this is the page-level CSS for one round of screens, and it
 * introduces no colour, radius or font of its own - every value below is one
 * of neo.css's tokens. Linked from <head> by app/templates/operate.html's
 * `styles()` macro rather than inlined in each page, because an inline <style>
 * is part of the response body, and several of this product's guards scan the
 * whole body for characters ("@") and words that a stylesheet legitimately
 * contains. Markup should be readable as markup.
 *
 * NOTHING here may render a price, a sales pitch or a charge: these classes dress
 * /bookings, /cover, /messages and /applications, which are work-seeker
 * surfaces (EAA 1973 s.6).
 */
/* ---- state badges ------------------------------------------------------
   Five meanings, never more: something is settled, waiting, over, stopped,
   or open to you. */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 800;
  border-radius: var(--r-pill);
  padding: 4px 11px;
  white-space: nowrap;
  border: 1.5px solid transparent;
}
/* A drawn dot, so a state is not carried by hue alone. */
.badge::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none;
}
.badge-ok   { background: var(--v-fill); color: var(--v-on); }
.badge-wait { background: var(--c-bg); color: var(--c); border-color: var(--c); }
.badge-open { background: var(--ask-bg); color: var(--ask); border-color: var(--ask); }
.badge-off  { background: transparent; color: var(--mut); border-color: var(--line); }
.badge-stop { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }

/* ---- the queue table ---------------------------------------------------
   The console's whole job is scanning, so the table is built for an eye
   travelling down a column: a ruled head, hairline rows, no vertical
   chrome, and dates that do not wrap. */
.table-wrap {
  overflow-x: auto;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
}
table.data { width: 100%; border-collapse: collapse; font-size: 14.5px; }
table.data th, table.data td { text-align: left; padding: 12px 14px; vertical-align: top; }
table.data td:first-child { min-width: 11rem; }
table.data thead th {
  font-size: 11.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--mut);
  white-space: nowrap;
  border-bottom: 1.5px solid var(--line);
  background: var(--bg);
}
table.data tbody tr + tr td { border-top: 1px solid var(--line); }
table.data tbody tr:hover td { background: var(--brand-soft); }
table.data td.when { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--mut); font-size: 13.5px; }
table.data td.act, table.data th.act { text-align: right; white-space: nowrap; }
table.data .lead { font-weight: 700; color: var(--ink); }
table.data a.lead { color: var(--link); text-decoration: none; }
table.data a.lead:hover { text-decoration: underline; }
table.data .sub { display: block; font-size: 13px; color: var(--mut); font-weight: 500; }
/* An empty queue is good news, not a broken page. */
/* A log wants density: eighty rows of history, not eighty cards. */
table.data-tight td { padding: 8px 14px; }
table.data td.nothing { padding: 32px 16px; text-align: center; color: var(--mut); font-size: 14.5px; }
.unsaid { color: var(--mut); font-style: italic; }

/* A queue table on a phone. The console is a desktop tool, but a queue whose
   Approve and Reject buttons have scrolled off the right-hand edge with no
   visible affordance is not "compromised on small screens", it is broken - so
   below this width each row becomes a block and every cell carries its own
   column name. */
@media (max-width: 760px) {
  table.data thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  table.data, table.data tbody, table.data tr, table.data td { display: block; width: auto; }
  table.data tr { padding: 14px 2px; }
  table.data tbody tr + tr { border-top: 1px solid var(--line); }
  table.data tbody tr + tr td { border-top: 0; }
  table.data tbody tr:hover td { background: transparent; }
  table.data td { padding: 4px 14px; }
  table.data td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 10.5px; font-weight: 800;
    text-transform: uppercase; letter-spacing: .07em;
    color: var(--mut);
  }
  table.data td:first-child { min-width: 0; padding-bottom: 8px; }
  table.data td.act, table.data th.act { text-align: left; }
  table.data td.act { padding-top: 12px; }
  table.data .rowacts { justify-content: flex-start; }
}

/* Two POSTs that decide one row sit side by side. Stacking them is what
   made every queue row three lines tall. */
.rowacts { display: flex; gap: 8px; justify-content: flex-end; align-items: center; flex-wrap: wrap; }
.rowacts form { margin: 0; display: flex; gap: 6px; align-items: center; }
.rowacts select { margin: 0; min-width: 8.5rem; max-width: 11rem; padding: 6px 10px; font-size: 13.5px; }
.rowacts .btn { padding: 7px 14px; font-size: 13px; }

/* ---- the console frame ------------------------------------------------- */
.console-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px 20px; flex-wrap: wrap; margin-bottom: 18px;
}
.console-head h1 { margin: 0; }
.console-head .count { font-size: 14px; color: var(--mut); font-weight: 600; }

.subnav {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin: 0 0 26px; padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.subnav-label {
  font-size: 11.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .09em; color: var(--mut); margin-right: 8px;
}
.subnav a {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--r-pill);
  font-size: 14px; font-weight: 700; text-decoration: none; color: var(--mut);
}
.subnav a:hover { background: var(--brand-soft); color: var(--ink); }
.subnav a[aria-current="page"] { background: var(--ink); color: var(--bg); }
.subnav .n {
  font-size: 11.5px; font-weight: 800;
  border-radius: var(--r-pill); padding: 1px 8px;
  background: var(--c-bg); color: var(--c);
}
.subnav a[aria-current="page"] .n { background: var(--c); color: var(--card); }

/* The overview is a board, not a spreadsheet: each figure is the size of
   its importance, and the ones with work behind them are a door. */
.board { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(186px, 1fr)); }
.tile {
  display: block; text-decoration: none; color: inherit;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--shadow);
  padding: 18px 20px 20px;
}
a.tile:hover { border-color: var(--brand-text); color: inherit; }
.tile .n { display: block; font-size: 34px; font-weight: 800; letter-spacing: -.03em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.tile .k { display: block; font-size: 13.5px; font-weight: 700; color: var(--mut); margin-top: 4px; }
.tile .go { display: block; font-size: 13px; font-weight: 700; color: var(--brand-text); margin-top: auto; padding-top: 12px; }
.tile { display: flex; flex-direction: column; }
.tile-work { border-color: var(--c); background: var(--c-bg); }
.tile-work .n, .tile-work .k, .tile-work .go { color: var(--c); }

/* ---- notices -----------------------------------------------------------
   A rule the operator has to keep, said where the work happens. Purple is
   this product's colour for an open obligation. */
.notice {
  background: var(--ask-bg); border-radius: var(--r-card);
  padding: 16px 18px; margin: 0 0 24px; max-width: 72ch;
}
.notice-title {
  display: block; margin: 0 0 6px; font-size: 12px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .08em; color: var(--ask);
}
.notice p { margin: 0; font-size: 14px; line-height: 1.6; max-width: none; }
.notice p + p { margin-top: 8px; }

/* ---- a record list -----------------------------------------------------
   Bookings, introductions, engagements, applications and cover offers are
   all the same shape: a thing that happened, its state, and what you can do
   about it. One component, so they cannot drift apart. */
.records { list-style: none; padding: 0; margin: 0; display: grid; gap: 14px; }
@media (min-width: 900px) { .records-2 { grid-template-columns: 1fr 1fr; } }
.record {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
  padding: 16px 18px 18px;
  display: flex; flex-direction: column; gap: 11px;
}
/* The left rail repeats the badge's meaning, so a long list reads as blocks
   of state before a single word is read. */
.record-ok   { border-left-color: var(--v-fill); }
.record-wait { border-left-color: var(--c); }
.record-open { border-left-color: var(--ask); }
.record-stop { border-left-color: var(--danger); }
.record-off  { border-left-color: var(--line); }

/* THE ROW GIVES GROUND BEFORE THE CARD DOES.
   Measured at 390: /applications rendered `li.record` from x=20 to x=406 in a
   350px column and the page scrolled sideways. Nothing here was too wide on
   its own — the title column simply could not be made narrower than its own
   longest run of words (190px for "Nanny/Housekeeper needed in Kensington"),
   because `min-width: auto` is a flex item's default and that is what it
   means. Beside a 141px "Not opened yet" and 14px of gap it asked for 345 in
   329, the card's automatic minimum grew with it, and the grid it sits in
   grew with the card.
   Three lines, in the order they take effect: the row may wrap, so the badge
   drops under the title when the two will not share a line; either column may
   then be narrowed, so a wrapped row still fits; and a single word longer
   than the card breaks rather than sticking out of it.
   NO WIDTH QUERY. The row wraps when its own contents say so, so the same
   card behaves the same way in a 300px rail and on a 390px phone. */
.record-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 10px 14px; flex-wrap: wrap;
}
.record-top > * { min-width: 0; }
.record-title, .record-sub { overflow-wrap: break-word; }
.record-who { display: flex; align-items: center; gap: 12px; min-width: 0; }
.record-title { margin: 0; font-size: 17px; font-weight: 800; letter-spacing: -.01em; line-height: 1.3; }
.record-title a { text-decoration: none; }
.record-title a:hover { text-decoration: underline; }
.record-sub { margin: 2px 0 0; font-size: 13.5px; color: var(--mut); }
.record p { margin: 0; max-width: 62ch; }
.record-note {
  margin: 0; font-size: 14px; line-height: 1.6;
  border-left: 2px solid var(--line); padding-left: 12px; font-style: italic;
}
.record-foot {
  margin: 0; font-size: 12.5px; color: var(--mut);
  display: flex; gap: 4px 14px; flex-wrap: wrap; align-items: center;
}
.record-top-right { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; }
.record .actions { margin: 3px 0 0; }
.record form { margin: 0; }
.record .field { margin-bottom: 10px; }
.record label { margin-bottom: 0; }
.record input[type="text"] { max-width: 30rem; }

/* ---- the reveal --------------------------------------------------------
   The one panel in the application that shows a person's contact details.
   Drawn as a released thing - a green rule, and a line saying what happened
   and when - because the release is deliberate, one-way and recorded. */
.reveal {
  background: var(--bg);
  border: 1.5px solid var(--v-fill);
  border-radius: 12px;
  padding: 13px 16px 14px;
}
.reveal-label {
  display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .08em; color: var(--v-fill); margin: 0 0 6px;
}
.reveal-label::before {
  content: ""; width: 6px; height: 11px;
  border: solid var(--v-fill); border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg); margin-bottom: 4px; flex: none;
}
.reveal-value { margin: 0; font-size: 16.5px; font-weight: 700; word-break: break-word; }
.reveal-value a { text-decoration: none; }
.reveal-value a:hover { text-decoration: underline; }
.reveal-none { border-color: var(--line); border-style: dashed; }
.reveal-none .reveal-label { color: var(--mut); }
.reveal-none .reveal-label::before { border-color: var(--mut); }
.reveal-none .reveal-value { font-size: 14.5px; font-weight: 500; color: var(--mut); }

/* ---- an empty page ------------------------------------------------------ */
.empty {
  background: var(--card);
  border: 1px dashed var(--line);
  border-radius: var(--r-card);
  padding: 30px 26px 32px;
  text-align: center;
}
.empty h2 { margin: 0 0 8px; font-size: 17px; }
/* TASK-279: this used to be plain `.empty p`, (0,1,1) -- one step more
   specific than neo.css's `.actions { margin: 16px 0 0 }` at (0,1,0) -- so
   it also caught the empty state's own `<p class="actions">` and reset its
   top margin to 0, closing the gap `.actions` gives every action row in the
   product. The body copy is what this rule means to style; `:not(.actions)`
   says so, rather than leaving `.actions` to win a specificity fight it
   should never have been in. */
.empty p:not(.actions) { margin: 0 auto; max-width: 46ch; color: var(--mut); font-size: 14.5px; }
.empty .actions { justify-content: center; }

/* ---- a compact form grid ------------------------------------------------
   Eight fields stacked one per line is a page of scrolling for a job that is
   one glance wide. */
.grid-form { display: grid; gap: 2px 18px; grid-template-columns: repeat(auto-fit, minmax(225px, 1fr)); align-items: start; }
.grid-form label { margin-bottom: 12px; }
.grid-form input, .grid-form select { max-width: none; }
.grid-form .span-all { grid-column: 1 / -1; }

/* ---- conversation -------------------------------------------------------
   A thread is read, not scanned, so the body is set at reading weight and
   the metadata gets out of the way. Sides are told apart by alignment and
   ground, never by a photograph. */
.thread { list-style: none; padding: 0; margin: 0; display: grid; gap: 16px; }
.turn { max-width: 40rem; }
.turn-mine { margin-left: auto; }
.turn-head { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; color: var(--mut); margin-bottom: 5px; }
.turn-who { font-weight: 800; color: var(--ink); }
.turn-mine .turn-head { justify-content: flex-end; }
.bubble {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px 14px 14px 4px;
  padding: 12px 15px;
  box-shadow: var(--shadow);
}
.turn-mine .bubble { background: var(--brand-soft); border-color: var(--brand-soft); border-radius: 14px 14px 4px 14px; }
.bubble p { margin: 0; font-size: 15px; font-weight: 400; line-height: 1.6; max-width: none; }
.masked {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px;
  font-size: 12px; font-weight: 700;
  color: var(--ask); background: var(--ask-bg);
  border-radius: var(--r-pill); padding: 3px 10px;
}
/* inline-block, because ::first-letter only applies to a block container -
   this is what lets the canonical lower-case sentence stay in the markup and
   still read as a sentence on screen. */
.cap { display: inline-block; }
.cap::first-letter { text-transform: uppercase; }
.composer { margin-top: 26px; }
.composer textarea { max-width: 40rem; min-height: 6em; }
.composer .form-actions { margin-top: 10px; }

/* ---- shared page furniture --------------------------------------------- */
.page-lede { font-size: 16px; color: var(--mut); max-width: 62ch; margin: 0 0 26px; }
.section + .section { margin-top: 40px; }
.section-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.section-head h2 { margin: 0; }
.section-head .count { font-size: 13.5px; color: var(--mut); font-weight: 600; }
