/* lane.css — the two views.
 *
 * ONE STYLESHEET FOR BOTH, AND WHY
 * The advisor's phone and the concierge iPad show the same things — a request, a
 * person, how long something has been waiting — from opposite ends. If they had
 * separate stylesheets, "eleven minutes is orange" would eventually be true on
 * one screen and not the other, and the two people looking at them would be
 * having a disagreement the software caused. So the components are shared and
 * only the layout differs.
 *
 * THE SURFACE CLASS
 * `is-hand` and `is-desk` come from shared/device.js and mean "poked with a
 * finger" and "read with a mouse in reach". They are the only thing in here
 * that knows about hardware; everything else is composed from them.
 */

/* ---------------- shell ---------------- */

.lane-shell {
  max-width: 620px; margin: 0 auto; min-height: 100vh;
  display: flex; flex-direction: column;
  padding-bottom: env(safe-area-inset-bottom);
}
.lane-shell.is-wide { max-width: none; }

.lane-bar {
  background: var(--surface); border-bottom: 1px solid var(--line);
  padding: 10px 16px; display: flex; align-items: center; gap: 10px;
  position: sticky; top: 0; z-index: 20;
}
.lane-bar .who { min-width: 0; }
.lane-bar .store { font-weight: 650; font-size: .9375rem; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lane-bar .state { color: var(--muted); font-size: .75rem; display: flex; align-items: center; gap: 6px; }
.lane-bar .right { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: none; }

.lane-body { padding: 14px 16px 28px; flex: 1; }

/* The count in the header is the one thing on this screen somebody reads from
   the other side of the drive, and it used to be the same brand blue whether
   nothing was waiting or the oldest request was twenty minutes old. It carries
   the worst tone on the board now, which is the difference between a number and
   a signal. */
.waiting-badge {
  background: var(--brand-soft); border: 1px solid var(--brand-line); color: var(--brand);
  border-radius: 999px; padding: 4px 12px; font-weight: 650; font-size: .875rem;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.waiting-badge.wait-none { background: var(--surface-3); border-color: var(--line); color: var(--muted); }
.waiting-badge.wait-attn { background: var(--attn-soft); border-color: var(--attn-line); color: var(--attn); }
.waiting-badge.wait-high { background: var(--high-soft); border-color: var(--high-line); color: var(--high); }
.waiting-badge.wait-crit { background: var(--crit);      border-color: var(--crit);      color: #fff; }

/* ---------------- panels ---------------- */

.panel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
  padding: 14px 16px; margin-bottom: 14px;
}
.panel-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.panel-head h2 { font-size: 1rem; }
.panel-note { margin-left: auto; color: var(--muted); font-size: .8125rem; }

/* ---------------- the one button ----------------
   Deliberately the largest thing on the advisor's screen. It is the only reason
   they opened the app. */

.ask {
  appearance: none; width: 100%; border: 0; cursor: pointer;
  background: var(--brand); color: var(--brand-ink);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: 20px; margin-bottom: 16px;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  font: inherit; font-size: 1.125rem; font-weight: 650;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
  transition: transform .05s ease-out, background-color .1s linear;
}
.ask:active { transform: scale(.985); background: #0d5395; }
.ask-plus {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: rgb(255 255 255 / .18); font-size: 1.4rem; line-height: 1; font-weight: 500;
}
@media (prefers-reduced-motion: reduce) { .ask:active { transform: none; } }

/* ---------------- the sheet ---------------- */

.sheet {
  position: fixed; inset: 0; z-index: 50;
  background: rgb(19 26 36 / .42);
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0;
}
.sheet-card {
  background: var(--surface); width: 100%; max-width: 520px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: var(--shadow-lg);
  max-height: 92vh; overflow-y: auto;
  padding-bottom: env(safe-area-inset-bottom);
}
.sheet-head {
  display: flex; align-items: center; gap: 10px;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--surface); z-index: 1;
}
.sheet-head h2 { font-size: 1.0625rem; }
.sheet-head .gear { margin-left: auto; }
.sheet-body { padding: 18px; }
.sheet-sub { color: var(--muted); font-size: .875rem; margin-bottom: 14px; }
body.sheet-open { overflow: hidden; }

.gear {
  appearance: none; background: none; border: 1px solid var(--line);
  border-radius: 8px; color: var(--text-2);
  width: 38px; height: 38px; cursor: pointer; font-size: 1rem; line-height: 1;
  display: grid; place-items: center;
}
.gear:active { background: var(--surface-3); }

/* The three things an advisor can ask for. Stacked and large: this is a choice
   made while standing next to a customer, not a menu to be browsed. */
.choices { display: flex; flex-direction: column; gap: 10px; }
.choice {
  appearance: none; text-align: left; cursor: pointer; font: inherit;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg); padding: 16px 18px;
  display: flex; flex-direction: column; gap: 3px;
  touch-action: manipulation;
}
.choice:active { background: var(--surface-3); }
.choice-label { font-size: 1.0625rem; font-weight: 650; }
.choice-sub { color: var(--muted); font-size: .8125rem; }

/* ---------------- steppers ----------------
   Two big targets and a number, because a <input type=number> raises a keyboard
   and a keyboard covers the button you are reaching for. */

.stepper {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--line);
}
.stepper-label { font-weight: 550; flex: 1; }
.stepper-btn {
  width: 52px; min-height: 52px; font-size: 1.5rem; justify-content: center; padding: 0;
  touch-action: manipulation;
}
.stepper-value {
  min-width: 108px; text-align: center; font-weight: 650; font-size: 1.0625rem;
}

/* ---------------- a request ----------------
 *
 * The left border carries the age. That is the whole colour system on this
 * screen: nothing else is tinted, so a row going orange is unmissable and means
 * exactly one thing. Tinting the whole card was tried in the loaner board and
 * rejected there for the same reason — a wall of coloured cards is a wall.
 */

.req-list, .col-list, .who-list { list-style: none; margin: 0; padding: 0; }
.req-list { display: flex; flex-direction: column; gap: 10px; }

.req {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 4px solid var(--line-strong);
  border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow);
}
.req-ok   { border-left-color: var(--ok); }
.req-attn { border-left-color: var(--attn); }
.req-high { border-left-color: var(--high); }
.req-crit { border-left-color: var(--crit); }

/* A run somebody is already on reads as settled rather than urgent — it has
   been picked up, and the thing worth noticing on this screen is the ones that
   have not been. */
.req.is-running { background: var(--surface-2); }
/* Yours. Somebody scanning the board needs to find their own runs instantly. */
.req.is-mine { box-shadow: inset 3px 0 0 var(--brand), var(--shadow); }

/* ---------------- how old, and how that looks ----------------
 *
 * The age used to be grey text that changed colour at the bands. That is the
 * right idea drawn too quietly: on a card read from six feet the difference
 * between #778394 and #8a6100 at 15px is not a difference. So past the first
 * band the age becomes a filled pill — the same shape used for every status in
 * this application — and the card itself picks up a tint once it is properly
 * late. The escalation is deliberately uneven: white, then a pill, then a warm
 * card, then a red one. A scale that changes by the same amount at every step
 * cannot be read at a glance, because every step looks like the last.
 *
 * The word goes on the element as a title either way — see toneLabel() in
 * shared/requests.js for why colour is never carrying this alone. */
.req-age.age-attn, .req-age.age-high, .req-age.age-crit {
  padding: 2px 9px; border-radius: 999px; border: 1px solid; font-size: .8125rem;
}
.req-age.age-attn { background: var(--attn-soft); border-color: var(--attn-line); color: var(--attn); }
.req-age.age-high { background: var(--high-soft); border-color: var(--high-line); color: var(--high); }
.req-age.age-crit { background: var(--crit);      border-color: var(--crit);      color: #fff; }

.req.req-high { background: var(--high-soft); }
.req.req-crit { background: var(--crit-soft); }

.req-head { display: flex; align-items: baseline; gap: 10px; }
.req-kind {
  font-size: .75rem; font-weight: 650; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted);
}
.req-big { font-size: 1.75rem; font-weight: 650; letter-spacing: -.01em; line-height: 1.1; }
.req-age { margin-left: auto; color: var(--muted); font-weight: 600; font-size: .9375rem; }
/* The age's colour lives entirely in the .age-* classes above. These three used
   to set it from the card's tone and, sitting further down the file at equal
   specificity, they quietly won — which painted the crit pill's text in crit
   red on a crit red fill and made the number disappear exactly when it mattered
   most. Two rules describing one colour is the bug; deleting one is the fix. */

.req-kind.kind-ro      { background: var(--id-a-soft); border: 1px solid var(--id-a-line); color: var(--id-a); }
.req-kind.kind-shuttle { background: var(--id-b-soft); border: 1px solid var(--id-b-line); color: var(--id-b); }
.req-kind.kind-visit   { background: var(--id-c-soft); border: 1px solid var(--id-c-line); color: var(--id-c); }
.req-kind { padding: 2px 8px; border-radius: 999px; }

.req-title { font-size: 1.0625rem; font-weight: 600; margin-top: 2px; }
.req-from, .req-detail { color: var(--text-2); font-size: .875rem; margin-top: 3px; }
.req-note {
  margin-top: 6px; font-size: .875rem; color: var(--text-2);
  background: var(--surface-3); border-radius: 6px; padding: 6px 9px;
}
/* What is happening to this request, as a word rather than as an inference from
   which buttons are showing. "Waiting" and "Out with Jess" are the two states
   that matter to whoever is reading, and neither of them was written anywhere
   on the concierge board before — they were implied by a background shade. */
/* Always neutral, whatever the card's tone.
   It said "Waiting" in crit red, on a crit red card, next to a crit red age
   pill — three things shouting one fact, which is how a screen stops having a
   loudest element. The state is WHAT is happening; the age is HOW BAD it is.
   Only one of those escalates. */
.req-state { display: inline-flex; align-items: center; gap: 5px; }

.req-foot, .req-with {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; font-size: .875rem; color: var(--muted);
}
.req-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.btn-tap { flex: 1 1 40%; min-height: 52px; justify-content: center; font-size: 1rem; touch-action: manipulation; }
/* Stepping somebody off names them — "Step off: Jess" — and a name is not
   something to truncate on the one screen where it is the whole point of the
   button. On a shared screen a two-person shuttle carries two of these, so they
   take a line each rather than fighting Accept and Done for the same row. */
.btn-release { flex: 1 1 100%; }
.btn-done { background: var(--ok); border-color: var(--ok); color: #fff; font-weight: 650; }
.btn-done:hover { background: #17573a; border-color: #17573a; }

/* ---------------- the desk layout ----------------
 *
 * Advisors and the front desk work at computers, in landscape, and the advisor
 * board used to be a single 620px column down the middle of a 1400px monitor —
 * a phone layout being shown on a desk because the phone was the harder case to
 * get right. What somebody does here has an order: the thing they came to do,
 * then what they have outstanding, then who is free. On a narrow screen that
 * order is vertical; on a wide one it is the left column and then the right,
 * which is the same order read the way a person reads a desk.
 */
.lane-body.desk, .lane-body.admin { max-width: 1280px; margin: 0 auto; width: 100%; }

.desk-grid { display: grid; gap: 16px; grid-template-columns: 1fr; }
.desk-main, .desk-side { min-width: 0; }

@media (min-width: 980px) {
  .desk-grid { grid-template-columns: minmax(0, 1.55fr) minmax(300px, .85fr); align-items: start; }
  /* Outstanding requests tile across the width they have been given rather than
     running down it in a single file, because an advisor with four cars up at
     once is the ordinary Saturday and scrolling to find one of four is not. */
  .req-list.cards {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
    align-items: start;
  }
}

/* ---------------- the concierge columns ----------------
 *
 * NOT THREE EQUAL THIRDS, AND THE REASON IS THE WORK
 * A shift is mostly ROs — every car being delivered is one, they arrive in
 * bursts, and they are the column somebody is reading when they walk past with
 * keys in their hand. Shuttles are a handful an hour. "Come see me" is capped by
 * the application itself at one per advisor at a time (see createRequest in
 * routes/requests.js), so its ceiling is the number of desks in the store and in
 * practice it holds two rows.
 *
 * Equal thirds spend the same width on all three, which means the RO column
 * wraps and scrolls while a third of the screen sits empty next to it. The
 * weights below are the volumes.
 */

.columns { display: grid; gap: 14px; grid-template-columns: 1fr; }
@media (min-width: 900px) {
  .columns { grid-template-columns: 1.6fr 1fr .72fr; align-items: start; }
  /* The one that gets read from six feet away gets the bigger number. */
  .col-ro .req-big { font-size: 2rem; }
}

.col {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow); overflow: hidden;
}
/* The header says WHICH column — identity, from the cool palette — and the count
   badge says how bad it is — status, from the urgent one. Two questions, two
   palettes, one row. From across the drive the tint is what tells somebody
   which column they are looking at before any of the words resolve. */
.col-head {
  display: flex; align-items: baseline; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line); background: var(--surface-2);
}
.col-head h2 { font-size: .9375rem; }
.col-ro      .col-head { background: var(--id-a-soft); border-bottom-color: var(--id-a-line); }
.col-ro      .col-head h2 { color: var(--id-a); }
.col-shuttle .col-head { background: var(--id-b-soft); border-bottom-color: var(--id-b-line); }
.col-shuttle .col-head h2 { color: var(--id-b); }
.col-visit   .col-head { background: var(--id-c-soft); border-bottom-color: var(--id-c-line); }
.col-visit   .col-head h2 { color: var(--id-c); }

.col-count {
  margin-left: auto; font-weight: 650; color: var(--muted);
  background: var(--surface-3); border: 1px solid transparent; border-radius: 999px;
  padding: 1px 10px; font-size: .8125rem;
}
.col-count.count-attn { background: var(--attn-soft); border-color: var(--attn-line); color: var(--attn); }
.col-count.count-high { background: var(--high-soft); border-color: var(--high-line); color: var(--high); }
.col-count.count-crit { background: var(--crit);      border-color: var(--crit);      color: #fff; }
.col-list { padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.col-list .empty { padding: 22px 8px; }

/* ---------------- the undo strip ---------------- */

.closed-strip {
  display: flex; gap: 8px; flex-wrap: wrap; margin-top: 18px;
  padding-top: 14px; border-top: 1px solid var(--line);
}
.closed-chip {
  appearance: none; cursor: pointer; font: inherit; font-size: .8125rem;
  background: var(--surface); border: 1px dashed var(--line-strong);
  color: var(--muted); border-radius: 999px; padding: 6px 13px;
  touch-action: manipulation;
}
.closed-chip:active { background: var(--surface-3); color: var(--text); }

/* ---------------- who is on ---------------- */

.who-list { display: flex; flex-direction: column; }
.who-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.who-row:last-child { border-bottom: 0; }
/* Greyed out, and only greyed out — not hidden. An advisor needs to see that
   Jess exists and is on a shuttle, because "there is nobody" and "everybody is
   out" call for different decisions. */
.who-row.is-away { opacity: .55; }
.who-row.is-me .who-name { font-weight: 650; }
.who-row.is-me .who-desk { color: var(--brand); }

.who-id { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.who-desk { font-weight: 650; font-size: 1.0625rem; color: var(--text-2); }
.who-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who-status { margin-left: auto; display: flex; align-items: center; gap: 9px; flex: none; }
.who-since { color: var(--muted); font-size: .8125rem; font-weight: 600; }

.presence-row { display: flex; gap: 8px; flex-wrap: wrap; }
.presence-btn { flex: 1; justify-content: center; min-height: 46px; touch-action: manipulation; }
/* THE CONTROL AND THE INDICATOR SPEAK THE SAME LANGUAGE.
   The button that sets "At lunch" is the amber one, and the pill that says
   somebody is at lunch is amber too. When every selected button was brand blue,
   a person setting their status had to learn one mapping for the buttons and
   another for the board. */
.presence-btn.is-on { font-weight: 650; }
.presence-btn.is-on.tone-ok   { background: var(--ok);   border-color: var(--ok);   color: #fff; }
.presence-btn.is-on.tone-attn { background: var(--attn); border-color: var(--attn); color: #fff; }
.presence-btn.is-on.tone-info { background: var(--info); border-color: var(--info); color: #fff; }

/* ---------------- the concierge view's status panel ----------------
 *
 * A drawer on a narrow screen and a permanent column on a wide one. The iPad in
 * the drive is wide, so in practice it is always up — but the same page opened
 * on a phone must not lose it, and a drawer is how it stays reachable
 * without stealing half the width.
 */

.status-panel { display: none; }
body.status-open .status-panel {
  display: block; position: fixed; inset: 56px 0 0 auto;
  width: min(380px, 92vw); overflow-y: auto; z-index: 30;
  background: var(--bg); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg); padding: 14px;
}
/* Keyed on `has-status` and NOT on `is-wide`, which is a distinction that cost
   an afternoon: `is-wide` only means "do not cap this shell at 620px", and the
   advisor board and the account manager both want that. When this rule was
   written against `is-wide` it also handed those two pages a 340px second
   column for a status panel neither of them has, so their content stopped 340px
   short of the right edge and the space sat empty. A layout rule that reserves
   room for an element has to name the element. */
@media (min-width: 1180px) {
  .lane-shell.has-status { display: grid; grid-template-columns: 1fr 340px; grid-template-rows: auto 1fr; }
  .lane-shell.has-status .lane-bar { grid-column: 1 / -1; }
  .lane-shell.has-status .lane-body { grid-column: 1; }
  .lane-shell.has-status .status-panel {
    display: block; grid-column: 2; position: static; width: auto;
    border-left: 1px solid var(--line); background: transparent; box-shadow: none;
    padding: 14px 16px 28px; overflow-y: visible;
  }
  #statusToggle { display: none; }
}

/* ---------------- the surface ----------------
   Everything above is the desk layout. `is-hand` scales the touch targets and
   the type that has to be read at arm's length; it does not move anything,
   because a layout that reflows between two screens is two layouts to maintain. */

body.is-hand .btn { min-height: 46px; }
body.is-hand .form-row input, body.is-hand .form-row select { min-height: 46px; font-size: 1rem; }
body.is-hand .btn-tap { min-height: 58px; font-size: 1.0625rem; }
body.is-hand .req-big { font-size: 2rem; }
body.is-hand .closed-chip { padding: 9px 15px; }
body.is-hand .who-row { padding: 13px 0; }

/* ---------------- a notice that is not a warning ----------------
 *
 * The station banner: somebody has signed into a shared screen and everything
 * they tap is going on the board as them. That is worth saying plainly and is
 * not an error, so it does not borrow the amber a test board uses.
 */
.banner-soft {
  background: var(--brand-soft); border-bottom: 1px solid var(--brand-line);
  color: var(--brand); padding: 9px 16px; font-size: .8125rem;
}

/* A name in the "who is going" picker that is not marked ready. Dimmed, never
   hidden: somebody at lunch who is standing at the podium taking a shuttle
   anyway is a normal Tuesday, and a picker that omits them is one that gets
   worked around. */
.choice.is-away { opacity: .6; }

/* ---------------- the tool bar ----------------
 *
 * Tabs inside the header rather than a bar of their own, so the concierge
 * columns do not lose a row to navigation. 40px tall on a desk and 44px on a
 * touch screen — the size of every other target in the header — on a quiet
 * track so it reads as "where am I" before it reads as buttons.
 */
.tool-nav {
  display: flex; gap: 3px; padding: 3px; margin-left: 10px; flex: none;
  background: var(--surface-3); border: 1px solid var(--line); border-radius: 12px;
}
.tool-tab {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 0 14px; border-radius: 9px;
  color: var(--text-2); font-weight: 600; font-size: .9375rem; text-decoration: none;
  white-space: nowrap; touch-action: manipulation; -webkit-user-select: none; user-select: none;
  transition: background-color .08s linear;
}
.tool-tab:hover { background: var(--surface); color: var(--text); }
.tool-tab:active { background: var(--line); }
.tool-tab[aria-current="page"] {
  background: var(--surface); color: var(--brand); box-shadow: var(--shadow);
}
.tool-icon {
  width: 19px; height: 19px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
body.is-hand .tool-tab { min-height: 44px; }

/* Narrow: the tabs you are not on become icons; the one you are on keeps its
   name. An iPad in portrait with the concierge header's four buttons lands
   here, and still says in words which screen it is. */
@media (max-width: 1000px) {
  .tool-tab:not([aria-current="page"]) { padding: 0 12px; }
  .tool-tab:not([aria-current="page"]) .tool-label { display: none; }
}
@media (max-width: 520px) {
  .tool-nav { margin-left: 4px; }
  .tool-tab { padding: 0 11px; }
  .tool-tab .tool-label { display: none; }
  .lane-bar .who { flex: 1; }
}
