/* Dark, quiet, and dense. Two rules of thumb behind everything here:
   the sheet is the interface, so chrome recedes and data does not; and
   categories are shapes (pills), while values are text.

   The grid's own colours live in grid.js — AG Grid v33 is themed through
   parameters, not a stylesheet — and the two palettes are kept in step by
   hand. If you change a colour here, change it there. */

/* The browser hides [hidden] elements with `display: none` from its own
   stylesheet, which ANY explicit display in this file outranks. #topbar sets
   `display: flex`, so `topbar.hidden = true` did nothing and the sign-in
   screen showed a bar with an empty project picker in it. This is the fix, and
   it has to come first and carry !important to beat every layout rule below.

   jsdom does not do the cascade, so no test can catch this — the assertion in
   login.test.mjs checks the attribute, which was always correct. Look at the
   screen. */
[hidden] { display: none !important; }

:root {
  --bg: #0f1114;
  --card: #16191e;
  --card-2: #1a1d23;
  --ink: #e6e8eb;
  --muted: #8b93a1;
  --dim: #6b7280;
  --line: #23272f;
  --line-strong: #2a2f3a;

  --accent: #4f8cff;
  --accent-dim: #1a2740;
  --ok: #4ade80;
  --ok-dim: #14301f;
  --warn: #f5c26b;
  --warn-dim: #2e2515;
  --danger: #f87171;
  --danger-dim: #331a1a;

  --radius: 10px;
  --radius-sm: 6px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 13px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* Times, dates and day counts are compared down a column — they must line up. */
.time, .num, input.time, .ag-cell[col-id="start"], .ag-cell[col-id="end"],
.ag-cell[col-id="wx"], .ag-cell[col-id="sf_id"] {
  font-variant-numeric: tabular-nums;
}

/* --- top bar --- */

#topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
}

#topbar h1 {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .02em;
  margin: 0;
  white-space: nowrap;
}

#context { display: flex; align-items: center; gap: 12px; flex: 1; }
#identity { display: flex; align-items: center; gap: 10px; margin-left: auto; }

nav#tabs { display: flex; gap: 2px; }

.tab {
  background: none;
  border: 1px solid transparent;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--muted);
}
.tab:hover { background: var(--card-2); color: var(--ink); }
.tab.active {
  background: var(--card-2);
  border-color: var(--line-strong);
  color: var(--ink);
  font-weight: 600;
}

/* --- layout --- */

#view { padding: 20px; max-width: 1600px; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  margin-bottom: 16px;
}
.card.inset { background: var(--card-2); }
.card h2 { margin: 0 0 4px; font-size: 14px; font-weight: 600; }
.card h3 { margin: 0 0 4px; font-size: 13px; font-weight: 600; }

.card.login { max-width: 380px; margin: 80px auto; }
.card.login input { display: block; width: 100%; margin: 12px 0; }

/* The control strip above the sheet: one recessed bar, like the mockup's. */
.row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.row label { display: flex; align-items: center; gap: 6px; color: var(--muted); }
.spacer { flex: 1; }

.muted { color: var(--muted); }
.num { text-align: right; }

/* --- controls --- */

input, select, button {
  font: inherit;
  color: var(--ink);
  padding: 6px 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
input::placeholder { color: var(--dim); }
input:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
input:disabled { background: var(--card-2); color: var(--dim); }
input.wide { flex: 1; min-width: 260px; }
input.time { width: 76px; text-align: center; }

button {
  cursor: pointer;
  background: var(--card-2);
  border-color: var(--line-strong);
  font-weight: 500;
}
button:hover:not(:disabled) { border-color: var(--muted); background: #20242c; }
button:disabled { opacity: .45; cursor: default; }

/* Tinted outlines rather than solid fills: the sheet stays the loudest thing
   on the page, and the two consequential buttons still stand apart. */
button.primary {
  background: var(--ok-dim);
  border-color: #2f6b45;
  color: #86efac;
}
button.primary:hover { background: #1a3d28; border-color: var(--ok); }

button.link { border: none; background: none; padding: 4px 6px; color: var(--accent); }
button.link.danger { color: var(--danger); }
button.link:hover { background: none; text-decoration: underline; }

.pill {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--card-2);
  border: 1px solid var(--line-strong);
  font-size: 11px;
  color: var(--muted);
}

/* --- category tags (BLOCK column in the mockup) --- */

.tag {
  display: inline-block;
  padding: 2px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  line-height: 1.6;
}
.tag-core { color: #86efac; border-color: #2f6b45; background: var(--ok-dim); }
.tag-daily { color: var(--warn); border-color: #6b5423; background: var(--warn-dim); }
/* Added by hand, no Start Form behind it. Deliberately cooler than core and
   daily: it is not a deal CM knows about, it is the head's own word. */
.tag-manual { color: #93b4e0; border-color: #33506f; background: rgba(111, 155, 216, .14); }

/* --- the day's units, above the sheet --- */

/* What the day offers, as one chip per unit. This was a four-column table
   three lines tall, to say two numbers per unit that are read once at the
   start of a day — and it pushed the sheet, which is the actual interface,
   down the screen. The dropped column headings live on each chip's title. */
.day-units { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.du-unit {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--card-2);
  border: 1px solid var(--line-strong);
}
.du-unit .time { font-variant-numeric: tabular-nums; }

/* The two free-text batch boxes. Left to themselves they stretch and push
   Submit onto a row of its own, which is the thing this layout exists to
   avoid — and neither a unit name nor a location needs the width. */
input.batch-wide { width: 140px; }

/* Coverage: a count sits UNDER its weekday. AG Grid's numericColumn puts the
   value hard right and the column-menu button hard left of the header, which
   on a 90px column means the label and the number are at opposite ends and
   the eye cannot pair them. Both centred, menu button suppressed. */
.ag-header-cell.hdr-centre .ag-header-cell-label { justify-content: center; }
.ag-cell.cov-num { text-align: center; }

/* --- responsibilities --- */

/* The setup grid gets more height than the submit sheet: it is the whole
   screen, and it is worked through a department at a time. */
.grid-host.tall { height: 68vh; }

/* The department bar's own tick box — AG Grid does not give a full-width group
   row one, so this is ours. */
.dept-bar { display: inline-flex; align-items: center; gap: 9px; }
.dept-tick { cursor: pointer; }

/* --- combobox --- */

.combo { position: relative; display: inline-block; min-width: 240px; }
.combo input { width: 100%; }

.combo-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 260px;
  overflow-y: auto;
  background: var(--card-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
  z-index: 30;
}

.combo-item {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 12px;
  cursor: pointer;
}
.combo-item + .combo-item { border-top: 1px solid var(--line); }
.combo-item:hover, .combo-item.active { background: #232833; }
.combo-item .muted { font-size: 11px; text-align: right; flex-shrink: 0; }
.combo-item.combo-new { color: var(--accent); }

/* --- AG Grid host --- */

.grid-host { height: 560px; width: 100%; margin-top: 12px; }

/* The combobox lives inside a popup cell editor, where it must size itself
   rather than inherit the cell's width. Names and titles are long — a fixed
   320px box truncated most of them — so it is generous and grows with the
   viewport rather than being pinned to one number. */
.combo-in-cell {
  min-width: min(560px, 60vw);
  background: var(--card-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
}
.combo-in-cell .combo-list {
  position: static;
  box-shadow: none;
  border: none;
  border-top: 1px solid var(--line);
  max-height: 320px;
}
.combo-in-cell .combo-item span:first-child { overflow-wrap: anywhere; }

/* Column headers: small, spaced, quiet. */
.ag-header-cell-text {
  text-transform: uppercase;
  letter-spacing: .06em;
}

/* A row that is off, or on Off Set, has no meaningful times — dim them so the
   empty cells read as deliberate rather than forgotten. */
.ag-cell.cell-idle { opacity: .35; }

/* A row with days on it is the normal case and should read as the solid
   foreground; "did not work" recedes into italics and grey, as in the mockup.
   Greyed only — a strike-through read as "deleted" when the row is very much
   still going in. */
.ag-row.row-off .ag-cell { color: var(--dim); font-style: italic; }

/* A submitted row: locked, on record, and unmistakably not draft. Blue,
   because blue is already this app's "recorded in the system" colour — the
   SF number wears it too. */
/* Read down a long sheet, a tint alone is too quiet — the eye wants an edge.
   Hence the bar on the left of the name cell: it makes the sent block
   scannable at a glance without shouting over the rows still being filled in.
   No strike-through anywhere here: a sent row is the LIVE record, and a strike
   would say it had been withdrawn. */
.ag-row.row-locked { background-color: rgba(79, 140, 255, .13) !important; }
.ag-row.row-locked .ag-cell { color: #b6cbe8; font-style: normal; }
.ag-row.row-locked .ag-cell[col-id="name"] {
  box-shadow: inset 3px 0 0 var(--accent);
  font-weight: 600;
  color: #d7e4f7;
}
.ag-row.row-locked .ag-cell[col-id="system_note"] { color: #7f9dc7; }

/* --- Companies: the people under a company's blank deals ---------------- */

.co-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.co-card {
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
}
.co-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.co-name { font-weight: 650; }
.co-bds { font-size: 12px; margin: 2px 0 8px; }
.co-people { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
/* A listed person is a chip, not a row: the list is short, and a chip says
   "one value among several" where a row would imply a record. */
.co-person {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 4px 2px 9px;
  border-radius: 999px;
  background: var(--accent-dim); color: #cfe0ff;
  border: 1px solid #2b3f63;
}
.co-drop {
  background: none; border: none; padding: 0 4px;
  color: #7f9dc7; font-size: 12px; line-height: 1; cursor: pointer;
}
.co-drop:hover { color: var(--danger); }

.co-paste {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  resize: vertical;
}
/* What a paste did. Stays on the card until dismissed — "3 of 22 were already
   listed" is a sentence somebody has to read, and a toast is a thing that
   goes away while they are still reading it. */
.co-report {
  margin: 8px 0;
  padding: 8px 10px;
  border-left: 3px solid var(--accent);
  background: var(--card);
  border-radius: var(--radius-sm);
}
.co-skipped { margin: 6px 0 0; padding-left: 18px; color: var(--warn); font-size: 12px; }

/* --- the view toggle, and the card view -------------------------------- */

/* Grid or Cards. The same rows either way: see submit.js, which routes every
   card edit through the grid's own value setters rather than repeating them. */
.viewtoggle {
  display: inline-flex;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.viewtoggle button {
  border: none; border-radius: 0;
  background: var(--card-2); color: var(--muted); padding: 5px 12px;
}
.viewtoggle button.on { background: var(--accent-dim); color: #cfe0ff; font-weight: 650; }

/* THE layout rule. One line, no breakpoints, no second screen to maintain:
   a phone gets one column, an iPad two or three, a laptop four or five. */
.cards-host {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: 10px;
  align-items: start;
  margin-top: 10px;
}

.card-row {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 11px 9px;
  position: relative;
}
/* The same four states the grid paints, in the same order of precedence. */
.card-row.is-off { opacity: .66; }
.card-row.is-sent { background: rgba(79, 140, 255, .10); border-color: #2b3f63; }
.card-row.is-sent::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px;
  background: var(--accent); border-radius: 2px;
}
/* Being amended: dimmed, never struck through — it is still the record until
   the amendment is sent. */
.card-row.is-amended { opacity: .6; }
.card-row.is-amends { border-color: var(--warn); }
.card-row.is-ticked { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

.card-head { display: flex; align-items: flex-start; gap: 8px; }
.card-tick { flex: none; margin-top: 2px; width: 15px; height: 15px; accent-color: var(--accent); }
.card-who { min-width: 0; flex: 1; }
.card-name { font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-title { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-sf { color: var(--dim); font-size: 11px; }

/* The editable pair on an open card. They stand where the read-only name and
   title do and carry the same weight, so a card does not change shape when it
   turns out to be one you can still type into. Full width: a name is the
   longest thing on the card and a phone has no room to waste. */
.card-name-in,
.card-title-in { width: 100%; min-width: 0; }
.card-name-in { font-weight: 650; }
.card-title-in { color: var(--muted); }

/* W and the two times are the whole job, so they get the whole width and a
   target big enough for a thumb. */
.card-day { display: flex; align-items: center; gap: 6px; margin: 9px 0 8px; }
.card-w { flex: none; width: 46px; height: 34px; text-align: center; padding: 0 4px; font-size: 15px; font-weight: 700; }
span.card-w { display: flex; align-items: center; justify-content: center; color: var(--accent); }
.card-times { display: flex; align-items: center; gap: 5px; flex: 1; min-width: 0; }
span.card-times { color: var(--ink); justify-content: flex-start; }
.card-t { flex: 1; min-width: 0; height: 34px; text-align: center; padding: 0 4px; font-size: 14px; }
.card-dash { color: var(--dim); }
.card-unit { width: 100%; }

.card-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tag-unit { color: #cfe0ff; border-color: #2b3f63; background: var(--accent-dim); }
.tag-mp { color: var(--warn); border-color: #6b5423; background: var(--warn-dim); }

.card-note {
  margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--line);
  color: var(--muted); font-size: 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card-sys { margin-top: 6px; color: var(--warn); font-size: 12px; }
.card-row.is-sent .card-sys { color: #7f9dc7; }

/* Meal penalty, location and note are the uncommon case, so they fold away
   until wanted. A native details element: no state to keep, and it works
   with a keyboard for free. */
.card-more { margin-top: 7px; }
.card-more > summary { color: var(--accent); font-size: 12px; cursor: pointer; list-style: none; }
.card-more > summary::-webkit-details-marker { display: none; }
.card-more > summary::before { content: "+ "; }
.card-more[open] > summary::before { content: "− "; }
.card-more-fields { display: flex; flex-direction: column; gap: 6px; margin-top: 7px; }
.card-more-fields input { width: 100%; }

/* Touch: a 34px box is fine under a mouse and mean under a thumb, and iOS
   zooms the page for any font under 16px in a focused field. */
@media (pointer: coarse) {
  .card-t, .card-w, .card-unit, .card-more-fields input { min-height: 42px; font-size: 16px; }
  .card-tick { width: 20px; height: 20px; }
  .cards-host { gap: 12px; }
}

/* The version badge: this row is not the first thing said about this person
   on this day. Small and blue — it belongs to the sent-row family, and it is
   a fact about the row rather than a warning about it. */
.ver-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 0 5px;
  border-radius: var(--radius-sm);
  background: rgba(79, 140, 255, .26);
  color: #dbe8fb;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.55;
  vertical-align: middle;
}

/* Being amended: the copy below it is not sent yet, so this row is STILL the
   truth. Dimmed to say "you are working on this one", never struck out. */
.ag-row.row-amended { background-color: rgba(79, 140, 255, .07) !important; }
.ag-row.row-amended .ag-cell { opacity: .62; }

/* The amendment itself: a draft row that will replace the one above it. */
.ag-row.row-amends .ag-cell[col-id="name"] { box-shadow: inset 3px 0 0 var(--warn); }
.ag-row.row-amends .ag-cell[col-id="system_note"] { color: var(--warn); }

/* Amend, in the same slot the working toggle uses on an unsent row. */
.row-amend {
  display: inline-block; min-width: 22px;
  color: #6f8cba; font-size: 14px; line-height: 1.4;
  border-radius: var(--radius-sm);
}
.ag-cell[col-id="remove"]:hover .row-amend { background: var(--card-2); color: #cfe0ff; }

/* NOTE: unselected rows are deliberately NOT dimmed. That rule dated from
   when ticking meant "include in the submission"; the box is only a batch
   selector now, and nothing is ticked by default, so it greyed the whole
   sheet. What a row is worth is said by its days, not by its tick. */

/* The System note column. Anything the app has to say about a row lives here,
   away from the columns being filled in. Amber, not red: a thing to notice,
   not an error. */
.ag-cell.cell-warn { color: var(--warn); }

/* The SF number is a reference, not a value — recessive, and blue like the
   mockup's, so it reads as a link to something in Crew Manager. */
.ag-cell[col-id="sf_id"] { color: #6f9bd8; }

/* The working/not-working toggle. The whole cell is the hit target, so make
   that obvious; the glyph says which way the click will go. */
.ag-cell[col-id="remove"] { cursor: pointer; text-align: center; }

/* AG Grid puts `text-overflow: ellipsis` on every cell and 14px of padding on
   each side. A cell whose content is an ELEMENT rather than text still gets the
   "…" painted beside it when that element is wider than the padded box — so the
   44px toggle column and the DAILY pill both grew two stray dots that mean
   nothing and truncate nothing. Clip instead of marking, and give these two
   their width back. CORE never showed it; it is simply a shorter word. */
.ag-cell[col-id="remove"],
.ag-cell[col-id="deal_type"] {
  text-overflow: clip;
  padding-left: 4px;
  padding-right: 4px;
}
.row-toggle {
  display: inline-block;
  min-width: 22px;
  color: var(--dim);
  font-size: 15px;
  line-height: 1.4;
  border-radius: var(--radius-sm);
}
/* On a stood-down row the toggle offers to put them back on: green, like the
   day it will give them. */
.row-toggle-on { color: #86efac; font-weight: 700; }
.ag-cell[col-id="remove"]:hover .row-toggle { background: var(--card-2); color: var(--ink); }

/* --- tables (admin screens) --- */

table.grid { width: 100%; border-collapse: collapse; margin-top: 12px; }
table.grid th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
  padding: 8px;
}
table.grid td { padding: 6px 8px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.grid tr.dim td { opacity: .45; }
table.submit td:first-child, table.submit th:first-child { width: 28px; }

.sf-id {
  font-size: 11px;
  color: var(--dim);
  margin-left: 6px;
  font-variant-numeric: tabular-nums;
}

/* --- assignment tree --- */

details.dept { border-top: 1px solid var(--line); padding: 8px 0; }
details.dept summary { cursor: pointer; list-style: none; }
details.dept summary::-webkit-details-marker { display: none; }
.sf-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 2px;
  padding: 6px 0 6px 18px;
}
label.sf { display: flex; align-items: center; gap: 7px; padding: 2px 0; }

/* --- toast --- */

#toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  padding: 11px 20px;
  border-radius: var(--radius);
  color: var(--ink);
  background: var(--card-2);
  border: 1px solid var(--line-strong);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
  z-index: 50;
}
#toast.error {
  background: var(--danger-dim);
  border-color: #6b2b2b;
  color: #fca5a5;
}
