/* ==========================================================================
   SelectRFP — operations console
   Density over decoration. Every figure is mono and tabular so columns of
   rates and dates line up when you scan them.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700;800&family=IBM+Plex+Mono:wght@400;500;600&display=swap');

:root {
  /* Ink — warm near-black, so it sits with the orange rather than against it */
  --ink-900: #16120E;
  --ink-800: #241D17;
  --ink-700: #362C23;
  --ink-500: #5C5045;
  --ink-400: #7A6E62;
  --ink-300: #9E9287;

  /* Structure */
  --canvas:    #F2F0ED;
  --surface:   #FFFFFF;
  --surface-2: #FAF8F6;
  --line:      #E0DBD5;
  --line-soft: #EDE9E4;

  /* Brand. #fd7008 is the Select Hospitality orange — bright enough to carry
     the identity, too bright to sit under white text (2.8:1). So the accent
     keeps the exact hue for marks, borders and focus rings, and buttons use a
     darkened step that reads as the same color at 4.6:1. */
  --brand:     #FD7008;
  --brand-600: #E06106;
  --brand-700: #C4530A;   /* button fill, white text */
  --brand-800: #9E430A;
  --brand-100: #FBDCC2;
  --brand-50:  #FEF1E6;

  /* Status — deliberately kept clear of the brand orange. Warnings moved to a
     yellower gold so "needs attention" never reads as "click me". */
  --ok-700:   #1B6B43;  --ok-50:   #E4F1E9;
  --warn-700: #8A6A00;  --warn-50: #FBF3D6;
  --bad-700:  #A32A22;  --bad-50:  #FAE8E5;
  --idle-700: #5C5045;  --idle-50: #F0EDE9;

  /* Neutral info — a muted slate, clear of both the brand and the warnings */
  --info-700: #3F5A63;  --info-50: #EAF0F2;

  --radius:    5px;
  --radius-lg: 8px;
  --shadow:    0 1px 2px rgba(22, 18, 14, .06), 0 1px 1px rgba(22, 18, 14, .04);
  --shadow-lg: 0 8px 24px rgba(22, 18, 14, .10), 0 2px 6px rgba(22, 18, 14, .06);

  --font:  'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono:  'IBM Plex Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;

  --nav-w: 216px;
  --bar-h: 52px;
}

* { box-sizing: border-box; }

/* Bigger on big screens.
   Every type size here is a fixed pixel value — 350 of them, and 102 more
   inline in the pages — so scaling the type means scaling the page. Browser
   zoom would do it, but each person would have to set it themselves.

   Zoom has one trap: it enlarges everything without telling the layout the
   screen got smaller, so a rule meant for a wide screen can fire with less
   room than it assumes. The largest breakpoint here is 1,080px, and these
   steps never let the usable width fall below it — 1,280 / 1.15 is 1,113,
   and 1,600 / 1.3 is 1,231 — so no layout rule ever fires at the wrong size.

   Screens only: print and email keep their own sizes, and phones are left
   alone. Anything sized in viewport height is divided by the same factor,
   because zoom enlarges those too and the nav would otherwise run off the
   bottom of the screen. */
:root { --zoom: 1; }
@media screen and (min-width: 1280px) { :root { --zoom: 1.15; } }
@media screen and (min-width: 1600px) { :root { --zoom: 1.3; } }
html { zoom: var(--zoom); }

html, body {
  margin: 0; padding: 0;
  background: var(--canvas);
  color: var(--ink-800);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand-700); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 2px solid var(--brand-600);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Numbers everywhere are mono + tabular so columns align on scan. */
.num, td.num, .money, .stat-value, code, kbd {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum';
}

/* ------------------------------------------------------------------ mark */
/* The room-block grid: rooms across, nights down. The product in miniature. */
.mark { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; width: 22px; }
.mark i { display: block; aspect-ratio: 1; background: var(--brand-100); border-radius: 1px; }
.mark i.on { background: var(--brand-600); }
.mark.lg { width: 34px; gap: 3px; }

/* ------------------------------------------------------------------ shell */
.shell { display: grid; grid-template-columns: var(--nav-w) 1fr;
         min-height: calc(100vh / var(--zoom)); }

.nav {
  background: var(--ink-900);
  color: #fff;
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: calc(100vh / var(--zoom));
}

.nav-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 16px 18px;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.nav-brand .wordmark {
  font-weight: 800; font-size: 15px; letter-spacing: -.02em; color: #fff;
}
.nav-brand .wordmark span { color: var(--brand-100); font-weight: 500; }
.nav-brand .mark i { background: rgba(255,255,255,.18); }
.nav-brand .mark i.on { background: var(--brand-100); }

.nav-group { padding: 14px 0 4px; }
.nav-group h6 {
  margin: 0 0 6px; padding: 0 18px;
  font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-300);
}
.nav a.nav-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 7px 18px;
  color: rgba(255,255,255,.72);
  font-size: 13.5px; font-weight: 500;
  border-left: 2px solid transparent;
}
.nav a.nav-item:hover { background: rgba(255,255,255,.05); color: #fff; text-decoration: none; }
.nav a.nav-item.active {
  background: rgba(255,255,255,.07); color: #fff;
  border-left-color: var(--brand-600);
}
.nav-item .count {
  font-family: var(--mono); font-size: 11px;
  background: rgba(255,255,255,.12); color: rgba(255,255,255,.85);
  padding: 1px 6px; border-radius: 8px;
}
.nav-item .count.warn { background: var(--warn-700); color: #fff; }

.nav-foot {
  margin-top: auto; padding: 14px 18px;
  border-top: 1px solid rgba(255,255,255,.08);
  font-size: 11.5px; color: var(--ink-300);
}

/* ------------------------------------------------------------------- bar */
.main { min-width: 0; display: flex; flex-direction: column; }

.topbar {
  height: var(--bar-h);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 14px;
  padding: 0 22px;
  position: sticky; top: 0; z-index: 20;
}
.crumbs { font-size: 13px; color: var(--ink-400); display: flex; gap: 7px; align-items: center; }
.crumbs b { color: var(--ink-800); font-weight: 600; }
.topbar .spacer { flex: 1; }

/* Dev-only identity switcher. Real auth replaces this. */
.roleswitch {
  display: flex; align-items: center; gap: 8px;
  background: var(--warn-50); border: 1px solid #DFCE8C;
  border-radius: var(--radius); padding: 3px 4px 3px 10px;
}
.roleswitch label {
  font-size: 10px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--warn-700);
}
.roleswitch select {
  font-family: var(--font); font-size: 12.5px; font-weight: 600;
  border: 1px solid #E0BE7E; border-radius: 4px; background: #fff;
  padding: 3px 6px; color: var(--ink-800);
}

/* -------------------------------------------------------------- content */
.page { padding: 22px; max-width: 1500px; width: 100%; }

.page-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.page-head .spacer { flex: 1; }
.page-title {
  margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -.02em; color: var(--ink-900);
}
.page-sub { margin: 3px 0 0; color: var(--ink-400); font-size: 13px; }

.eyebrow {
  font-size: 10px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-300);
}

/* ------------------------------------------------------------------ card */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
}
.card + .card { margin-top: 16px; }
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-soft);
}
.card-head h3 { margin: 0; font-size: 14px; font-weight: 700; letter-spacing: -.01em; }
.card-head .spacer { flex: 1; }
.card-body { padding: 16px; }
.card-body.flush { padding: 0; }
.card-foot {
  padding: 10px 16px; border-top: 1px solid var(--line-soft);
  background: var(--surface-2);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  font-size: 12.5px; color: var(--ink-400);
}

.grid { display: grid; gap: 16px; }
.grid.c2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.grid.c3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.grid.c4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
/* Five states on the rentals page. All of them are ours: nothing arrives to
   move a rental along. */
.grid.c5 { grid-template-columns: repeat(5, minmax(0,1fr)); }
.grid.main-side { grid-template-columns: minmax(0,1fr) 320px; align-items: start; }

/* ------------------------------------------------------------------ stat */
.stat { padding: 14px 16px; }
.stat .stat-label {
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-300); margin-bottom: 6px;
}
.stat .stat-value { font-size: 25px; font-weight: 600; letter-spacing: -.02em; color: var(--ink-900); }
.stat .stat-note { font-size: 12px; color: var(--ink-400); margin-top: 3px; }
.stat.alert { border-left: 3px solid var(--warn-700); }
.stat.alert .stat-value { color: var(--warn-700); }
.stat.bad { border-left: 3px solid var(--bad-700); }
.stat.bad .stat-value { color: var(--bad-700); }

/* ----------------------------------------------------------------- table */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data th {
  text-align: left; padding: 9px 14px;
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-400); background: var(--surface-2);
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
table.data td { padding: 10px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
table.data tbody tr:hover { background: var(--brand-50); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num { text-align: right; }
table.data .primary { font-weight: 600; color: var(--ink-900); }
/* The same name, without being a link. A school super user reaches a coach's
   travel by working as them, so the name is a label — it should still read as
   the row's subject rather than dropping to body text. */
table.data .rostername { font-weight: 600; color: var(--ink-900); }
table.data .muted { color: var(--ink-400); font-size: 12.5px; }

/* ----------------------------------------------------------------- chips */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 20px;
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
  border: 1px solid transparent;
}
.chip .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.chip.ok   { background: var(--ok-50);   color: var(--ok-700);   border-color: #BFDFCC; }
.chip.warn { background: var(--warn-50); color: var(--warn-700); border-color: #DFCE8C; }
.chip.bad  { background: var(--bad-50);  color: var(--bad-700);  border-color: #EFC4BE; }
.chip.idle { background: var(--idle-50); color: var(--idle-700); border-color: var(--line); }
.chip.info { background: var(--info-50); color: var(--info-700); border-color: #C9D6DA; }

.tag {
  display: inline-block; padding: 1px 6px; border-radius: 3px;
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: 11px; font-weight: 600; color: var(--ink-500);
}

/* Contact-health strip: one cell per contact, colored by send eligibility.
   Reads as a miniature room block, which is the point. */
.health { display: inline-flex; gap: 2px; vertical-align: middle; }
.health i { width: 7px; height: 14px; border-radius: 1.5px; background: var(--line); display: block; }
.health i.ok    { background: var(--ok-700); }
.health i.warn  { background: var(--warn-700); }
.health i.bad   { background: var(--bad-700); }
.health i.alias { background: repeating-linear-gradient(45deg, var(--bad-700) 0 2px, #fff 2px 4px); }

/* --------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: var(--radius);
  font-family: var(--font); font-size: 13px; font-weight: 600;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-800);
  cursor: pointer; white-space: nowrap;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn.primary { background: var(--brand-700); border-color: var(--brand-800); color: #fff; }
.btn.primary:hover { background: var(--brand-800); }
.btn.danger { background: var(--bad-700); border-color: var(--bad-700); color: #fff; }
.btn.sm { padding: 4px 9px; font-size: 12px; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

/* ----------------------------------------------------------------- forms */
.field { margin-bottom: 14px; }
.field label {
  display: block; margin-bottom: 5px;
  font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-500);
}
.field .hint { font-size: 12px; color: var(--ink-400); margin-top: 4px; font-weight: 400; }
/* `password` was missing, so every password field in the app — sign in,
   reset, change password, sign up — rendered as the browser's own square
   box at its own width beside properly styled fields. */
input[type=text], input[type=date], input[type=number], input[type=email],
input[type=password], input[type=search], input[type=tel],
input[type=time], input[type=url], input[type=datetime-local],
select, textarea {
  width: 100%; padding: 7px 10px;
  border: 1px solid var(--line); border-radius: var(--radius);
  font-family: var(--font); font-size: 13.5px; color: var(--ink-800); background: #fff;
}
input.num, input[type=number] { font-family: var(--mono); font-variant-numeric: tabular-nums; }
input:focus, select:focus, textarea:focus { border-color: var(--brand-600); outline: none;
  box-shadow: 0 0 0 3px var(--brand-50); }
.field-row { display: flex; gap: 12px; }
.field-row > * { flex: 1; }

.filters {
  display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap;
  padding: 14px 16px; border-bottom: 1px solid var(--line-soft); background: var(--surface-2);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.filters .field { margin: 0; min-width: 130px; }
.filters .grow { flex: 1; min-width: 220px; }

/* ------------------------------------------------------- room block grid */
/* Rooms across, nights down — the actual shape of a team travel block. */
.blockgrid { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.blockgrid table { width: 100%; border-collapse: collapse; }
.blockgrid th {
  background: var(--ink-900); color: #fff;
  font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: 8px 10px; text-align: center;
}
.blockgrid th:first-child { text-align: left; }
.blockgrid td { border: 1px solid var(--line-soft); padding: 0; text-align: center; }
.blockgrid td:first-child {
  text-align: left; padding: 8px 10px; background: var(--surface-2);
  font-family: var(--mono); font-size: 12px; white-space: nowrap; font-weight: 500;
}
.blockgrid input {
  width: 100%; border: 0; text-align: center; padding: 9px 4px;
  font-family: var(--mono); font-size: 13px; background: transparent;
  -moz-appearance: textfield;
}
.blockgrid input::-webkit-outer-spin-button,
.blockgrid input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.blockgrid input:focus { background: var(--brand-50); box-shadow: inset 0 0 0 2px var(--brand-600); }
.blockgrid input.filled { font-weight: 600; color: var(--ink-900); background: var(--brand-50); }
.blockgrid tfoot td {
  background: var(--ink-800); color: #fff;
  font-family: var(--mono); font-size: 12px; font-weight: 600; padding: 7px 6px;
}
.blockgrid tfoot td:first-child { background: var(--ink-900); }

/* ------------------------------------------------------------------ misc */
.empty { padding: 46px 20px; text-align: center; color: var(--ink-400); }
.empty .mark { margin: 0 auto 14px; opacity: .5; }
.empty h4 { margin: 0 0 5px; font-size: 15px; color: var(--ink-700); font-weight: 700; }
.empty p { margin: 0 0 14px; font-size: 13px; }

.banner {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 11px 14px; border-radius: var(--radius);
  font-size: 13px; margin-bottom: 16px; border: 1px solid;
}
.banner.warn { background: var(--warn-50); border-color: #DFCE8C; color: #5C4700; }
.banner.info { background: var(--info-50); border-color: #C9D6DA; color: var(--info-700); }
.banner.bad  { background: var(--bad-50);  border-color: #EFC4BE; color: #7C1F19; }
.banner b { display: block; margin-bottom: 2px; }

.kv { display: grid; grid-template-columns: 128px 1fr; gap: 7px 14px; font-size: 13px; }
.kv dt { color: var(--ink-400); font-size: 12px; }
.kv dd { margin: 0; color: var(--ink-800); }

.pager { display: flex; align-items: center; gap: 10px; justify-content: flex-end; }
.pager .pos { font-family: var(--mono); font-size: 12px; color: var(--ink-400); }

.rule { height: 1px; background: var(--line-soft); margin: 18px 0; border: 0; }

@media (max-width: 1080px) {
  .grid.c4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .grid.main-side, .grid.c3 { grid-template-columns: minmax(0,1fr); }
}
@media (max-width: 780px) {
  .shell { grid-template-columns: 1fr; }
  .nav { position: static; height: auto; flex-direction: row; overflow-x: auto; align-items: center; }
  .nav-group { display: flex; align-items: center; padding: 6px 0; }
  .nav-group h6 { display: none; }
  .nav-foot { display: none; }
  .grid.c2, .grid.c4 { grid-template-columns: minmax(0,1fr); }
  .page { padding: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ------------------------------------------------------ venue type-ahead */
/* The search anchor for every trip: campus, airport, or city. */
.venue-results { margin-top: 6px; }
.venue-opt {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  padding: 8px 11px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-bottom: 0; font-family: var(--font); font-size: 13.5px;
}
.venue-opt:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.venue-opt:last-child  { border-bottom: 1px solid var(--line-soft);
                         border-radius: 0 0 var(--radius) var(--radius); }
.venue-opt:hover, .venue-opt:focus-visible { background: var(--brand-50); }
.venue-kind {
  flex: 0 0 62px; font-size: 10px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-300);
}
.venue-name { font-weight: 600; color: var(--ink-900); }
.venue-loc  { margin-left: auto; font-family: var(--mono); font-size: 12px; color: var(--ink-400); }
.venue-none { padding: 9px 11px; font-size: 13px; color: var(--ink-400); }
.venue-chosen {
  margin-top: 7px; padding: 6px 10px; border-radius: var(--radius);
  background: var(--brand-50); color: var(--brand-800);
  font-size: 12.5px; font-weight: 600;
}

/* -------------------------------------------------------------- quickbar */
/* Three standing jobs, always one click from the top of the app. */
.quickbar { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; }
.quick {
  display: block; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
  color: var(--ink-800); text-decoration: none;
  border-left: 3px solid var(--brand-600);
}
.quick:hover { background: var(--brand-50); text-decoration: none; border-color: var(--brand-600); }
.quick-mark { display: block; margin-bottom: 9px; }
.quick-label { display: block; font-weight: 700; font-size: 14.5px; letter-spacing: -.01em; }
.quick-note { display: block; font-size: 12.5px; color: var(--ink-400); margin-top: 2px; }
@media (max-width: 1080px) { .quickbar { grid-template-columns: 1fr; } }

/* -------------------------------------------------------- form details */
.req { color: var(--bad-700); font-weight: 700; }

.roomrow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.roomcell label {
  display: block; margin-bottom: 5px;
  font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-500);
}
.roomcell input.roomqty {
  font-family: var(--mono); font-size: 16px; text-align: center;
  font-variant-numeric: tabular-nums; margin-bottom: 6px;
}
.roomcell input.roomqty.filled {
  font-weight: 600; color: var(--ink-900); background: var(--brand-50);
  border-color: var(--brand-100);
}
.roomcell input[type=text] { font-size: 12.5px; }
.roomtotal {
  margin-top: 12px; padding: 9px 13px; border-radius: var(--radius);
  background: var(--ink-900); color: #fff;
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12.5px; font-weight: 600;
}
.roomtotal b { font-family: var(--mono); font-size: 16px; }

.checkrow { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
.check {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13.5px; cursor: pointer; user-select: none;
}
.check input { width: 15px; height: 15px; accent-color: var(--brand-700); cursor: pointer; }

/* --------------------------------------------------- trip header + cards */
.triphead {
  display: flex; align-items: flex-start; gap: 16px; margin-bottom: 14px;
  padding: 16px 18px; background: var(--surface);
  border: 1px solid var(--line); border-left: 3px solid var(--brand-600);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
}
.triphead .page-title { margin: 3px 0 8px; }
.triphead-facts { list-style: none; margin: 0; padding: 0;
  display: flex; gap: 20px; flex-wrap: wrap; font-size: 13px; color: var(--ink-500); }
.triphead-facts li { position: relative; padding-left: 13px; }
.triphead-facts li::before {
  content: ''; position: absolute; left: 0; top: 7px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--brand-600);
}

.selectbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 16px; margin-bottom: 14px;
  background: var(--ink-900); color: #fff;
  border-radius: var(--radius-lg); font-size: 13px;
}
.selectbar b { font-family: var(--mono); font-size: 15px; }
.selectbar .capnote { color: #F0C070; font-weight: 600; }
.radiusform { display: flex; align-items: center; gap: 7px; }
.radiusform label { font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-300); }
.radiusform input { width: 68px; padding: 4px 7px; font-family: var(--mono); font-size: 12.5px; }
.radiusform .muted { color: var(--ink-300); font-size: 12px; }

.hotelcards { display: grid; gap: 12px; }
.hcard {
  display: flex; gap: 18px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 15px 17px; box-shadow: var(--shadow);
}
.hcard.picked { border-color: var(--brand-600); background: var(--brand-50); }
.hcard-main { flex: 1; min-width: 0; }
.hcard-main h3 { margin: 0 0 7px; font-size: 15.5px; letter-spacing: -.01em; }
.hcard-facts { list-style: none; margin: 0; padding: 0; font-size: 13px; color: var(--ink-500); }
.hcard-facts li { margin-bottom: 2px; }
.hcard-facts b { font-family: var(--mono); color: var(--ink-900); }
.hcard-side { flex: 0 0 168px; display: flex; flex-direction: column; gap: 7px; }
.btn.block { width: 100%; justify-content: center; }
.hcard-warn {
  margin-top: 10px; padding: 6px 10px; border-radius: var(--radius);
  background: var(--bad-50); color: var(--bad-700);
  font-size: 12px; font-weight: 600;
}

.amenities { list-style: none; margin: 0; padding: 0; display: flex; gap: 16px; flex-wrap: wrap; }
.amenities li { font-size: 13px; position: relative; padding-left: 19px; }
/* What the team asked for, on the hotel's own page: bigger than the notes
   around it, and marked, because a hotel skimming past this answers the
   wrong questions. */
.wantshead {
  display: inline-block; margin: 0 0 8px;
  background: #FEF08A; color: #713F12;
  padding: 4px 10px; border-radius: var(--radius);
  font-size: 15px; font-weight: 700; letter-spacing: -.01em;
}
.amenities.big { gap: 10px 20px; }
.amenities.big li { font-size: 15px; padding-left: 22px; font-weight: 600; }
.amenities li::before { position: absolute; left: 0; font-weight: 700; }
.amenities li.yes { color: var(--ok-700); }
.amenities li.yes::before { content: '✓'; }
.amenities li.no { color: var(--ink-300); text-decoration: line-through; }
.amenities li.no::before { content: '–'; }
.amenities li.unknown { color: var(--ink-300); }
.amenities li.unknown::before { content: '?'; }

/* ------------------------------------------------------------- done page */
.donecard {
  max-width: 620px; margin: 20px auto; padding: 26px 30px 28px; text-align: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
}
.donecard .mark { margin: 0 auto 18px; }
.donecard h1 { margin: 0 0 7px; font-size: 22px; letter-spacing: -.02em; }
.donecard > p { margin: 0 0 20px; color: var(--ink-500); font-size: 14px; }
.donelist { list-style: none; margin: 0 0 22px; padding: 0; text-align: left; }
.donelist li {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; border: 1px solid var(--line-soft); border-bottom: 0;
  font-size: 13px;
}
/* Name over city and distance, rather than name and city on one line pushed
   to opposite edges — with a brand mark alongside, a row needs a left edge to
   line up on. */
.donelist-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.donelist .logoslot { width: 62px; height: 38px; flex: 0 0 62px; }
.donelist li:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.donelist li:last-child { border-bottom: 1px solid var(--line-soft);
  border-radius: 0 0 var(--radius) var(--radius); }
.donelist li .muted { font-family: var(--mono); font-size: 12px; color: var(--ink-400); }
.doneactions { display: flex; gap: 9px; justify-content: center; flex-wrap: wrap; }
.donetransport { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--line-soft); }
.donetransport > div { display: flex; gap: 9px; justify-content: center;
  flex-wrap: wrap; margin-top: 8px; }
.stub {
  padding: 6px 12px; border-radius: var(--radius);
  border: 1px dashed var(--line); color: var(--ink-300); font-size: 13px;
}
/* Same reasoning as .donelead: a sentence and a half centred over two lines
   reads as crooked. Left in a centred block instead. */
.donetransport .hint {
  margin: 9px auto 0; max-width: 46ch; text-align: left;
}

/* A second hotel at the airport, or a bus on to the next city. Folded, so
   the common path stays one decision. */
.againfold { margin-top: 14px; }
.againfold > summary {
  cursor: pointer; font-size: 12.5px; font-weight: 600;
  color: var(--ink-500); text-align: center;
}
.againfold > div {
  display: flex; gap: 8px; justify-content: center;
  flex-wrap: wrap; margin-top: 10px;
}

@media (max-width: 780px) {
  .roomrow { grid-template-columns: 1fr; }
  .hcard { flex-direction: column; }
  .hcard-side { flex: 1 1 auto; flex-direction: row; }
}

/* --------------------------------------------------------- hotel portal */
.portal { max-width: 1020px; margin: 0 auto; padding: 22px 18px 60px; }
.portal-head {
  display: flex; align-items: center; gap: 12px; margin-bottom: 18px;
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.portal-head .spacer { flex: 1; }
.rfpno {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  color: var(--ink-400); letter-spacing: .04em;
}
.banner.ok-banner { background: var(--ok-50); border: 1px solid #BFDFCC; color: var(--ok-700); }

.roomlist { list-style: none; margin: 0; padding: 0; display: flex; gap: 26px; flex-wrap: wrap; }
.roomlist li { font-size: 13.5px; }
.roomlist b { font-family: var(--mono); font-size: 16px; color: var(--ink-900); }
.roomlist span { display: block; font-size: 12px; color: var(--ink-400); }

@media (max-width: 780px) { .portal { padding: 14px 12px 40px; } }

/* ------------------------------------------------- invitation cards */
.invcard {
  display: flex; gap: 16px; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  margin-bottom: 10px; background: var(--surface);
}
.invcard.declined { background: var(--surface-2); opacity: .82; }
.invcard-main { flex: 1; min-width: 0; }
.invcard-main h4 { margin: 0 0 3px; font-size: 15px; letter-spacing: -.01em; }
.invcard-addr { font-size: 12.5px; color: var(--ink-400); margin-bottom: 8px; }
.invcard-status { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12.5px; margin-bottom: 9px; }
.invcard-contact {
  font-size: 12.5px; padding: 8px 11px; background: var(--surface-2);
  border-radius: var(--radius); border: 1px solid var(--line-soft);
}
.invcard-contact .num { font-size: 12px; color: var(--ink-500); }
.invcard-nocontact { color: var(--bad-700); font-weight: 600; }
/* 158px cramped "Change contact" and "Also try Skyylee" onto two lines
   each, which is what made the column read as jammed however the buttons
   inside it were styled. Roughly three-quarters of an inch wider. */
.invcard-side { flex: 0 0 230px; display: flex; flex-direction: column; gap: 6px; }

.bidsummary { margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--line-soft); }
.bidrate { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 9px; }
.bidrate b { font-family: var(--mono); font-size: 19px; color: var(--ink-900); }
.bidrate b.second { font-size: 15px; color: var(--ink-500); }
.bidrate span { font-size: 12px; color: var(--ink-400); }
.bidrate .tax { font-family: var(--mono); }
.bidterms { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr);
  /* Each answer names its column, so a conditional one — late checkout,
     asked only where the team wanted it — cannot push everything below it
     into the other side. */
  grid-auto-flow: row dense;
  gap: 3px 22px; font-size: 12.5px; }
.bidterms li.col1 { grid-column: 1; }
.bidterms li.col2 { grid-column: 2; }
/* The label on the left, everything else stacked to the right of it.
   A plain flex row made each qualifier its own column, so "Property allows
   you to bring in your own food — $50.00 cleanup fee" came out as a strip
   six words tall beside a breakfast note doing the same thing. */
.bidterms li { display: grid; grid-template-columns: 106px 1fr; gap: 2px 7px; }
.bidterms li > span:first-child {
  grid-row: 1 / -1;
  font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-300); padding-top: 2px;
}
.bidnotes { margin-top: 9px; font-size: 12.5px; color: var(--ink-500); font-style: italic; }

.subform {
  padding: 14px 16px; margin: -4px 0 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-top: 0; border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.subform .field { margin-bottom: 10px; }
.subform .field-row { flex-wrap: wrap; }
.subform .field-row > * { min-width: 130px; }

@media (max-width: 780px) {
  .invcard { flex-direction: column; }
  .invcard-side { flex-direction: row; flex-wrap: wrap; }
  .bidterms { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------- identity */
/* A name in a corner does not look like a link, so this one is given the
   affordances of one: a border that appears on hover and a label that says
   what is behind it. */
.whoami {
  display: flex; flex-direction: column; line-height: 1.25; text-align: right;
  padding: 5px 10px; border: 1px solid transparent; border-radius: 7px;
  text-decoration: none;
}
.whoami:hover { border-color: var(--line); background: var(--surface-2); }
.whoami:hover .whoami-role { color: var(--brand-700); }
.whoami-name { font-size: 13px; font-weight: 600; color: var(--ink-800); }
.whoami-role { font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-300); }

/* Impersonation has to be impossible to miss — acting as someone else without
   realising it is how mistakes get attributed to the wrong person. */
.imp-banner {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 12px; border-radius: var(--radius);
  background: var(--warn-700); color: #fff; font-size: 12.5px;
}
.imp-banner a { color: #fff; text-decoration: underline; font-weight: 600; }

/* -------------------------------------------------------------- sign in */
.signin-body { display: flex; align-items: center; justify-content: center;
  min-height: calc(100vh / var(--zoom)); background: var(--canvas); }
.signin { width: 100%; max-width: 380px; padding: 20px; }
.signin-note { margin-top: 18px; text-align: center; font-size: 12.5px;
  color: var(--ink-400); }
.signin-alt { margin-top: 16px; text-align: center; font-size: 13.5px;
  color: var(--ink-500); }
.signin-head { margin: 0 0 16px; font-size: 16px; letter-spacing: -.01em; }

/* ==========================================================================
   The front door.

   Two audiences on one page: a coach who visits weekly and wants the password
   field, and somebody who has never heard of us. The card is first in the
   markup so the returning coach never scrolls past a pitch to reach it, and
   the pitch sits alongside on anything wide enough to hold both.
   ========================================================================== */

.signin-body.split { align-items: stretch; }
.signin-split {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(340px, 420px);
  gap: 60px;
  align-items: center;
  width: 100%;
  max-width: 1060px;
  margin: 0 auto;
  padding: 40px 28px;
}
.signin-split .signin { max-width: none; padding: 0; }
/* The card is first in the markup — reading order matters more than column
   order — so the pitch is moved left rather than the card being moved right. */
.signin-split .pitch { order: -1; }

.pitch .brandlogo { height: 38px; margin: 0 0 26px; }
.pitch-since {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--brand-700);
}
.pitch-head {
  margin: 0 0 14px;
  font-size: 34px;
  line-height: 1.15;
  letter-spacing: -.022em;
  font-weight: 600;
}
.pitch-lead {
  margin: 0 0 30px;
  max-width: 44ch;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-500);
}
.pitch-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 15px; }
.pitch-list li { display: flex; align-items: flex-start; gap: 12px; }
.pitch-list .svcicon { color: var(--brand); flex: 0 0 auto; }
.pitch-list span { display: flex; flex-direction: column; gap: 2px; }
.pitch-list b { font-size: 14px; }
.pitch-list .muted { font-size: 13px; line-height: 1.45; }

/* One column, card first. Somebody signing in on a phone at an airport is not
   here to read the pitch. */
@media (max-width: 900px) {
  .signin-split {
    grid-template-columns: 1fr;
    gap: 34px;
    padding: 28px 20px;
    max-width: 460px;
  }
  /* The comment above said card first, and the pitch's `order: -1` from
     the wide layout was never undone — so a coach on a phone scrolled past
     the marketing to find the password box. */
  .signin-split .pitch { order: 0; }
  .pitch { text-align: center; }
  .pitch .brandlogo { margin: 0 auto 18px; }
  .pitch-head { font-size: 26px; }
  .pitch-lead { margin-left: auto; margin-right: auto; }
  .pitch-list { text-align: left; max-width: 340px; margin: 0 auto; }
}

.linkrow { display: flex; gap: 6px; }
.linkrow .btn { flex: 1; justify-content: center; }

.raterange { font-size: 14px; }
.raterange b { font-family: var(--mono); font-size: 17px; color: var(--ink-900); }
.raterange span { color: var(--ink-400); font-size: 12.5px; }
a.whoami { text-decoration: none; }
a.whoami:hover .whoami-name { color: var(--brand-700); }

.escalate-note {
  font-size: 11.5px; color: var(--warn-700); background: var(--warn-50);
  border: 1px solid #DFCE8C; border-radius: var(--radius); padding: 6px 9px;
  line-height: 1.4;
}

.staticmap {
  display: block; width: 100%; max-width: 560px; margin-top: 10px;
  border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.photogrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.photocell { border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden;
  background: var(--surface-2); }
.photocell img { display: block; width: 100%; aspect-ratio: 4/3; object-fit: cover; }
.photocell.primary { border-color: var(--brand-600); box-shadow: 0 0 0 2px var(--brand-50); }
.photocell-foot { display: flex; gap: 6px; padding: 8px; align-items: center; }
.photocell-foot .tag { margin-right: auto; }
.photo-empty {
  border: 1px dashed var(--line); border-radius: var(--radius-lg);
  aspect-ratio: 4/3; display: flex; align-items: center; justify-content: center;
  color: var(--ink-300); font-size: 12.5px; text-align: center; padding: 12px;
}
@media (max-width: 780px) { .photogrid { grid-template-columns: 1fr 1fr; } }

.hotelphoto { display: block; width: 100%; aspect-ratio: 16/9; object-fit: cover;
  border-bottom: 1px solid var(--line-soft); }

/* ------------------------------------------- hotels added after the send */
/* Gold tint so a manager can tell at a glance which properties joined late.
   The pulse runs for 8 seconds and stops — a permanently animating row is
   just noise after the first look. */
.invcard.added-later {
  border-color: #D9C77A;
  background: linear-gradient(0deg, var(--warn-50), var(--warn-50));
  animation: added-pulse 1.6s ease-in-out 5;
}
@keyframes added-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(217, 199, 122, 0); }
  50%      { box-shadow: 0 0 0 5px rgba(217, 199, 122, .55); }
}
@media (prefers-reduced-motion: reduce) {
  .invcard.added-later { animation: none; }
}
.added-flag {
  display: inline-block; margin-bottom: 7px; padding: 2px 8px;
  border-radius: 20px; background: var(--warn-700); color: #fff;
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}

/* ------------------------------------------------------ coach rate block */
/* The rate is the one number a coach is looking for, so it gets its own box
   rather than sitting in a table cell. */
.coach-side { flex: 0 0 210px; }
/* Egg white with black on it. This was a dark box with white text, and
   setting the number to near-black put dark on dark — the rate disappeared
   entirely. */
.ratebox {
  display: flex; flex-direction: column; gap: 1px;
  padding: 12px 14px; border-radius: var(--radius-lg);
  background: #FAF7F0; color: #111;
  border: 1px solid var(--line);
  margin-bottom: 4px;
}
.ratebox.pending { background: var(--surface-2); color: var(--ink-500);
  border: 1px solid var(--line); }
.ratebox-label {
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  /* Readable on the light box. --ink-300 was chosen against a dark one. */
  text-transform: uppercase; color: #111;
}
.ratebox-value {
  /* Dark and large rather than orange. The rate is the number a coach reads
     calmly and compares; an attention colour on every card competes with the
     button underneath and stops meaning anything. */
  font-family: var(--mono); font-size: 22px; font-weight: 600;
  letter-spacing: -.02em; line-height: 1.15;
  /* Sized down and allowed to wrap rather than tuned to today's number: a
     week of two coaches is five figures and ran out of the box at 27px. */
  overflow-wrap: anywhere;
}
.ratebox.pending .ratebox-value { color: var(--ink-300); }
/* All of these were picked against a dark box. On egg white they were pale
   grey on cream — technically present, unreadable in practice. */
.ratebox-note { font-size: 11.5px; color: #111; }
.ratebox-second {
  font-family: var(--mono); font-size: 13px; color: #111; margin-top: 3px;
}
@media (max-width: 780px) { .coach-side { flex: 1 1 auto; } }


/* Cancel sits beside a primary action and should read as the quiet option. */
.btn.muted {
  background: transparent; border-color: var(--line); color: var(--ink-400);
}
.btn.muted:hover { background: var(--surface-2); color: var(--ink-700); }

/* Form footer where the primary action is the point of the page. */
.form-actions {
  display: flex; gap: 12px; align-items: center; justify-content: center;
  padding: 18px 16px;
}
.form-actions .btn { min-width: 150px; justify-content: center; }
.form-actions .btn.primary { min-width: 200px; padding: 11px 22px; font-size: 14px; }

/* --------------------------------------------------------- form pages */
.formpage { max-width: 720px; }
.card.accent { border-left: 3px solid var(--brand); }
input.lg { font-size: 15px; padding: 10px 12px; }
.roomrow .roomcell input.roomqty { margin-bottom: 0; }

.subquestion {
  margin-top: 12px; padding: 11px 13px;
  background: var(--brand-50); border: 1px solid var(--brand-100);
  border-radius: var(--radius);
}
.subquestion-q { font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--ink-800); }
.invcard-dist { font-size: 12.5px; color: var(--ink-500); margin-bottom: 8px; }
.invcard-dist b { font-family: var(--mono); color: var(--ink-900); }

/* The hotel the coach picked. Green rather than brand orange — this is a
   confirmation, not an action. */
.invcard.chosen {
  border: 2px solid var(--ok-700);
  background: var(--ok-50);
}
.chosen-flag {
  display: inline-block; margin-bottom: 7px; padding: 2px 9px;
  border-radius: 20px; background: var(--ok-700); color: #fff;
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}

/* ------------------------------------------------------------ view filter */
/* Deliberately loud when active. A manager who forgets a filter is set will
   assume a missing trip means the app is broken, so it never hides. */
.filterbar { display: flex; align-items: center; gap: 8px; }
.filterbar select {
  font-size: 12.5px; padding: 4px 7px; max-width: 190px;
  border-color: var(--line); color: var(--ink-500);
}
.filterbar.on {
  padding: 5px 8px 5px 12px; border-radius: var(--radius);
  background: var(--info-700); color: #fff;
}
.filterbar.on b { font-size: 13px; }
.filterbar-label {
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; opacity: .75;
}
.filterbar-clear {
  color: #fff; text-decoration: underline; font-size: 12px; font-weight: 600;
  padding-left: 4px;
}
.filterbar-clear:hover { color: #fff; }
@media (max-width: 980px) { .filterbar select { max-width: 120px; } }

/* The reference a hotel reads down the phone. Mono, high contrast, easy to
   say aloud — "S H one zero four two". */
.rfpref, .refchip {
  font-family: var(--mono); font-size: 12.5px; font-weight: 600;
  letter-spacing: .04em; color: var(--brand-800);
  background: var(--brand-50); border: 1px solid var(--brand-100);
  padding: 2px 8px; border-radius: var(--radius);
}
.rfpref { font-size: 14px; }
.refchip { margin-right: 6px; text-transform: none; }

/* ---------------------------------------------------------- hotel bid page */
.rfp-intro {
  margin: 0 0 14px; padding: 11px 14px; border-radius: var(--radius);
  background: var(--brand-50); border: 1px solid var(--brand-100);
  font-size: 13.5px; line-height: 1.55; color: var(--ink-700);
}
.roomlist li.roomnights { font-size: 13.5px; color: var(--ink-500); }
.roomlist li.roomnights b { color: var(--brand-800); }

/* A field the team specifically asked about — it shouldn't read as just
   another dropdown in the stack. */
.field.highlight {
  padding: 11px 13px; margin-left: -13px; margin-right: -13px;
  background: var(--brand-50); border-left: 3px solid var(--brand);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.asked {
  font-size: 12.5px; color: var(--brand-800); margin-bottom: 7px;
}
.asked b { font-family: var(--mono); }

.commission {
  margin-top: 16px; padding: 13px 15px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line);
}
.pctwrap { display: flex; align-items: center; gap: 6px; }
.pctwrap input { text-align: right; }
.pctwrap span { font-family: var(--mono); color: var(--ink-500); }

/* Commission is the business arrangement, not part of the stay — it never
   renders for a coach, and it reads differently when it does. */
.bidterms li.commission-line { color: var(--info-700); font-weight: 600; }

.invcard-phone {
  font-family: var(--mono); font-size: 12.5px; color: var(--ink-500);
  margin: -4px 0 8px;
}

/* A coach should always know who's working for them, without it competing
   with the page. */
.mymanager {
  display: flex; flex-direction: column; gap: 1px; text-align: right;
  margin-right: 14px; line-height: 1.35;
}
.mymanager-label {
  font-size: 9.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-300);
}
.mymanager b { font-size: 12.5px; }
.mymanager a, .mymanager span { font-family: var(--mono); font-size: 11.5px;
  color: var(--ink-400); }
@media (max-width: 780px) { .mymanager { display: none; } }

/* The three facts a hotel checks first. Labelled, because an unlabelled list
   of a date range, a place and a sport takes a second to parse. */
.tripfacts { display: grid; grid-template-columns: 150px 1fr; gap: 9px 16px;
  margin: 0 0 16px; }
.tripfacts dt {
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-300); padding-top: 2px;
}
.tripfacts dd { margin: 0; font-size: 14px; font-weight: 600; color: var(--ink-900); }
.tripfacts dd span { display: block; font-size: 12.5px; font-weight: 400;
  color: var(--ink-400); }
@media (max-width: 620px) { .tripfacts { grid-template-columns: 1fr; gap: 3px 0; }
  .tripfacts dd { margin-bottom: 9px; } }

/* One asset, two variants — the wordmark is charcoal, which vanishes on the
   dark sidebar, so that surface gets the light version. */
.brandlogo { display: block; height: 30px; width: auto; }
.nav-brand .brandlogo { height: 26px; }
.signin .brandlogo, .portal-head .brandlogo { height: 34px; }
/* A third of what it was. The mark was the biggest thing on a page whose
   job is to say "that arrived" — the heading should carry that, not the
   logo. */
.donecard .brandlogo { height: 22px; opacity: .9; }
.signin .brandlogo { margin: 0 auto 4px; }

/* Something arrived while you were looking. Says so, changes nothing until
   you ask it to. */
/* `display: flex` on the class beats the plain [hidden] attribute, so the bar
   would sit there empty on every page load. Say it explicitly. */
.pulsebar[hidden] { display: none; }
.pulsebar {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px; margin-bottom: 14px;
  background: var(--ok-700); color: #fff;
  border-radius: var(--radius-lg); font-size: 13.5px; font-weight: 600;
}
.pulsebar button {
  background: #fff; color: var(--ok-700); border: 0;
  padding: 4px 12px; border-radius: var(--radius);
  font-family: var(--font); font-size: 12.5px; font-weight: 700; cursor: pointer;
}
.pulsebar button.pulse-dismiss {
  background: transparent; color: #fff; text-decoration: underline;
  padding: 4px 2px; font-weight: 500;
}

/* A full date is 16 characters; a range wrapped mid-word across five lines is
   unreadable. Stack the two dates instead. */
td.nowrap, th.nowrap { white-space: nowrap; }
td.nowrap { line-height: 1.4; font-size: 12px; }

/* Google requires the credit when their photos are displayed. */
.photo-credit {
  position: absolute; bottom: 42px; left: 0; right: 0;
  padding: 4px 8px; font-size: 10px; color: #fff;
  background: linear-gradient(transparent, rgba(0,0,0,.6));
  text-align: right;
}
.photo-credit.inline {
  position: static; background: none; color: var(--ink-300);
  padding: 5px 16px 0; text-align: right; font-size: 10.5px;
}
.photocell { position: relative; }

/* ------------------------------------------------- photos on hotel cards */
/* A coach choosing between seven properties is doing it visually. Fixed
   dimensions so a card with a photo and one without are the same height —
   a ragged column reads as broken rather than incomplete. */
.hcard-photo {
  position: relative; flex: 0 0 168px; width: 168px; height: 112px;
  border-radius: var(--radius); overflow: hidden;
  background: var(--surface-2); align-self: flex-start;
}
.hcard-photo img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  position: absolute; inset: 0;   /* sits over the placeholder beneath it */
}
.hcard-credit {
  position: absolute; right: 5px; bottom: 4px;
  font-size: 9px; color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.9);
  max-width: 88%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hcard-nophoto {
  position: absolute; inset: 0; width: 100%; height: 100%; display: flex; align-items: center;
  justify-content: center; color: var(--ink-300); font-size: 11.5px;
  font-weight: 600; text-align: center; padding: 0 10px; line-height: 1.3;
  background: repeating-linear-gradient(45deg, var(--surface-2),
    var(--surface-2) 9px, #F4F1ED 9px, #F4F1ED 18px);
}
@media (max-width: 620px) {
  .hcard-photo { flex-basis: 104px; width: 104px; height: 74px; }
}
/* Reserved whether or not there is an image. Floating the photo meant a
   hotel without one had its text 104px further left than the card above. */
.invcard-photoslot {
  flex: 0 0 92px;
  width: 92px; height: 68px;
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
}
.invcard-photo {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
@media (max-width: 620px) {
  .invcard-photoslot { flex-basis: 68px; width: 68px; height: 52px; }
}

/* A pasted row that needs a human eye before it lands. */
tr.flagged td { background: var(--warn-50); }
tr.flagged td:first-child { box-shadow: inset 3px 0 0 var(--warn-700); }
ol.plainlist { margin: 0; padding-left: 20px; font-size: 13.5px; line-height: 1.7;
  color: var(--ink-500); }
ol.plainlist b { color: var(--ink-800); }

/* Stored contract language, on the hotel-facing contract page and in the
   manager's preview. Set apart from the surrounding prose because it is the
   part a hotel's legal team will actually read twice. */
.clause {
  border-left: 3px solid var(--line);
  padding: 2px 0 2px 12px;
  margin: 0 0 14px;
}
.clause h4 {
  margin: 0 0 4px;
  font-size: 13px;
  letter-spacing: .01em;
}
.clause p {
  margin: 0;
  font-size: 13px;
  line-height: 1.65;
  color: var(--ink-500);
  white-space: pre-wrap;
}

/* The bid deadline, in the Trip details card head.

   Two weights on purpose. Far out it is a fact; inside four days — or inside
   a fortnight of check-in — it is a nudge, and only then does it move. An
   animated badge on a date two weeks away says urgent while the number says
   relax, and the number is the part they remember. */
.duebadge {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-500);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 11px;
  white-space: nowrap;
}
.duebadge b { font-weight: 700; color: var(--ink-700); }

.duebadge.urgent {
  color: #5C4700;
  background: var(--warn-50);
  border-color: #DFCE8C;
  animation: duepulse 1s ease-in-out 3;
}
.duebadge.urgent b { color: #5C4700; }

@keyframes duepulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(223, 206, 140, 0); }
  50%      { box-shadow: 0 0 0 5px rgba(223, 206, 140, .55); }
}

/* Someone who has asked their OS to stop animations gets the color and none
   of the movement. The badge still reads as urgent. */
@media (prefers-reduced-motion: reduce) {
  .duebadge.urgent { animation: none; }
}

/* Why answering now is worth something, in a sentence that is true: rates are
   reviewed as they arrive, so an early one reaches the team earlier. */
.rfp-nudge {
  margin: 0 0 14px;
  padding: 9px 12px;
  background: var(--ok-50);
  border-left: 3px solid var(--ok-700);
  border-radius: 4px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ok-700);
}

/* The action boxes are links now — each one opens the queue it counts, which
   is the whole reason it earns space. Anchors inherit link color and
   underline by default, so they need saying otherwise. */
a.card.stat {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color .12s ease, transform .12s ease;
}
a.card.stat:hover {
  border-color: var(--ink-400);
  transform: translateY(-1px);
}
a.card.stat:focus-visible {
  outline: 2px solid var(--brand-700);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  a.card.stat { transition: none; }
  a.card.stat:hover { transform: none; }
}

/* A form button that has to read as a link — used where an action sits inside
   a sentence, like "work as them" in the super user's banner. A real anchor
   can't POST, and impersonation must not be reachable by a GET. */
.linkbtn {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--brand-700);
  text-decoration: underline;
  cursor: pointer;
}
.linkbtn:hover { color: var(--ink-900); }

/* A released coach quote on the coach's own page. One row, one price, one
   button — they are choosing, not auditing, so the vendor's breakdown stays
   on the manager's side. */
.quoterow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 0;
  border-top: 1px solid var(--line-soft);
}
.quoterow:first-of-type { border-top: 0; }
.quoterow .ratebox-value { font-size: 19px; font-weight: 600; }

/* The day-by-day movements on the vendor page. Monospace and preserved
   whitespace because it is a schedule — a dispatcher reads down the day
   numbers, and reflowing it into a paragraph destroys that. */
.specblock {
  margin: 0;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  font: 13px/1.7 ui-monospace, Menlo, Consolas, monospace;
  white-space: pre-wrap;
  overflow-x: auto;
}

/* The spec a coach's prices were quoted against. Collapsed by default — the
   numbers are the decision, the movements are the check. */
.specfold {
  margin: 0 0 18px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
}
.specfold > summary {
  padding: 10px 14px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-700);
  list-style: none;
}
.specfold > summary::-webkit-details-marker { display: none; }
.specfold > summary::before {
  content: '▸ ';
  color: var(--ink-400);
}
.specfold[open] > summary::before { content: '▾ '; }
.specfold > summary:hover { color: var(--ink-900); }
.specfold .specblock {
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0 0 6px 6px;
  background: transparent;
}

/* The vendor the coach picked, on the manager's sourcing page. Green from the
   moment it is chosen and still green once confirmed — the point is spotting
   it at a glance while scanning six of them. */
.vendorpicked {
  background: var(--ok-50);
  border-left: 3px solid var(--ok-700);
  border-radius: 6px;
  padding-left: 13px !important;
  padding-right: 13px;
  margin: 4px 0;
}

/* The show-more control under a folded table. Full width and quiet — it is a
   way back to the rest of the list, not an action competing with the rows. */
.foldmore {
  display: block;
  width: 100%;
  border: 0;
  border-top: 1px solid var(--line-soft);
  border-radius: 0 0 8px 8px;
  background: var(--surface-2);
  color: var(--ink-500);
  padding: 10px;
  text-align: center;
}
.foldmore:hover { background: var(--line-soft); color: var(--ink-900); }

/* A flight a coach is choosing between. Departure time first and largest,
   because that is the decision — a team cannot land at 11pm before a noon
   game, and the fare is the second question. */
.flightpick {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  margin-bottom: 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
}
.flightpick:hover { border-color: var(--ink-400); }
/* Settled: no radio inside it and nothing to click, so it stops behaving like
   a control. The left padding takes the space the radio used to hold, or the
   logo sits a few pixels further left than it does on every other card. */
.flightpick.locked { cursor: default; padding-left: 20px; }
.flightpick.locked:hover { border-color: var(--line); }
.flightpick.picked.locked:hover { border-color: var(--ok-700); }
.flightpick.picked {
  /* A green edge rather than a green field. The fill fought the logos: an
     airline mark drawn on white painted a white rectangle onto the tint,
     which read as pasted on. */
  background: var(--surface);
  border: 2px solid var(--ok-700);
  border-left: 6px solid var(--ok-700);
}
.flightpick-body { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.flightpick-time { font-size: 15px; font-weight: 600; }
.flightpick-body .muted { font-size: 12.5px; }
.flightpick-price {
  text-align: right;
  font-size: 17px;
  font-weight: 600;
  white-space: nowrap;
}
.flightpick-price .muted { display: block; font-size: 11.5px; font-weight: 400; }
.lookupmsg { font-size: 12.5px; }
.legadder { padding-top: 4px; }

/* The legs inside one itinerary. Indented under the summary so a connection
   reads as one choice with two flights in it, not as two choices. */
.seglist { margin: 8px 0 0; padding-left: 14px; border-left: 2px solid var(--line); }
.segrow {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: baseline;
  font-size: 12.5px;
  padding: 3px 0;
}
.segrow b { font-size: 13px; }
.seginline { font-size: 12px; }

/* Drop one leg from an itinerary being built. Quiet until hovered — it sits
   next to every leg, and most of the time none of them need dropping. */
.segdrop {
  margin-left: auto;
  border: 0;
  background: none;
  color: var(--ink-400);
  font-size: 15px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
}
.segdrop:hover { color: var(--bad-700); }

/* An airline's mark beside its flight number. Fixed box either way, so a row
   with a logo and a row with a text badge line up — a list of flights that
   jitters as logos arrive is worse than one with no logos at all. */
.airlogo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  object-fit: contain;
  vertical-align: middle;
  border-radius: 3px;
}
.airlogo-text {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--ink-500);
  background: var(--surface-2);
  border: 1px solid var(--line);
}

/* Joining a connecting flight onto an itinerary already saved. Folded away by
   default — most options are one leg, and an open form under every one of them
   would bury the fares. */
.addleg { margin-top: 8px; }
.addleg > summary {
  font-size: 12.5px;
  color: var(--ink-500);
  cursor: pointer;
  list-style: none;
  padding: 4px 0;
}
.addleg > summary::-webkit-details-marker { display: none; }
.addleg > summary::before { content: '+ '; font-weight: 700; }
.addleg > summary:hover { color: var(--brand-700); }
.addleg form { padding: 8px 0 4px 14px; border-left: 2px solid var(--line); }

/* Which operation of a flight number they meant. Only drawn when a number
   flew more than once that day — one answer is not a choice. */
.candidates { margin: 8px 0; display: flex; flex-direction: column; gap: 6px; }
.candidate {
  display: flex;
  gap: 10px;
  align-items: baseline;
  text-align: left;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.candidate:hover { border-color: var(--brand-700); background: var(--warn-50); }

/* Renaming a trip in place. The name looks like text until you point at it,
   because most of the time it is text — the edit is the rare case. */
.rename { display: inline-block; }
.rename-open {
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  padding: 2px 6px;
  margin-left: -6px;
  border-radius: 4px;
  cursor: pointer;
  text-align: left;
}
.rename-open:hover { background: var(--surface-2); outline: 1px dashed var(--line); }
.rename-form { display: flex; gap: 6px; align-items: center; }
.rename-form input {
  font: inherit;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 5px;
  min-width: 260px;
}

/* The flights a coach did not pick, once they have booked. Folded away rather
   than removed — "what else was there?" is a fair question — but small,
   because the answer no longer changes anything. */
.otherflights { margin: 6px 0 0; }
.otherflights > summary {
  display: inline-block;
  font-size: 12px;
  color: var(--ink-400);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 999px;
  list-style: none;
}
.otherflights > summary::-webkit-details-marker { display: none; }
.otherflights > summary::before { content: '▸ '; }
.otherflights[open] > summary::before { content: '▾ '; }
.otherflights > summary:hover { color: var(--ink-700); background: var(--surface-2); }
/* Not choices any more, so they should not look like them. */
.otherflights-body { margin-top: 8px; opacity: .72; }
.otherflights-body .flightpick { cursor: default; }
.otherflights-body .flightpick:hover { border-color: var(--line); }
.otherflights-body input[type=radio] { display: none; }

/* One flight option on the manager's page. Boxed because each carries a leg
   list, a price row, four buttons and a fold for connections — four of them
   stacked with only a hairline between is unreadable. */
.optcard {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 13px 15px;
  margin-bottom: 12px;
  background: var(--surface);
}
.optcard.picked {
  /* Marked by its edge, so the airline logos inside sit on white as they
     were drawn. */
  background: var(--surface);
  border-color: var(--ok-700);
  border-left: 4px solid var(--ok-700);
}

/* The flight desk, where a coach is choosing or has just chosen — the moment
   a question actually occurs to somebody, rather than filed on a contact page
   nobody opens. */
.deskcard {
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand-700);
  border-radius: 6px;
  padding: 12px 14px;
  background: var(--surface-2);
}
.deskcard p { margin: 6px 0 0; font-size: 13.5px; line-height: 1.65; }

/* Trip shape: one way, round trip, multi-city. Segmented rather than a
   dropdown because there are three and they are the first decision. */
.triptype { display: flex; gap: 0; }
.tt {
  font: inherit;
  font-size: 13.5px;
  padding: 8px 18px;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  color: var(--ink-500);
}
.tt:first-child { border-radius: 7px 0 0 7px; }
.tt:last-child { border-radius: 0 7px 7px 0; }
.tt + .tt { border-left: 0; }
.tt.active {
  background: var(--brand-700);
  border-color: var(--brand-700);
  color: #fff;
  font-weight: 600;
}

/* An airport field holds a set, not a value. The first chip is what they
   named; the rest are alternatives they said they would accept. */
.airportfield { position: relative; }
.apresults { margin-top: 6px; display: flex; flex-direction: column; gap: 4px; }
.apopt {
  text-align: left;
  font: inherit;
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--surface-2);
  cursor: pointer;
}
.apopt:hover { border-color: var(--brand-700); }
.apchips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.apchip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12.5px;
  font-weight: 600;
  padding: 3px 6px 3px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--ink-500);
}
.apchip.primary { background: var(--ok-50); border-color: var(--ok-700); color: var(--ok-700); }
.apchip button { border: 0; background: none; cursor: pointer; color: inherit; font-size: 14px; line-height: 1; }

/* One leg's decision. Boxed so a round trip reads as two choices rather than
   one long list — which is what it is, since each is bought separately. */
.legblock {
  padding: 14px 0;
  border-top: 1px solid var(--line-soft);
}
.legblock:first-of-type { border-top: 0; padding-top: 0; }
.flightpick-price .muted + .muted { margin-top: 1px; font-size: 11px; }
.declinebox { border-top: 1px solid var(--line-soft); }

/* One service inside a trip. Three columns, one per kind, so "what is
   happening with Georgetown" is answered by looking rather than by clicking
   through three pages. */
.grid.c3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.svcrow {
  padding: 10px 0;
  border-top: 1px solid var(--line-soft);
  font-size: 13.5px;
}
.svcrow:first-child { border-top: 0; padding-top: 0; }
.svcrow .muted { font-size: 12.5px; }
.svcrow > div:last-child { margin-top: 4px; }
@media (max-width: 900px) {
  .grid.c3 { grid-template-columns: minmax(0,1fr); }
}

/* A trip on My Trips: three service rows in one card, so the shape of the
   trip is visible without opening it. */
.tripcard { margin-bottom: 14px; }
.tripcard .card-head h3 a { color: inherit; text-decoration: none; }
.tripcard .card-head h3 a:hover { color: var(--brand-700); }
.tripsvc {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-top: 1px solid var(--line-soft);
  font-size: 13.5px;
}
.tripsvc:first-child { border-top: 0; padding-top: 0; }
.tripsvc-label {
  flex: 0 0 110px;
  font-weight: 600;
  color: var(--ink-500);
  font-size: 12.5px;
}
.tripsvc-body { display: flex; align-items: center; gap: 8px; text-decoration: none; color: inherit; }
.tripsvc-body:hover b { color: var(--brand-700); }
/* An empty service is an invitation, not a gap. */
.tripsvc.empty .tripsvc-label { color: var(--ink-400); font-weight: 500; }
.tripsvc-add { font-size: 12.5px; color: var(--brand-700); }

/* "Same as outbound, reversed" — sits in the return leg's own label, because
   that is where somebody is when the thought occurs. */
.reversebtn {
  border: 0;
  background: none;
  font: inherit;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--brand-700);
  cursor: pointer;
  padding: 0 0 0 8px;
  text-decoration: underline;
}
.reversebtn:hover { color: var(--ink-900); }

/* ==========================================================================
   Trips — the coach's own list
   A trip is a row until you open it. Ten trips should read as ten lines, not
   ten pages of cards, and the state of each is carried by the marks on the
   right rather than by three chips repeating the word "Confirmed".
   ========================================================================== */

.triplist { display: flex; flex-direction: column; gap: 8px; }

.trip {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.trip[open] { border-color: var(--ink-300); box-shadow: var(--shadow); }

.trip > summary {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 16px;
  cursor: pointer;
  list-style: none;
}
.trip > summary::-webkit-details-marker { display: none; }
.trip > summary:hover { background: var(--surface-2); }
.trip > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

.trip-name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ink-900);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Dates in mono, like every other figure in this console, so they line up
   down the column when a coach scans ten of them. */
.trip-dates {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-400);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.trip-marks { display: flex; align-items: center; gap: 9px; }

.svcicon { display: inline-flex; width: 20px; height: 20px; flex: 0 0 20px; }
.svcicon svg { width: 100%; height: 100%; }
/* The mark carries the state. Grey while it is still being worked, green once
   it is settled — so a row of green means a trip that needs nothing.

   These are filled rather than stroked, which makes them heavier than the
   rest of the console at full ink. Keeping them off near-black is what stops
   the icons pulling the eye away from the trip name they sit beside. */
/* Four states, so a closed row still says where everything stands. Blue for
   booked rather than orange: orange is the brand colour and means "this is a
   control" everywhere else — reusing it for a state would make it mean two
   things on one page. */
.svcicon-pending { color: var(--ink-300); }
.svcicon-rates { color: #B45309; }      /* amber, deep enough to read white */
.svcicon-booked { color: #1D4ED8; }
.svcicon-confirmed { color: var(--ok-700); }
/* A record, not a stage. Grey rather than green: green says "settled, and
   still ahead of you". */
.svcicon-past { color: var(--ink-400); }
/* The old two, until every caller has moved. */
.svcicon-progress { color: var(--ink-300); }
.svcicon-done { color: var(--ok-700); }

.trip-chev {
  color: var(--ink-300);
  transition: transform .15s ease;
  flex: 0 0 auto;
}
.trip[open] .trip-chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .trip-chev { transition: none; }
}

.trip-body { padding: 2px 16px 14px; border-top: 1px solid var(--line-soft); }

/* One service inside an open trip. The icon repeats from the header so the
   eye can follow it down, and an empty service reads as an invitation rather
   than a gap. */
.tripsvc {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 0;
  border-top: 1px solid var(--line-soft);
  font-size: 13.5px;
}
.tripsvc:first-child { border-top: 0; }
.tripsvc-label { flex: 0 0 82px; color: var(--ink-500); font-size: 12.5px; }
.tripsvc-body { display: flex; align-items: center; gap: 8px; color: inherit; text-decoration: none; }
.tripsvc-body b { font-weight: 600; }
.tripsvc-body:hover b { color: var(--brand-700); }
.tripsvc.empty .svcicon { opacity: .3; }
.tripsvc.empty .tripsvc-label { color: var(--ink-300); }
.tripsvc-add { font-size: 12.5px; color: var(--brand-700); font-weight: 500; }
.tripsvc-foot { padding-top: 11px; border-top: 1px solid var(--line-soft); font-size: 12.5px; }

/* A stay that has already happened, on Team Hotels. Dimmed rather than hidden
   — a coach still looks these up when an invoice arrives. */
tr.past td { opacity: .55; }

/* A brand mark in a fixed slot. The three kinds arrive as different shapes —
   a square airline badge, a wide operator wordmark, a hotel chain somewhere
   between — so the box is fixed and the mark is contained inside it. Cropping
   would cut wordmarks in half; letting each size itself would leave rows
   jagged down a column. */
/* A mark on the page, not in a box.
   The panel and border were doing nothing the fixed dimensions were not:
   those are what line Alaska's wide script up with Southwest's wordmark, and
   they stay. A row of eggshell tiles down a confirmation read as chrome. */
.logoslot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 32px;
  flex: 0 0 56px;
  padding: 3px 5px;
  overflow: hidden;
}
.logoslot img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Initials, so a row without a mark is the same shape as a row with one. */
.logoslot-fallback {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--ink-300);
}

.logoedit { display: flex; align-items: center; gap: 8px; }
.logoedit form { display: inline-flex; }
.logopick { cursor: pointer; }
.logopick input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.logopick span {
  font-size: 12px;
  color: var(--brand-700);
  text-decoration: underline;
}
.logopick:hover span { color: var(--ink-900); }
.logodrop {
  border: 0; background: none; cursor: pointer;
  color: var(--ink-300); font-size: 15px; line-height: 1; padding: 0 2px;
}
.logodrop:hover { color: var(--bad-700); }

/* What the buses have. Ticked on a yard, shown to a coach beside the price —
   which is what they are actually choosing between when two quotes are forty
   dollars apart. */
.amenitypick { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.amenitylist { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.amenity {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--ok-50);
  /* Black, not green. Green said "good" about facts that are neither good
     nor bad — a bus either has a washroom or it does not, and colouring
     every one of them like praise made the row read as marketing. */
  color: #111;
  border: 1px solid #BFDCCB;
}

/* "Ground Transportation segment of …" — the service names itself before the
   trip does, because the page you are on is the service. */
.segmentof {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink-900);
}
/* The operator a coach picked. */
.quoterow.picked {
  background: var(--ok-50);
  border-color: var(--ok-700);
}

/* A carrier mark inline in a line of flight text. Sized to be legible as a
   mark rather than to match the 12px text around it — matching the text made
   it too small to recognize, which is the only job it has. */
.airlogo.sm { width: 20px; height: 20px; flex: 0 0 20px; }
/* One mark for a whole itinerary, where every leg is the same carrier. */
.seginline .airlogo { width: 24px; height: 24px; flex: 0 0 24px; margin-right: 3px; }
/* With no mark and no room for letters, a quiet dot holds the place so the
   line does not jump when one is uploaded. */
.airlogo-text.sm {
  background: var(--line-soft);
  border-color: transparent;
  border-radius: 50%;
}

/* The carrier mark on a flight option: its own column, ahead of the times.
   Inline it could only be as tall as 12px type allowed, which is too small to
   recognize — and recognizing it is the only job it has.

   One size, booked or not. It used to shrink to a 40px square once a leg was
   booked, on the reasoning that it had become a detail on a record. That was
   wrong about which page a coach lives on: the confirmed card is the one they
   open at the airport, and since the fare came off the box the mark is the
   only thing naming the carrier at a glance.

   The square was also the wrong shape. A wordmark like Southwest's is wide
   and short, so "contain" inside 40px rendered it about eight pixels tall —
   present and unreadable. It fills the slot now and keeps its own
   proportions.

   The slot matches the capsule's, so an airline's mark is the same size
   wherever a coach meets it. There were two .flightpick-mark rules here for
   a while, the second silently overriding the first. */
.flightpick-mark {
  width: 96px; height: 44px; flex: 0 0 96px;
  display: flex; align-items: center; justify-content: center;
}
.flightpick-mark img.airlogo {
  width: 100%; height: 100%; flex: none; object-fit: contain;
}
/* The letters we fall back to before a logo is uploaded. Sized to the text,
   not stretched to the slot — a 120px block of initials would shout louder
   than any real mark. */
.flightpick-mark .airlogo-text {
  width: auto; height: auto; flex: none;
  padding: 7px 13px; font-size: 15px; border-radius: 6px;
}

/* Which decision this is. On a multi-city trip it was set in the same small
   grey caps as every other label on the page. */
.legtitle {
  margin: 0 0 10px;
  font-size: 15px;
  color: var(--ink-700);
}
.legtitle b { font-size: 16.5px; font-weight: 700; color: var(--ink-900); }

/* When an option went to the coach. Each carries its own stamp, so a release
   of four and four separate releases read the same afterwards. */
.releasedat {
  margin: 6px 0 2px;
  font-size: 11.5px;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
}

/* A vendor mark where it is the thing being chosen, rather than a detail
   beside a name — the coach's quote row and anywhere else it carries weight. */
/* The operator's mark where they are the thing being chosen. Larger than
   anywhere else because on this page a coach is picking between companies,
   and the mark is doing the work a name cannot do at a glance. */
.logoslot.lg { width: 124px; height: 72px; flex: 0 0 124px; padding: 7px 10px; }
.logoslot.lg .logoslot-fallback { font-size: 18px; }
@media (max-width: 700px) {
  .logoslot.lg { width: 92px; height: 56px; flex: 0 0 92px; }
}


/* Marks on the trip rows. Bigger than the directory listing because this is
   the page a coach opens every day, and there is room in the row for them to
   be recognized rather than merely present. */
/* Wide enough for a long wordmark. A square badge is held by the height
   and does not change; a wordmark like an operator's gains a quarter more
   room. Every row keeps the same box, so the column still lines up. */
.tripsvc .logoslot { width: 96px; height: 44px; flex: 0 0 96px; }
.tripsvc .logoslot-fallback { font-size: 13px; }

/* A service inside an open trip. A row rather than a label-and-value pair,
   because a trip can hold two hotels and two buses and each is its own thing
   to open. */
a.tripsvc { text-decoration: none; color: inherit; }
a.tripsvc:hover { background: var(--surface-2); }
a.tripsvc:hover .tripsvc-body b { color: var(--brand-700); }
.tripsvc-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.tripsvc-body .muted { font-size: 12px; }

/* Only what the trip lacks. A complete trip should not carry three dead
   links. */
.tripadd {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  padding-top: 11px;
  margin-top: 4px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
}
.tripadd a:not(.btn) { color: var(--brand-700); }
.tripadd { align-items: center; }
.tripadd .addstrip { margin: 0; }

/* A leg the team is not flying. Dimmed rather than removed — a coach scanning
   the trip should see the return is not happening, not see a gap and assume
   nobody entered it. */
a.tripsvc.dropped { opacity: .55; }
a.tripsvc.dropped .tripsvc-body b { text-decoration: line-through; }

/* One vendor on the sourcing page. Boxed because each carries a mark, a price
   row, four buttons and a note — six of them separated by a hairline is not a
   list somebody can work from. */
.vendorbox {
  border: 2px solid var(--line);
  border-radius: 9px;
  padding: 14px 16px;
  margin-bottom: 12px;
  background: var(--surface);
}
.vendorbox.picked {
  background: var(--ok-50);
  border-color: var(--ok-700);
}
/* A preferred operator should be findable in a stack of six without reading
   every name. */
.vendorbox.preferred { border-color: var(--brand); }
.vendorbox.preferred.picked { border-color: var(--ok-700); }

/* A preferred operator, and the reason behind it. The reason is the point —
   the badge alone asks for trust it has not earned. */
.preferredbadge {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--brand-50, #FDF0E7);
  color: var(--brand-700);
  border: 1px solid var(--brand);
  cursor: help;
}
.preferredwhy { font-size: 12.5px; margin-top: 4px; font-style: italic; }

/* ==========================================================================
   The ground queue — five stages you work along, left to right.
   The strip is the filter. Four cards above a dropdown said the same thing
   twice and gave two places for it to disagree.
   ========================================================================== */

.stages {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 14px;
}
.stage {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
}
.stage:hover { border-color: var(--ink-300); }
/* The stage you are looking at, so the strip and the list never disagree
   about what is on screen. */
.stage.on {
  border-color: var(--brand);
  box-shadow: inset 0 -3px 0 var(--brand);
  background: var(--surface);
}
.stage-n {
  font-family: var(--mono);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.stage-label { font-size: 12px; color: var(--ink-500); }
/* Empty is the good state here, so it recedes rather than shouting. */
.stage.empty .stage-n { color: var(--ink-300); }
.stage-flag {
  margin-top: 3px;
  font-size: 11px;
  font-weight: 600;
  color: var(--bad-700);
}

/* One search row, not a form pretending to be a card. */
.groundsearch {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 14px;
}
.groundsearch input[type=search] {
  flex: 1 1 auto;
  max-width: 460px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 7px;
  font: inherit;
  font-size: 13.5px;
}
.groundsearch select {
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  font: inherit;
  font-size: 13.5px;
}
@media (max-width: 900px) {
  .stages { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .groundsearch { flex-wrap: wrap; }
}

/* The breakdown behind a quote. Folded when empty because most never get one
   and six open rows under every vendor would bury the prices. */
.pricelines { margin-top: 10px; }
.pricelines > summary {
  font-size: 12.5px;
  color: var(--brand-700);
  cursor: pointer;
  list-style: none;
  padding: 4px 0;
}
.pricelines > summary::-webkit-details-marker { display: none; }
.pricelines > summary::before { content: '▸ '; }
.pricelines[open] > summary::before { content: '▾ '; }
.linetable { width: 100%; border-collapse: collapse; margin-top: 6px; }
.linetable td { padding: 2px 4px 2px 0; }
.linetable input {
  width: 100%;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 5px;
  font: inherit;
  font-size: 12.5px;
}
.linetable td.num input { text-align: right; font-family: var(--mono); }
/* Said, not enforced — a quote that does not reconcile is still worth having. */
.mismatch { font-size: 12px; color: var(--warn-700); }

/* Bus photos on the vendor page. */
.busthumbs { display: flex; gap: 8px; flex-wrap: wrap; }
.busthumb { position: relative; width: 120px; height: 80px; }
.busthumb img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 7px;
  border: 1px solid var(--line);
}
.busthumb form { position: absolute; top: 3px; right: 3px; }
.busthumb-x {
  border: 0;
  background: rgba(22,18,14,.72);
  color: #fff;
  width: 20px; height: 20px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
}

/* One operator a coach is choosing between. A box with a footer, so the book
   buttons line up across vendors however much detail each carries above them —
   inline they landed wherever the content happened to end. */
.quotebox {
  display: flex;
  flex-direction: column;
  border: 2px solid var(--line);
  border-radius: 9px;
  padding: 14px 16px;
  margin-bottom: 12px;
  background: var(--surface);
}
.quotebox.picked {
  /* An edge rather than a tint, like the hotel and the flights. The fill put
     a white logo tile in the middle of a green field, and "confirmed" looked
     like three different things across three pages. */
  background: var(--surface);
  border: 2px solid var(--ok-700);
  border-left: 6px solid var(--ok-700);
}
.quotebox-top { display: flex; align-items: center; gap: 14px; }
.quoteextras { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 10px; }
.quotefoot {
  display: flex;
  justify-content: flex-end;
  padding-top: 12px;
  margin-top: 12px;
  border-top: 1px solid var(--line-soft);
}
.quotefold > summary, .quotefold-btn {
  font-size: 12.5px;
  color: var(--brand-700);
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  list-style: none;
}
.quotefold > summary::-webkit-details-marker { display: none; }
.quotefold > summary::before { content: '▸ '; }
.quotefold[open] > summary::before { content: '▾ '; }
.quotefold-btn:hover, .quotefold > summary:hover { color: var(--ink-900); }
.breakdown { display: grid; grid-template-columns: 1fr auto; gap: 5px 18px; margin: 9px 0 0; font-size: 13px; }
.breakdown dt { color: var(--ink-500); }
.breakdown dt .muted { font-size: 12px; }
.breakdown dd { margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* The photo gallery. A look, not a destination — Escape or a click outside
   puts them straight back where they were. */
.lightbox {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(22,18,14,.62);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.lightbox-inner {
  background: var(--surface);
  border-radius: var(--radius-lg);
  max-width: 860px; width: 100%;
  max-height: calc(88vh / var(--zoom)); overflow: auto;
  padding: 18px 20px;
  box-shadow: var(--shadow-lg, 0 18px 48px rgba(22,18,14,.28));
}
.lightbox-head { display: flex; align-items: center; margin-bottom: 14px; }
.lightbox figure { margin: 0 0 16px; }
.lightbox img { width: 100%; border-radius: 9px; display: block; }
.lightbox figcaption { font-size: 12.5px; color: var(--ink-500); margin-top: 6px; }


/* Captioning a bus photo in place. Sits under the thumb because several files
   uploaded together cannot share one caption box at upload time. */
.busthumb { width: 130px; height: auto; }
.busthumb img { height: 84px; }
.busthumb-cap { margin-top: 4px; }
.busthumb-cap input {
  width: 100%;
  padding: 4px 7px;
  border: 1px solid var(--line);
  border-radius: 5px;
  font: inherit;
  font-size: 11.5px;
}


/* The bus gallery: one photo at a time and large, with arrows. Three side by
   side in a dialog are three small photos, and the point is to see the bus. */
.carousel { display: flex; align-items: center; gap: 10px; }
.carousel figure { margin: 0; flex: 1 1 auto; min-width: 0; }
.carousel img { width: 100%; border-radius: 9px; display: block; }
.carousel figcaption {
  font-size: 12.5px; color: var(--ink-500); margin-top: 8px; text-align: center;
}
.carousel-arrow {
  flex: 0 0 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  font-size: 22px;
  line-height: 1;
  color: var(--ink-500);
  cursor: pointer;
}
.carousel-arrow:hover { border-color: var(--ink-400); color: var(--ink-900); }
.carousel-dots { display: flex; justify-content: center; gap: 6px; margin-top: 12px; }
.carousel-dots .dot {
  width: 7px; height: 7px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--line);
  cursor: pointer;
}
.carousel-dots .dot.on { background: var(--ink-500); }

/* The photo a coach sees first. */
.busthumb.first img { border-color: var(--brand); border-width: 2px; }
.busthumb-badge {
  position: absolute; top: 4px; left: 4px;
  font-size: 10px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase;
  padding: 2px 6px; border-radius: 999px;
  background: var(--brand); color: #fff;
}
.busthumb-first { position: absolute; bottom: 30px; left: 4px; }
.busthumb-first button {
  border: 0; border-radius: 999px;
  background: rgba(22,18,14,.72); color: #fff;
  font-size: 10px; padding: 2px 7px; cursor: pointer;
}


/* Which shape of trip a coach is describing. Two buttons rather than a
   dropdown because there are two, and the sport has already picked one. */
.shapepick { display: flex; gap: 0; margin-bottom: 4px; }
.sp {
  font: inherit;
  font-size: 13px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-500);
  cursor: pointer;
}
.sp:first-child { border-radius: 7px 0 0 7px; }
.sp:last-child { border-radius: 0 7px 7px 0; border-left: 0; }
.sp.active {
  background: var(--brand-700);
  border-color: var(--brand-700);
  color: #fff;
  font-weight: 600;
}
.games .gamerow { margin-bottom: 0; }


/* Flights run to four stages rather than five. */
.stages.air { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .stages.air { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* Results under a venue box, wherever one appears. */
.venueresults { position: relative; display: flex; flex-direction: column; gap: 4px; margin-top: 5px; }
.venueopt {
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-align: left;
  font: inherit;
  font-size: 13px;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
  cursor: pointer;
}
.venueopt:hover { border-color: var(--brand-700); }
.venueopt .muted { font-size: 12px; }


/* A venue that was actually chosen, rather than typed past. Without this a
   plain box looks the same whether it holds a real place or a string, and the
   difference decides whether anything downstream has coordinates. */
.venuechip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 11.5px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--ok-50);
  color: var(--ok-700);
  border: 1px solid #BFDCCB;
}
.venuechip::before { content: '✓'; }


/* Typed but not chosen. The server still tries to match the name, so this is
   a nudge rather than a refusal — but saying nothing is how somebody finds out
   after submitting that the venue was never linked. */
.venuechip.unlinked {
  background: var(--warn-50, #FDF4E7);
  color: var(--warn-700);
  border-color: #E8D3AE;
}
.venuechip.unlinked::before { content: '?'; }


/* One hotel or two, asked while they can still answer it. */
.planask {
  margin-top: 14px;
  padding: 13px 15px;
  border: 1px solid var(--brand);
  border-radius: 9px;
  background: var(--brand-50, #FDF0E7);
}
.planpick { display: flex; gap: 20px; flex-wrap: wrap; margin: 9px 0 4px; }


/* Where the pre-filled answers came from. Stated rather than implied: a
   number somebody skipped past is a number that goes out wrong. */
.carriedfrom {
  margin: 0 16px;
  padding: 9px 13px;
  border-left: 3px solid var(--brand);
  background: var(--surface-2);
  font-size: 12.5px;
  color: var(--ink-500);
  border-radius: 0 6px 6px 0;
}


/* The line that answers "what happens now", which is the question a coach
   actually has on a confirmation page. Centerd and held to a readable measure
   — it is four sentences, and full-width four-sentence paragraphs do not get
   read. */
.donelead {
  /* Left-aligned in a centred block. Narrowing the measure to 44ch helped
     and did not fix it: centred prose over three lines gives three different
     start and end points, and the eye reads that as crooked rather than as
     centred. Centring is for a slogan; this is instruction. */
  max-width: 44ch;
  text-align: left;
  margin: 0 auto 22px;
  color: var(--ink-500);
  font-size: 14px;
  line-height: 1.55;
}
.donecard .brandlogo { margin: 0 auto 14px; display: block; }
.donecard h1 { display: inline-flex; align-items: center; gap: 9px; }

/* The details stop floating in the middle of the page: their own panel,
   left-aligned inside a centred card, ruled row by row — which is how a
   receipt reads, and this is a receipt. */
.donedetail {
  text-align: left; border: 1px solid var(--line-soft);
  border-radius: var(--radius); background: var(--surface-2);
  padding: 4px 16px; margin: 0 0 18px;
  display: grid; grid-template-columns: 128px 1fr;
}
.donedetail dt {
  color: var(--ink-400); font-size: 12px; padding: 9px 0;
  border-top: 1px solid var(--line-soft);
}
.donedetail dd {
  margin: 0; padding: 9px 0; font-size: 14px;
  border-top: 1px solid var(--line-soft);
}
.donedetail > dt:first-of-type,
.donedetail > dt:first-of-type + dd { border-top: 0; }
/* One game per line, date first: that is the order a coach scans them in. */
.gameline { display: block; }
.gameline .when { color: var(--ink-400); }
/* The reference itself is already styled below as .doneref — one rule for
   it, not two that drift. */


/* One line above the list, where every hotel sits the same distance from the
   same campus. */
.donenote {
  margin: 0 0 10px;
  font-size: 12.5px;
  color: var(--ink-500);
  text-align: center;
}
/* The number a coach quotes on the phone. */
.doneref {
  margin: 18px 0 16px;
  font-size: 12.5px;
  color: var(--ink-400);
  text-align: center;
}
.doneref b { font-family: var(--mono); color: var(--ink-900); font-size: 15px; }


/* The trip's own number, on the page a coach lands on. */
.tripref { font-family: var(--mono); font-size: 12px; }


/* What a coach told us, read back on a confirmation. Held to a readable
   width and left-aligned inside a centered card — a definition list centered is
   a definition list nobody can scan. */
/* The detail block on a submission page.
   `.kv` gives labels a fixed 128px column against `1fr`, which on a narrow
   centred card left a gap down the middle: the labels ended well left of the
   values and neither column lined up with the heading above. Sized to the
   content instead, and the pair centred as one block. */
.donedetail {
  display: inline-grid;
  grid-template-columns: max-content max-content;
  gap: 7px 16px;
  margin: 0 auto 4px;
  text-align: left;
  max-width: 100%;
}
.donedetail dt { justify-self: end; }


/* What the bus is for. Three cards rather than a dropdown, because the choice
   changes the rest of the form and a coach should see all three before
   picking. */
.kindpick { display: flex; flex-direction: column; gap: 8px; }
.kindopt {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
}
.kindopt:hover { border-color: var(--ink-300); }
.kindopt:has(input:checked) {
  border-color: var(--brand);
  background: var(--brand-50, #FDF0E7);
}
.kindopt > span { display: flex; flex-direction: column; gap: 2px; }
.kindopt .muted { font-size: 12.5px; }


/* The trip in the order it happens. A coach reads a trip forwards, and
   grouping by service made them assemble that from three lists. */
.phases { list-style: none; margin: 0; padding: 0; }
.phaseday {
  padding: 9px 16px 5px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-400);
  border-top: 1px solid var(--line-soft);
}
.phaseday:first-child { border-top: 0; }
.phase {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 16px;
}
.phase:hover { background: var(--surface-2); }
/* The clock column stays the same width whether or not there is a time, so
   the icons line up down the page. */
.phase-when {
  flex: 0 0 62px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
}
.phase-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.phase-body .muted { font-size: 12px; }
.phase-open { font-size: 12.5px; color: var(--brand-700); }
/* A leg the team is not flying stays on the page, struck through — showing
   nothing would read as "not arranged yet". */
.phase.dropped { opacity: .55; }
.phase.dropped .phase-body b { text-decoration: line-through; }


/* Three ways into a first trip, rather than a sentence describing three ways
   in and a button that only does one of them. */
.startempty { padding-bottom: 26px; }
.startpick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  max-width: 720px;
  margin: 20px auto 0;
  text-align: left;
}
.startopt {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 14px 15px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
  text-decoration: none;
  color: inherit;
}
.startopt:hover { border-color: var(--brand); background: var(--surface-2); }
/* Held while the click lands, so tapping one on a phone visibly does
   something before the next page arrives. */
.startopt:active,
.startopt:focus-visible {
  border-color: var(--brand);
  background: var(--brand-50, #FDF0E7);
  outline: none;
}
.startopt > span { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* Brand orange on the name and the mark: these are the three doors into the
   product, and on an otherwise empty screen they should be the thing the eye
   lands on. */
.startopt b { color: var(--brand-700); }
.startopt .svcicon { color: var(--brand); }
.startopt .muted { font-size: 12px; line-height: 1.4; }

/* A nudge on arrival, then still. Four seconds is long enough to be noticed
   and short enough not to become the page's personality — and anything that
   keeps moving while somebody reads is a thing they have to look away from. */
@keyframes startnudge {
  0%, 100% { transform: translateY(0); box-shadow: none; }
  50% { transform: translateY(-3px);
        box-shadow: 0 6px 18px rgba(253, 112, 8, .18); }
}
/* `.choosebox`, not `.startopt`. The markup was renamed and this rule was
   not, so the nudge had been animating nothing at all — the boxes a new
   coach lands on sat there as still as everything else on the page. */
[data-startpulse] .choosebox {
  animation: startnudge 1.3s ease-in-out 3;
}
[data-startpulse] .choosebox:nth-child(2) { animation-delay: .12s; }
[data-startpulse] .choosebox:nth-child(3) { animation-delay: .24s; }
[data-startpulse] .choosebox:nth-child(4) { animation-delay: .36s; }
/* Somebody who has asked for less movement gets none. */
@media (prefers-reduced-motion: reduce) {
  [data-startpulse] .choosebox { animation: none; }
}
@media (max-width: 760px) {
  .startpick { grid-template-columns: 1fr; }
}


/* A value shown rather than edited, where the field is real but not theirs to
   change. Looks like an input's neighbour without pretending to be one. */
.readback {
  margin: 0;
  padding: 9px 12px;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
  font-size: 14px;
}
/* Eleven programmes is a wall in one column and a scan in three. */
.rewardgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0 18px;
}


/* Told to a hotel while they are deciding what to offer: a member is worth
   points to them, which is exactly the lever this field is asking about. */
.memberflag {
  margin: 0 0 8px;
  font-size: 12.5px;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--ok-50);
  color: var(--ok-700);
  border: 1px solid #BFDCCB;
}


/* A button that reads as a link, for an action that reveals rather than
   commits. */
.linkish {
  border: 0; background: none; padding: 0 0 0 4px;
  font: inherit; font-size: 12.5px;
  color: var(--brand-700); text-decoration: underline; cursor: pointer;
}


/* ==========================================================================
   The flight sourcing page.

   A round trip is two of these and a multi-city is however many, so the eye
   needs to know where one leg ends and the next begins before it reads a
   word.
   ========================================================================== */

.legcard { border-width: 2px; }
.legcard + .legcard { margin-top: 22px; }

/* The date, given weight: it is what tells a manager what to search. */
.legdate {
  margin-left: 10px;
  font-size: 13px;
  font-weight: 700;
  color: var(--brand-700);
  font-variant-numeric: tabular-nums;
}

/* What the coach asked for, beside the times being chosen. One pulse on
   arrival, then still — anything that keeps moving while somebody reads is a
   thing they have to look away from. */
.askedfor {
  margin: 0 0 14px;
  padding: 10px 13px;
  border-left: 3px solid var(--warn-700);
  background: var(--warn-50, #FDF4E7);
  border-radius: 0 7px 7px 0;
  font-size: 13px;
}
.askedfor b { color: var(--warn-700); }
@keyframes askednudge {
  0%, 100% { box-shadow: none; }
  50% { box-shadow: 0 0 0 4px rgba(196, 83, 10, .16); }
}
[data-asked] { animation: askednudge 2s ease-in-out 4; }
@media (prefers-reduced-motion: reduce) {
  [data-asked] { animation: none; }
}

/* Saved, and waiting on the coach. Green is reserved for booked — the tint
   tracks what has to happen next, not what already did.

   The whole border, not one edge: with four priced options stacked on a leg,
   a stripe down the left does not tell you where one ends and the next
   begins. */
.optcard.saved { border: 2px solid var(--brand); }
.optcard.saved.picked {
  border-color: var(--ok-700);
  background: var(--ok-50);
}
.optnum {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
}

/* Typed by hand, behind a link: the lookup gives real schedules and a flight
   id that feeds alerts, and this gives none of that. */
.manualentry {
  margin-top: 10px;
  padding: 12px 14px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  background: var(--surface-2);
}


/* What the coach asked for, beside the leg it applies to. Stated rather than
   claimed: "flights shown meet your requested time" stops being true the
   moment one of them does not. */
.asked {
  margin-top: 6px;
  font-size: 14px;
  color: var(--ink-700);
  font-weight: 500;
}
.asked b { color: var(--brand-700); }

/* And the exception, on the flight itself with the reason it was sent. */
.outsideflag {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--warn-700);
  line-height: 1.45;
}
.outsideflag b { display: block; }
.outsideflag span { color: var(--ink-500); }

/* Manager side: the breach, and the box to explain it. */
.outsidewindow {
  margin: 8px 0 4px;
  padding: 10px 13px;
  border-left: 3px solid var(--warn-700);
  background: var(--warn-50, #FDF4E7);
  border-radius: 0 7px 7px 0;
  font-size: 13px;
}
.outsidewindow > b { color: var(--warn-700); }


/* The fare, once a flight has resolved. An option saved without one is
   invisible to the coach, so it asks to be filled — briefly, then stops. */
@keyframes wantsfare {
  0%, 100% { box-shadow: none; }
  50% { box-shadow: 0 0 0 4px rgba(253, 112, 8, .22); }
}
.field.wantsfare input {
  animation: wantsfare 1.4s ease-in-out 4;
  border-color: var(--brand);
}
@media (prefers-reduced-motion: reduce) {
  .field.wantsfare input { animation: none; }
}


/* ==========================================================================
   The group travel confirmation.

   One document, read by both sides — and printed, forwarded and filed. It
   should look like the PDF SelectHospitality already sends, because that is
   what a coach recognizes.
   ========================================================================== */

.confdoc {
  max-width: 820px;
  margin: 0 auto;
  padding: 8px 4px 40px;
  font-size: 13.5px;
  line-height: 1.55;
}
.confdoc .brandlogo { height: 32px; margin: 0 0 22px; }
.confdoc h1 { font-size: 19px; line-height: 1.3; margin: 0 0 2px; }
.confsub { margin: 0 0 20px; font-size: 15px; font-weight: 600;
           color: var(--ink-700); }

.confhead {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  gap: 26px;
  padding-bottom: 16px;
  border-bottom: 3px solid var(--ink-800);
  margin-bottom: 18px;
}
.confhead b { font-weight: 700; }
/* The contact, under the address it belongs with. */
.confcontact { margin-top: 12px; }

.confbanner {
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: .01em;
  margin: 0 0 14px;
}

/* The banded boxes from the PDF: an orange head and a bordered body. */
.confbox { margin: 0 0 16px; border: 1px solid var(--line); }
.confbox-head {
  padding: 6px 11px;
  background: var(--brand);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
}
.confbox-head .muted { color: rgba(255,255,255,.85); font-weight: 400; }
.confbox-body {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 9px 11px;
  color: var(--warn-700);
}
.confbox-body.col { display: block; }
.confbox-body.col div { margin-top: 5px; color: var(--warn-700); }
.confno { font-weight: 700; }

.confrule {
  margin: 26px 0 8px;
  padding-top: 14px;
  border-top: 3px solid var(--ink-800);
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: .02em;
}

.conftable { width: 100%; border-collapse: collapse; font-size: 13px; }
.conftable th, .conftable td {
  padding: 6px 9px; text-align: left; border-bottom: 1px solid var(--line-soft);
}
.conftable thead th { border-bottom: 1px solid var(--ink-300); font-weight: 700; }
.conftable .num { text-align: right; font-variant-numeric: tabular-nums; }
.conftable.fares { border: 1px solid var(--line); }
.conftable.fares th, .conftable.fares td { border: 1px solid var(--line); }
.conftable .grand td { background: var(--surface-2); }

.confnote { margin: 12px 0 0; font-size: 12.5px; color: var(--warn-700); }
.confmeta { margin-top: 30px; font-size: 12px; color: var(--ink-400); }

/* Typed at the moment of confirming, because the carrier sets them and they
   differ every time. */
.confirmform { text-align: left; }
.confirmform .field { margin-bottom: 10px; }

.confbar { display: flex; align-items: center; margin-bottom: 22px; }
.confbar .brandlogo { margin: 0; }

/* The dates money is owed and seats can still be dropped — the part of a
   group booking that costs somebody real money if it is missed. */
.duedates {
  margin-top: 20px;
  padding: 14px 16px;
  border: 2px solid var(--brand);
  border-radius: 9px;
  background: var(--brand-50, #FDF0E7);
}
.duedates h4 {
  margin: 0 0 10px;
  font-size: 14px;
  color: var(--brand-700);
}
.duedates dl {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 6px 18px;
  margin: 0;
}
.duedates dt { font-size: 13px; color: var(--ink-600); }
.duedates dd {
  margin: 0;
  font-size: 13.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.duedates dd .muted { font-weight: 400; font-size: 12.5px; }

@media print {
  /* A page somebody forwards to an athletic director. Everything that only
     works on a screen goes. */
  .confdoc { max-width: none; padding: 0; }
  nav, header, .page-head, .btn, .confbar .btn { display: none !important; }
  .confbox, .conftable, .duedates { break-inside: avoid; }
  .conftable tr { break-inside: avoid; }
  .confrule { break-after: avoid; }
  a[href]:after { content: none !important; }
}


/* The motor coach confirmation. Same furniture as the flight one — a coach
   who books a bus and flights should not meet two different companies. */
.confservice {
  margin: 0 0 18px;
  padding: 10px 13px;
  border-left: 3px solid var(--brand);
  background: var(--surface-2);
  border-radius: 0 7px 7px 0;
  font-size: 13px;
}
.confterms { margin: 10px 0 18px; padding-left: 20px; }
.confterms li { margin-bottom: 7px; }

/* The day plan runs down the page. The printed template had six columns hard
   coded, and a two-week trip has fourteen days. */
.conftable.dayplan th {
  width: 84px;
  white-space: nowrap;
  vertical-align: top;
  background: var(--surface-2);
}
.conftable.dayplan td { line-height: 1.5; }


/* The hotel's copy of what they submitted. Printed after submit rather than
   before, so it is a record and not a form. */
@media print {
  .noprint, nav, header, .page-head { display: none !important; }
  .card { border: none !important; box-shadow: none !important; }
}


/* ==========================================================================
   The manager's trip page during sourcing.

   Twelve hotels, each with a photo, a status, a rate block and a row of
   controls. Without a real edge between them the eye cannot find where one
   ends — and a manager scanning for the new rate is the whole job.
   ========================================================================== */

.invrow {
  border: 2px solid var(--ink-800);
  /* Weight earns its place on the manager's page, where twelve of these
     stack. A coach sees two or three and the heavy edge just shouts. */
}
.invrow.coachrow {
  border-width: 1px;
  border-color: var(--line);
  border-radius: 10px;
  padding: 14px 16px;
  margin-bottom: 16px;
  background: var(--surface);
}

/* A rate that arrived overnight should be obvious. The same rate a week
   later should not still be shouting, which is what `seen_at` decides. */
.invrow.newbid {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(253, 112, 8, .10);
}
.bidblock {
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-2);
}
.invrow.newbid .bidblock {
  border-color: var(--brand);
  background: var(--brand-50, #FDF0E7);
}
.bidwhen {
  font-size: 12px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}
.bidwhen b { color: var(--brand-700); }

/* The controls, fenced off from the hotel's own information. A manager
   reading a rate and a manager acting on it are two different moments. */
.rfptools {
  margin-top: 12px;
  border: 2px solid var(--brand);
  border-radius: 9px;
}
.rfptools-head {
  padding: 6px 12px;
  background: var(--brand);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-radius: 6px 6px 0 0;
}
/* Stacked and grouped, not a single wrapping row. Everything was the same
   size and the same weight, so the thing a manager came to do was wherever
   it happened to fall. */
.rfptools-body { padding: 12px; }
.rfptools-body .toolrow { margin: 0; }
.rfptools-body .btn.block {
  width: 100%;
  margin-bottom: 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rfptools-body form { margin: 0; }

/* A thin rule between groups: sending, adjusting, and the two that are hard
   to undo. */
.toolgroup {
  margin-top: 11px;
  padding-top: 11px;
  border-top: 1px solid var(--line-soft);
}
.toolgroup.danger { border-top-color: var(--line); }
.toolgroup.danger .btn { color: var(--bad-700, #9f1239); }

/* Three small controls that belong together, evenly spread. */
.rfptools-body .linkrow {
  display: grid;
  /* Two across, then Open beneath: "Copy as email" needs the width more
     than three-in-a-row needs the symmetry. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  margin-top: 4px;
}
.rfptools-body .linkrow > :last-child { grid-column: 1 / -1; }
.rfptools-body .linkrow .btn {
  width: 100%; text-align: center; margin: 0;
}
.rfptools-body .escalate-note {
  margin: 2px 0 8px; font-size: 12px; color: var(--ink-500);
}

/* Every send, folded away until somebody wants the history. */
.sendlog { display: inline; }
.sendlog summary { cursor: pointer; display: inline; }
.sendlog ol {
  margin: 8px 0 0; padding-left: 20px;
  font-size: 12.5px; color: var(--ink-600);
}
.sendlog li { margin-bottom: 3px; font-variant-numeric: tabular-nums; }


/* A hotel came back on a counter. Whether they moved or held, somebody has to
   look — and holding must not read the same as never replying. */
.counterback {
  margin-top: 10px;
  padding: 8px 11px;
  border-left: 3px solid var(--brand);
  background: var(--brand-50, #FDF0E7);
  border-radius: 0 7px 7px 0;
  font-size: 13px;
}
.counterback b { color: var(--brand-700); }


/* The agreement, attached to the hotel it belongs to. */
.contractfile { margin-top: 8px; font-size: 13px; }
.contractupload {
  display: flex; gap: 9px; align-items: center; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-soft);
}

/* Holding a rate, said out loud on the hotel's form. */
.counterask {
  margin: 0 0 14px;
  padding: 12px 14px;
  border: 2px solid var(--brand);
  border-radius: 9px;
  background: var(--brand-50, #FDF0E7);
}
.counterask > b { color: var(--brand-700); }


/* The request as it will be pasted. Shown rather than written blind to the
   clipboard, so a manager can see what they are about to send. */
.emailpreview {
  margin-top: 12px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  font-size: 14px;
  line-height: 1.55;
  max-height: 420px;
  overflow-y: auto;
}
.emailpreview p { margin: 0 0 10px; }


/* A qualifier belongs under the answer it qualifies. */
.bidterms .qualifier {
  display: block;
  grid-column: 2;
  font-style: normal;
  font-size: 12.5px;
  color: var(--ink-500);
}

/* Every rate block the same shape, whatever it says — one card with a tax
   line and one without read as lopsided however they are coloured. */
.ratebox .ratebox-value { color: #111; }
.ratebox.chosen .ratebox-value { color: var(--brand-700); }
.ratebox.chosen { border-color: var(--brand); }
/* The hotel a coach is confirmed on, marked like every other segment. */
.invcard.isconfirmed {
  border: 2px solid var(--ok-700);
  border-left: 6px solid var(--ok-700);
}
/* An operator's wordmark is long and thin — MTR Western is six times wider
   than it is tall — so it fits by width and the height goes nowhere. More
   width is what makes it bigger. */
.quotebox .logoslot.lg { width: 168px; height: 64px; flex: 0 0 168px; }


/* Several days pass between a coach asking and coming back to choose, and by
   then they have forgotten what they specified. Folded, because somebody who
   remembers does not need it in the way. */
.tripspecs {
  margin: 0 0 18px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
}
.tripspecs > summary {
  padding: 11px 15px;
  cursor: pointer;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--ink-700);
  list-style: none;
}
.tripspecs > summary::-webkit-details-marker { display: none; }
.tripspecs > summary::before {
  content: '▸ ';
  color: var(--ink-400);
}
.tripspecs[open] > summary::before { content: '▾ '; }
.tripspecs[open] > summary { border-bottom: 1px solid var(--line-soft); }
.tripspecs-body { padding: 14px 15px; }

/* A card that folds. The summary keeps the card head's shape so it does not
   read as a different kind of thing once it closes. */
details.card > summary {
  cursor: pointer;
  list-style: none;
}
details.card > summary::-webkit-details-marker { display: none; }
details.card > summary::after {
  content: '▸';
  color: var(--ink-400);
  margin-left: 8px;
}
details.card[open] > summary::after { content: '▾'; }


/* The two facts a coach checks first, set as secondary text under the trip
   name until now. */
.page-sub .tripwhere {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-900);
}
.page-sub .tripwhen {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink-800);
  margin-left: 8px;
  padding-left: 10px;
  border-left: 2px solid var(--brand);
}


/* Once a trip is booked the other hotels are history and the chosen one is
   the page. Folded rather than dropped: a coach who wants to remember what
   else was offered had no way back at all. */
.otherhotels {
  margin-top: 14px;
  border-top: 1px solid var(--line);
  padding-top: 12px;
}
.otherhotels > summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-600);
  list-style: none;
}
.otherhotels > summary::-webkit-details-marker { display: none; }
.otherhotels > summary::before { content: '▸ '; color: var(--ink-400); }
.otherhotels[open] > summary::before { content: '▾ '; }
.otherhotels-body { margin-top: 12px; }
.otherhotels-body .invcard { opacity: .88; }


/* The coach's name as a way in. A form, because impersonating is a POST and
   should not be a link somebody follows from a bookmark. */
.asuser { display: inline; margin: 0; }
.asuser .linkish {
  font: inherit;
  color: var(--brand-700);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0;
}


/* One column. The sidebar held two cards — what the team needs, which the
   specs panel at the top now says, and Cancel, which belongs with the other
   controls. A fixed right margin also capped how wide the hotel list could
   run, so a fourth hotel had nowhere to go. */
.onecol { display: block; }
.onecol > div { min-width: 0; }

/* The controls that used to be scattered: one at the top of the page, one at
   the bottom of the list, one in the sidebar. */
.triptools {
  display: flex;
  gap: 9px;
  align-items: center;
  flex-wrap: wrap;
  margin: 0 0 16px;
}
.triptools .cancelbox { margin-left: auto; }
.triptools .cancelbox .btn { margin: 0; }


/* The agreement, where both sides come back for it once a trip is booked.
   On the hotel card alone it sat among the amenity lines, which is not where
   anybody looks for a document. */
.agreement {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 16px;
  padding: 12px 15px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface-2);
  font-size: 13.5px;
}
.agreement > div { flex: 1; min-width: 0; }
.agreement.ready {
  border-color: var(--brand);
  background: var(--brand-50, #FDF0E7);
}
.agreement.ready b { color: var(--brand-700); }


/* The operator's own agreement with us. Staff only — on ground we are the
   contracting party, and a coach seeing it would be reading a document about
   our liability rather than theirs. */
.vendorcontract {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--line-soft);
  font-size: 13px;
}
.vendorcontract form { display: flex; gap: 8px; margin: 0; margin-left: auto; }


/* Charter or rental, asked once. A coach thinking "we need to get around"
   should not have to know our internal split. */
/* The pitch above the boxes: the same sentence a new coach sees on their
   empty dashboard, because the second time should be familiar. */
.startintro {
  max-width: 760px;
  margin: 0 0 18px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-700);
}

/* Four across. A 760px cap against a 280px minimum could only ever fit two,
   so the menu wrapped into a block of prose. */
.choosegrid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  max-width: 1040px;
}
@media (max-width: 1080px) {
  .choosegrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .choosegrid { grid-template-columns: 1fr; }
}
.choosebox {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  padding: 20px 16px;
  border: 2px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color .12s ease, transform .12s ease;
}
/* The box highlights; the words do not. An underline on hover made the
   heading and the blurb look like separate links inside one control. */
.choosebox:hover {
  border-color: var(--brand);
  transform: translateY(-1px);
}
.choosebox, .choosebox:hover, .choosebox * { text-decoration: none; }
/* Heavier than before. Four narrow boxes read as a menu, and a menu wants
   weight on the words you choose between. */
.choosebox h3 {
  margin: 4px 0 2px; font-size: 16px; font-weight: 700;
  color: var(--ink-900, var(--ink-800));
}
.choosebox p {
  margin: 0 0 10px; font-size: 13px; font-weight: 500;
  color: var(--ink-600); line-height: 1.4;
}
.choosego { font-size: 13px; font-weight: 700; color: var(--brand-700);
            margin-top: auto; }
/* The segment's own mark, the same one it carries everywhere else — bigger
   here, and in the brand colour rather than the grey it wears on a board. */
.choosebox .svcicon { width: 34px; height: 34px; color: var(--brand-600); }
.choosebox .svcicon svg { width: 26px; height: 26px; }


/* The sequence after a coach books: ask the winner for their agreement,
   upload it, then confirm. Laid out as steps because it is one. */
.confirmsteps {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-top: 14px; padding: 11px 13px;
  border: 2px solid var(--brand);
  border-radius: 9px;
  font-size: 13px;
}
.confirmsteps form { margin: 0; }


/* Telling the coach, when a manager decides to. Nothing here fires on its
   own, so it reads as a set of things you can do rather than a status. */
.tellcoach {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-top: 14px; padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface-2);
  font-size: 13px;
}
.tellcoach form { margin: 0; }
.tellcoach-head {
  font-weight: 700; font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-500);
}


/* A form a coach walks straight down. Two columns would make them choose
   where to look at every step, and it collapses on a laptop anyway — so one
   column, capped wide enough that a field is not a mile long. */
.oneform { max-width: 980px; }
.oneform .field-row { gap: 14px; }


/* The number a coach quotes on the phone. */
.tripref {
  margin-left: auto;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-500);
}

/* What the coach calls the trip, tucked to the right of our number for it.
   Quiet until used: an empty one is a grey "+ trip name" that a coach can
   ignore for a season, and a filled one reads as a label rather than a
   control. */
.tripname { display: inline-flex; align-items: center; margin-left: 14px; }
.tripname-open {
  background: none; border: 0; padding: 2px 4px; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--ink-700);
  border-bottom: 1px dashed var(--line);
}
.tripname-open:hover { color: var(--brand-700); border-bottom-color: var(--brand); }
.tripname-open .muted { font-size: 12px; color: var(--ink-300); }
.tripname-read { font-size: 12px; color: var(--ink-500); }
.tripname-form { display: inline-flex; gap: 6px; align-items: center; }
.tripname-form input { font-size: 13px; padding: 4px 8px; width: 190px; }

/* The same name where our own people see it — read-only, beside the trip it
   belongs to, so a coach quoting their own code on the phone can be found. */
.coachname {
  margin-left: 8px; padding: 1px 7px; border-radius: 4px;
  background: var(--surface-2); border: 1px solid var(--line-soft);
  font-size: 12px; color: var(--ink-500);
}


/* Where you are in the trip, and the way to its other parts.

   Two rows. One long line pushed the segments to the right margin, where
   they read as text trailing off the trip name rather than as things you
   click. */
.tripbar { margin: 0 0 18px; }
/* The bar and its right-hand column. Constant through every stage: status,
   the confirmation when there is one, and who to ring. */
/* Content on the left, a rail on the right. The rail used to be wedged into
   the bar, which made it a sidebar on a page with no sidebar — the hotel card
   ran the full width underneath it and nothing lined up. */
.segwrap {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  max-width: 1280px;
}
/* The rail is written first so a template can close cleanly around the main
   column; order puts it on the right where it belongs, and drops it below on
   a narrow screen. */
.segmain { flex: 1; min-width: 0; order: 1; }
.segrail {
  flex: 0 0 280px; order: 2;
  display: flex; flex-direction: column; gap: 12px;
  position: sticky; top: 18px;
}
.segrail .btn { width: 100%; }
@media (max-width: 1000px) {
  .segwrap { flex-wrap: wrap; }
  .segrail { flex-basis: 100%; position: static; }
}
.tripbar-line {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-bottom: 8px;
  font-size: 13px;
}
.tripbar-back { font-weight: 600; color: var(--ink-700); text-decoration: none; }
.tripbar-back:hover { color: var(--brand-700); }
/* The headline. It was a 15px span beside a page title saying the same
   thing; now it is the title. */
.tripbar-name {
  margin: 0 0 3px;
  font-size: 21px; font-weight: 700;
  letter-spacing: -.02em;
  color: var(--ink-900);
}
.tripbar-detail {
  margin: 0 0 12px;
  font-size: 13.5px;
  color: var(--ink-500);
}
.tripbar-ref { color: var(--ink-500); font-variant-numeric: tabular-nums; }

.tripbar-box {
  display: flex; align-items: stretch; gap: 8px; flex-wrap: wrap;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2);
}
.tripbar-seg {
  display: flex; flex-direction: column; gap: 1px;
  padding: 6px 13px; border-radius: 7px;
  text-decoration: none; color: var(--ink-800);
  border: 1px solid var(--line); background: var(--surface);
  min-width: 86px;
}
.tripbar-seg:hover { border-color: var(--brand); }
.tripbar-seg.here {
  background: var(--brand); color: #fff; border-color: var(--brand);
}
.tripbar-label { font-size: 13px; font-weight: 600; }
/* Underneath, not beside: "Groundconfirmed" read as one word. */
/* Colour as well as the word, matching the icons: a coach reads the state
   the same way wherever it appears. */
.tripbar-state { font-size: 11px; opacity: .85; }
.tripbar-state.state-pending { color: var(--ink-500); }
.tripbar-state.state-rates { color: #B45309; }
.tripbar-state.state-booked { color: #1D4ED8; }
.tripbar-state.state-confirmed { color: var(--ok-700); }
.tripbar-state.state-past { color: var(--ink-500); }
.tripbar-seg.here .tripbar-state { color: inherit; opacity: .8; }
.tripbar-gap { width: 10px; }
.tripbar-add {
  display: flex; align-items: center;
  padding: 6px 12px; border-radius: 7px; font-size: 12.5px;
  text-decoration: none; color: var(--ink-500);
  border: 1px dashed var(--line);
}
.tripbar-add:hover { color: var(--brand-700); border-color: var(--brand); }
.tripbar-box .btn { align-self: center; }


/* A confirmation is a document, not a page — there was no way back except
   the browser. Hidden on paper, where a navigation control is noise. */
.backbadge {
  position: fixed;
  top: 14px; left: 14px;
  z-index: 50;
  padding: 7px 13px;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
  font-size: 13px; font-weight: 600;
  color: var(--ink-700); text-decoration: none;
}
.backbadge:hover { border-color: var(--brand); color: var(--brand-700); }
@media print { .backbadge { display: none !important; } }


/* Filter, never re-sort. A coach thinks about their season chronologically
   whatever they are looking at. */
.tripfilter {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 14px;
  font-size: 13px;
}
.tripfilter .spacer { flex: 1; }
.tripfilter-pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-700);
  text-decoration: none;
}
.tripfilter-pill:hover { border-color: var(--brand); }
.tripfilter-pill.on {
  background: var(--brand); color: #fff; border-color: var(--brand);
}
.tripfilter-n {
  font-size: 11.5px; font-variant-numeric: tabular-nums; opacity: .75;
}


/* The trip's shape, beside its route. One way and round trip are different
   jobs and it used to sit in the right-hand column, read after the decision
   rather than before it. */
.tripshape {
  display: inline-block;
  margin-left: 8px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 12px; font-weight: 600;
  color: var(--ink-600);
  vertical-align: middle;
}


/* What was on the table before it was decided. Folded rather than deleted —
   a history you cannot see is a question you cannot answer later. */
.otheropts { margin: 10px 0 0; }
.otheropts > summary {
  cursor: pointer; font-size: 13px; color: var(--ink-600);
  padding: 6px 0;
}
.otheropts > summary:hover { color: var(--brand-700); }


/* The mark beside a hand-typed flight, so it looks like the ones the lookup
   found. */
.manuallogo { display: flex; align-items: center; min-height: 34px; }
.manuallogo .logoimg { max-height: 26px; max-width: 90px; }


/* The airport list on a hand-entered flight. */
.apdrop {
  position: absolute; z-index: 40; left: 0; right: 0; top: 100%;
  margin-top: 3px;
  max-height: 240px; overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0,0,0,.1);
  min-width: 260px;
}
.apdrop .apopt {
  display: block; width: 100%; text-align: left;
  padding: 7px 11px; border: 0; background: none; cursor: pointer;
  font-size: 13px;
}
.apdrop .apopt:hover { background: var(--surface-2); }


/* A next-day arrival. A 9:48pm departure landing at 6:20am is tomorrow, and a
   bus meeting them at the wrong dawn is the cost of not saying so. */
.nextday {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--danger-50, #FEF2F2);
  color: var(--danger-700, #B91C1C);
  font-size: 11.5px; font-weight: 700;
}


/* The dates and the rooms, where a coach is comparing rates. */
.stayline {
  margin: 0 0 14px;
  font-size: 15px; font-weight: 700;
  color: var(--ink-900);
}


/* A bid link, shown rather than silently copied. */
.showlink {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 8px; padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-2);
}
.showlink form { margin: 0; }
.linkbox {
  flex: 1; min-width: 240px;
  font-size: 12.5px; font-family: ui-monospace, monospace;
  padding: 6px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
}


/* My schools, or everyone's. */
.minefilter { display: flex; gap: 8px; margin: 0 0 14px; font-size: 13px; }
.minefilter a {
  padding: 5px 13px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-700); text-decoration: none;
}
.minefilter a.on {
  background: var(--brand); color: #fff; border-color: var(--brand);
}


/* Coaches with released rates nobody has told them about. */
.totell {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin: 0 0 14px; padding: 9px 12px;
  border: 1px solid var(--warn-700, #B45309);
  border-radius: 9px;
  background: var(--warn-50, #FFFBEB);
  font-size: 13px;
}
.totell form { margin: 0; }
.totell-head {
  font-weight: 700; font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--warn-700, #B45309);
}

/* Reminders on a settled stay. */
.staynotes { display: flex; flex-direction: column; gap: 6px; }
.staynotes form { margin: 0; }
.staynotes .muted { font-size: 11.5px; margin-top: -3px; }


/* Brand families with something in range, and how far through the list. */
.brandfilter { display: flex; gap: 7px; flex-wrap: wrap; margin: 0 0 14px;
               font-size: 13px; }
.brandfilter a {
  padding: 5px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-700); text-decoration: none;
}
.brandfilter a.on {
  background: var(--brand); color: #fff; border-color: var(--brand);
}
.showmore { display: flex; gap: 12px; align-items: center;
            margin: 18px 0 0; font-size: 13px; }


/* A hotel we already work with. Quiet on purpose — a record, not a nudge. */
.partnermark {
  color: var(--brand);
  font-weight: 700;
  font-size: 15px;
  vertical-align: super;
  line-height: 1;
}


/* Signed on paper. The lines have to survive a printer, so they are borders
   rather than underscores — a row of underscores wraps and breaks apart. */
.confsign {
  margin: 26px 0 0;
  padding: 16px 18px;
  border: 1px solid var(--ink-900);
  border-radius: 6px;
  break-inside: avoid;
}
.confsign-head {
  font-weight: 700; font-size: 12px; letter-spacing: .06em;
  text-transform: uppercase; margin-bottom: 8px;
}
.confsign p { margin: 0 0 20px; font-size: 13.5px; }
.confsign-lines { display: flex; gap: 26px; align-items: flex-end; }
.confsign-lines > div { flex: 1; }
.confsign-date { flex: 0 0 160px !important; }
.confsign-lines span {
  display: block; font-size: 11.5px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-500); margin-bottom: 26px;
}
.confsign-lines i { display: block; border-bottom: 1px solid var(--ink-900); }

@media print {
  .confsign { border-color: #000; }
  .confsign-lines i { border-bottom-color: #000; }
}


/* Paperwork rows: the ticks and the two "it arrived" buttons. */
.chk { display: inline-flex; align-items: center; gap: 5px;
       margin-right: 10px; font-size: 13px; }
.gotrow { display: flex; gap: 6px; margin-top: 7px; }
.gotrow form { margin: 0; }


/* The way back to a coach's page once the strips have cleared. */
.toldlink { margin: 0 0 12px; font-size: 13px; }


/* A record rather than work: folded by default, and open when there is
   nothing else on the page. */
.toldbox > summary {
  cursor: pointer; padding: 13px 18px;
  display: flex; gap: 8px; align-items: baseline;
}
.toldbox > summary::-webkit-details-marker { display: none; }
.toldbox > summary::before {
  content: '\25B8'; color: var(--ink-500); font-size: 12px;
}
.toldbox[open] > summary::before { content: '\25BE'; }
.toldbox[open] > summary { border-bottom: 1px solid var(--line); }


/* Brand standards on a hotel card. A tick means yes; nothing means anything
   else, which is why there is no greyed-out "no". */
.standards {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.standards li {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px 3px 8px;
  border-radius: 999px;
  background: var(--ok-50, #F0FDF4);
  border: 1px solid var(--ok-200, #BBF7D0);
  color: var(--ok-800, #166534);
  font-size: 12.5px; font-weight: 600;
}
.standards li::before {
  content: '\2713';
  font-weight: 700;
}

/* Reassurance, not a claim — so it sits below the ticks and stays out of
   their way. */
.maybe {
  margin: 9px 0 0;
  font-size: 12px;
  color: var(--ink-400);
}


/* A contact row that is its own form. Correcting a typo used to mean
   removing the contact and adding it back, which threw away its history. */
.ctrow { display: flex; gap: 4px; margin: 0 0 3px; }
.ctrow input, .ctwide {
  font-size: 12px; padding: 4px 6px;
  border: 1px solid var(--line); border-radius: 5px;
  background: var(--surface);
}
.ctwide { width: 100%; max-width: 230px; }


/* What happened to the address we wrote to, on the RFP row rather than three
   clicks away on the hotel. */
.dlv {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin: 6px 0 0; font-size: 12.5px;
}
.dlv form { margin: 0; }
.dlv-what {
  display: inline-flex; padding: 2px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600;
  background: var(--surface-2); color: var(--ink-500);
}
.dlv.bad .dlv-what { background: #F0605F; color: #fff; }


/* Postmark's own palette, so its Activity screen and this row read the same
   when somebody has both open: pale green for processed, solid green for
   delivered, teal for opened, red for a bounce. */
.dlv-step {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 2px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600;
  background: #E7F5E4; color: #4B7F3E;
}
.dlv-step.on { background: #5B9A2E; color: #fff; }
.dlv-step.opened { background: #12A5B5; color: #fff; }
.dlv-step time { font-weight: 500; opacity: .85; }


/* One press for every priced fare. Sits above the legs because it is the
   default action; the per-leg buttons are the exception. */
.releaseall {
  display: flex; gap: 10px; align-items: center;
  margin: 0 0 16px; font-size: 13px;
}

/* A connection short enough to be a problem with twenty-five players and
   their bags. */
.layover-tight { color: var(--danger-700, #B91C1C); }
.atrisk {
  padding: 1px 7px; border-radius: 999px;
  background: var(--danger-50, #FEF2F2); color: var(--danger-700, #B91C1C);
  font-size: 11px; font-weight: 700;
}
.dur { font-weight: 500; }


/* None of these work. Below the fares, not beside them — most of the time
   one of them is fine. */
.moreopts { margin: 10px 0 0; font-size: 13px; }
.moreopts > summary { cursor: pointer; color: var(--ink-500); }
.moreopts textarea {
  width: 100%; margin: 8px 0 6px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 7px;
  font: inherit; font-size: 13px;
}

/* Priced after they asked for more, so it is new to them. */
.newopt {
  padding: 1px 8px; border-radius: 999px;
  background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 700;
}

/* The fare box, once flights are in. Eight seconds and it stops — a box that
   animates for ever is a box nobody sees. */
@keyframes fare-wants-you {
  0%, 100% { box-shadow: 0 0 0 0 rgba(196,83,10,0); }
  50%      { box-shadow: 0 0 0 4px rgba(196,83,10,.28); }
}
input[data-fare-pulse] {
  animation: fare-wants-you 1.4s ease-in-out 6;
  border-color: var(--brand);
}
@media (prefers-reduced-motion: reduce) {
  input[data-fare-pulse] { animation: none; }
}


/* What a coach said when none of the fares worked, where the pricing
   happens. It used to arrive by phone. */
.moreasked {
  margin: 0 0 12px; padding: 9px 12px;
  border-left: 3px solid var(--brand);
  background: var(--surface-2);
  border-radius: 0 7px 7px 0;
  font-size: 13px;
}
.moreasked > div { margin-top: 4px; }


/* Typed details on the connecting-leg fold. Behind a summary because the
   lookup is the path that gives real schedules and a flight id for alerts. */
.segmanual { margin-top: 8px; }
.segmanual > summary {
  cursor: pointer; font-size: 12.5px; color: var(--ink-400);
}
.segmanual .hint { margin-top: 6px; }


/* Adding a vendor, once some are already picked. Folded, because from then on
   the page is about managing quotes and an open search is two weeks of
   noise. */
.addvendors { margin: 0 0 18px; }
.addvendors > summary {
  cursor: pointer; padding: 11px 16px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  font-weight: 600; font-size: 13.5px;
}
.addvendors[open] > summary { margin-bottom: 10px; }


/* What they asked for, beside the reference. The first thing read on opening
   a sourcing page, and it used to be four cards down. */
.askline {
  margin: 4px 0 0; font-size: 13px; font-weight: 600;
  color: var(--ink-700, var(--ink-800));
}
/* The coach's own number, next to the vendor one. Quieter, because the
   vendor reference is what most of this page is about. */
.refchip.tripref {
  background: var(--surface-2); color: var(--ink-500);
  border: 1px solid var(--line);
}


/* Receipts. What is in, and what is still expected — a coach filing two days
   after a trip needs to know whether to wait or to chase. */
.rcpt {
  padding: 11px 0; border-bottom: 1px solid var(--line);
}
.rcpt:last-child { border-bottom: 0; }
.rcpt-waiting { opacity: .72; }
.rcpt-file {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  margin-top: 4px; font-size: 13px;
}
.rcpt-file form { margin: 0; }
.rcptadd {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  font-size: 13px;
}
.rcptadd select, .rcptadd input[type="text"] {
  padding: 6px 9px; border: 1px solid var(--line); border-radius: 6px;
  font: inherit; font-size: 13px;
}


.rcptlink { margin: 0 0 12px; font-size: 13px; }


/* Filing a batch: what has gone in so far, so six receipts feel finished. */
.filedlist { font-size: 13px; margin-bottom: 10px; }
.filedlist > div { margin-top: 4px; }
.hint.ok { color: var(--ok-700, #15803D); font-weight: 600; }
.hint.bad { color: var(--danger-700, #B91C1C); font-weight: 600; }


/* A coach's trips, as a list. Five opened at once is a long page and they
   usually want one. */
.rcptrow {
  display: flex; gap: 14px; align-items: center;
  padding: 12px 18px; border-bottom: 1px solid var(--line);
}
.rcptrow:last-child { border-bottom: 0; }
.rcptrow-main { flex: 1; min-width: 0; }
.rcptrow-side {
  display: flex; gap: 10px; align-items: center; white-space: nowrap;
  font-size: 13px;
}


/* One icon per segment, three states. Grey is expected and nothing in;
   yellow is a deposit filed with the final still to come; green is settled.
   A deposit is a state of its segment, not a row of its own — that is how a
   coach reads it. */
.segicons { display: inline-flex; gap: 5px; align-items: center; }
.segicon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 27px; height: 27px; border-radius: 50%;
  border: 1px solid var(--line);
}
.segicon-due  { color: var(--ink-300, #A1A1AA); background: var(--surface-2); }
.segicon-part { color: #92400E; background: #FEF3C7; border-color: #FCD34D; }
.segicon-in   { color: #166534; background: #DCFCE7; border-color: #86EFAC; }


/* The trip a receipt belongs to, at the weight it deserves: "Santa Clara" is
   two trips a season and the dates are what tell them apart. */
.rcpttrip {
  margin: 3px 0 2px; font-size: 16px; font-weight: 700;
  color: var(--ink-900, var(--ink-800));
}
.rcptback { margin: 0 0 10px; font-size: 13px; }


/* Whose trip this is, when a super user reads a whole school's season. */
.trip-sport {
  margin-left: 8px; padding: 1px 8px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-500);
  font-size: 11.5px; font-weight: 600;
}


/* A rental quote's lines. Quantity, vehicle, price each — the total is the
   sum of them and is never typed, so the two cannot disagree. */
.rentlines { display: flex; flex-direction: column; gap: 6px; }
.rentline { display: flex; gap: 8px; }
.rentline input {
  padding: 7px 9px; border: 1px solid var(--line); border-radius: 6px;
  font: inherit; font-size: 13px;
}
.rentline input[name="line_vehicle"] { flex: 1; }
.rentline .qty { width: 62px; }
.rentline .num { width: 110px; text-align: right; }


.rentquote { margin: 6px 0 0; font-size: 13px; border-collapse: collapse; }
.rentquote td { padding: 2px 10px 2px 0; }
.rentquote td:last-child { padding-right: 0; font-weight: 600; }


/* Sending a rental quote: one press for the lot, and a mark on anything the
   coach has not seen. */
.sendall { margin: 0 0 14px; }
.sendall form { display: flex; gap: 10px; align-items: center; }
.notsent {
  display: block; text-align: center; font-size: 11.5px; font-weight: 600;
  color: var(--ink-400); padding: 5px 0;
}
.otherveh { flex: 1; }


/* Three states on the rentals page. Quiet when empty — a row of zeroes
   should not read as work. */
.qbox {
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 16px; border-radius: var(--radius-lg);
  background: var(--surface); border: 1px solid var(--line);
  text-decoration: none; color: inherit;
}
.qbox:hover { border-color: var(--brand); }
.qbox-n { font-size: 26px; font-weight: 700; line-height: 1.1; }
.qbox-l { font-size: 13px; font-weight: 600; }
.qbox-note { font-size: 11.5px; color: var(--ink-400); }
.qbox.quiet { opacity: .62; }
.qbox.quiet .qbox-n { color: var(--ink-400); }


/* A rental option's vehicles, beside the vendor: two Enterprise cards differ
   by what is in them, not by the name at the top. */
/* What differs between two cards from the same vendor, so it carries the
   weight the name used to. */
.optveh { font-weight: 700; color: var(--ink-900, var(--ink-800));
          font-size: 15px; }
.ratebox-each {
  font-size: 11.5px; color: var(--ink-500); font-weight: 500;
}


.drivernum { font-size: 13px; color: var(--ink-500); padding-top: 8px; }


.drivers { font-size: 13px; display: flex; flex-direction: column; gap: 3px; }


/* When a coach gets the keys and gives them back. A price without its dates
   is half an answer. */
.optwhen { font-size: 13px; color: var(--ink-700, var(--ink-800));
           font-weight: 600; margin: 2px 0 2px; }

/* Rental marks larger than the others. A coach recognises Enterprise by its
   shape before they read the word, and at hotel-brand size it was a smudge. */
.logoslot.rental { width: 92px; height: 46px; }
.logoslot.rental img { max-height: 40px; }


/* Prices we did not take. Folded, and openable either side — a vendor sells
   out and the second price is what somebody reaches for. */
.otheropts { margin-top: 10px; }
.otheropts > summary {
  cursor: pointer; padding: 10px 0; font-size: 13px; font-weight: 600;
  color: var(--ink-500);
}
.quietopt { opacity: .78; }

/* What a coach is committing to, on the form they commit on. */
.bookwhat {
  display: flex; gap: 12px; align-items: center;
  padding: 12px 14px; margin: 0 0 14px;
  background: var(--surface-2); border-radius: var(--radius-lg);
}
.booktotal { font-size: 18px; }


/* Driver rows on a request: two to start, more on asking. A coach needing
   four vans should not meet four empty pairs before deciding anything. */
.driverrow.hidden { display: none; }


.cancelrow {
  display: flex; gap: 10px; align-items: center;
  max-width: 760px; margin: 18px 0 0; font-size: 13px;
}


/* A staff sidebar outgrows a short window, and the two things that fall off
   the bottom are the two that matter: Sign out, and knowing where you are.
   The column and its full height are set above; this is the part that makes
   the middle of it move instead of the whole thing. */
.nav > .navscroll {
  flex: 1; min-height: 0; overflow-y: auto;
  /* Room for a scrollbar without the links shifting under it. */
  scrollbar-gutter: stable;
}


/* A pick that did not go through. A coach who thinks they selected a hotel
   and did not is worse off than one whose page jumped. */
.pickerr {
  margin-top: 6px; font-size: 12px; font-weight: 600;
  color: var(--danger-700, #B91C1C);
}


/* Picking a hotel is a tick, not a button. This is a multi-select: eight
   ticks with three on reads at a glance, where eight buttons alternating
   Select and Remove does not. */
.hpick {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 6px 8px; border-radius: var(--radius-lg);
  border: 1px solid var(--line); cursor: pointer;
  font-size: 12px; font-weight: 600; color: var(--ink-500);
  user-select: none;
}
.hpick input { width: 19px; height: 19px; accent-color: var(--brand-600);
               cursor: pointer; }
.hpick:hover { border-color: var(--brand-600); }
.hpick.on {
  border-color: var(--brand-600); background: var(--brand-50);
  color: var(--brand-700, var(--brand-600));
}
/* At the cap: reads as full rather than broken. */
.hpick:has(input:disabled) { opacity: .5; cursor: default; }
.hpick:has(input:disabled):hover { border-color: var(--line); }


/* Swap a bus photo without losing its place or its caption. */
.busthumb-swap { position: absolute; left: 6px; bottom: 6px; }
.busthumb-swap label {
  display: inline-block; cursor: pointer;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(0,0,0,.62); color: #fff;
  font-size: 11px; font-weight: 600;
}
.busthumb-swap label:hover { background: rgba(0,0,0,.8); }


/* Work that is finished reads as a fact, not a button. */
.donestate {
  margin: 0; padding: 9px 12px; border-radius: var(--radius-lg);
  background: var(--ok-50); color: #166534;
  font-size: 13px; font-weight: 600; text-align: center;
}


/* A coach quote is a trip total, not a nightly rate — four or five digits
   where a hotel shows three. Smaller, and the box grows with it. */
.quoteprice { min-width: 132px; text-align: right; }
.quoteprice .ratebox-value { font-size: 19px; white-space: nowrap; }


/* The return, stated rather than asked. Bold and black because it is the
   answer; the way out of it is quiet because most people do not need it. */
.reversed {
  margin: 0 0 14px; font-size: 15px;
  color: var(--ink-900, var(--ink-800));
}
.reversed b { font-weight: 700; }
.reversed .linkish { margin-left: 10px; font-size: 13px; font-weight: 600; }

/* The schedule, folded but saying what is inside. */
.schedfold > summary {
  cursor: pointer; padding: 14px 18px; font-size: 14px;
}
.schedfold > summary b { font-weight: 700; }


/* A neighbouring airport, offered with a way to say no. Without the × a
   suggestion nobody wants sits under the box looking like something still to
   be dealt with. */
.apoffer { display: flex; align-items: stretch; gap: 0; }
.apoffer .apopt { flex: 1; }
.apdismiss {
  border: 0; background: none; cursor: pointer;
  padding: 0 10px; font-size: 16px; line-height: 1;
  color: var(--ink-400);
}
.apdismiss:hover { color: var(--ink-800); }


/* Working as somebody, beside the name it acts on. A nameless button in a
   last column made a super user check which row they were on first. */
.asbtn { white-space: nowrap; }
.asbtn:hover { border-color: var(--brand); color: var(--brand-700); }
.lastseen { font-size: 11.5px; margin-top: 2px; }


/* The whole row opens the trip. Four words of link text is a small target on
   a phone, and the link is what the page exists for. */
.rcptrow-link {
  text-decoration: none; color: inherit;
  transition: background .12s ease;
}
.rcptrow-link:hover { background: var(--surface-2); }
.rcptrow-link:hover .rcpttripname { color: var(--brand-700); }
.rcpttripname {
  font-size: 15px; font-weight: 700;
  color: var(--ink-900, var(--ink-800));
}
.rcptchev { color: var(--ink-300); flex: 0 0 auto; }
.rcptrow-link:hover .rcptchev { color: var(--brand-600); }


/* The bid form in sections. A sales manager works down it in parts, and a
   single column of twenty fields gives no sense of how much is left. */
.bidsec { padding: 0 0 20px; }
.bidsec + .bidsec { border-top: 1px solid var(--line); padding-top: 20px; }
.bidsec-head {
  display: flex; align-items: center; gap: 10px; margin: 0 0 14px;
}
.bidsec-head h4 {
  margin: 0; font-size: 15px; font-weight: 700;
  color: var(--ink-900, var(--ink-800));
}
/* Quiet until earned: a tick that is always there says nothing. */
.bidsec-tick {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface-2); color: transparent;
  font-size: 12px; font-weight: 700;
  transition: background .15s ease, color .15s ease;
}
.bidsec-tick.on { background: #DCFCE7; color: #166534; }


/* How to reach a hotel, under its address on the RFP card. A prospect with
   no contact has to be rung, and the number was two pages from where that
   decision gets made. */
.invcard-reach {
  margin-top: 3px; font-size: 12.5px;
  display: flex; gap: 7px; flex-wrap: wrap; align-items: baseline;
}
.invcard-reach span { color: var(--ink-300); }


/* A Google match that does not agree with the name we hold. Quiet, but
   there: a number belonging to the wrong Washington Marriott is worse than
   no number at all. */
.reachwarn {
  font-size: 11.5px; color: #92400E;
  background: #FEF3C7; padding: 1px 7px; border-radius: 999px;
}




/* Import mode, in the nav so it is never out of sight.
   Off it is a quiet line nobody reads; on it is the loudest thing on the
   page, because a manager who forgets it is on watches every RFP appear to
   send and none arrive. */
.importswitch { margin: 10px 12px 0; }
.importswitch button {
  width: 100%; cursor: pointer; text-align: left;
  padding: 7px 10px; border-radius: var(--radius);
  border: 1px solid rgba(255,255,255,.14); background: none;
  color: rgba(255,255,255,.4); font-size: 11.5px; font-weight: 600;
}
.importswitch button:hover { color: rgba(255,255,255,.7); }
.importswitch.on button {
  background: #F59E0B; border-color: #F59E0B; color: #1F2937;
  font-weight: 700;
}
.importswitch.on button::before { content: '● '; }


/* Sign in, sized for a thumb.
   16px on the inputs is not taste: below it, Safari on an iPhone zooms the
   whole page in when the field is tapped, and the coach has to pinch back
   out to find the button. */
.signin .field input { font-size: 16px; padding: 11px 12px; }
/* In the stylesheet rather than inline: an inline style beats any rule a
   phone layout could apply, so the button could never go full width. */
.signin-foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px;
}
.signin .card-foot .btn { padding: 10px 22px; font-size: 15px; }

/* The show button sits inside the field's right edge rather than beside it,
   so both boxes stay the same width and line up. */
.pwfield { position: relative; }
.pwfield input { padding-right: 64px; }
.pwshow {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  border: 0; background: none; cursor: pointer;
  padding: 6px 8px; border-radius: var(--radius);
  font-size: 12.5px; font-weight: 700; color: var(--brand-700);
}
.pwshow:hover { background: var(--surface-2); }

@media (max-width: 900px) {
  /* A button the width of the card on a phone: the easiest thing on the
     screen to hit, which is right for the one thing the page is for. */
  .signin .card-foot { flex-direction: column-reverse; align-items: stretch; }
  .signin .card-foot .btn { width: 100%; justify-content: center; }
  .signin .card-foot .hint { text-align: center; }
}


/* Text pasted from a hotel's contract. Line breaks kept: cancellation terms
   are usually a list, and a paragraph that collapses them reads as one long
   run-on clause a school cannot find its deadline in. */
.confprose { margin: 0 0 14px; white-space: pre-line; line-height: 1.55;
             font-size: 13.5px; }

/* A revised document says so, above everything else. */
.confrev {
  margin: 0 0 12px; padding: 7px 12px; border-radius: var(--radius);
  background: #FFFBEB; border: 1px solid #FDE68A; color: #92400E;
  font-size: 12.5px; font-weight: 600;
}


/* A booked flight option: the quote is the record of what the coach agreed
   to, greyed and locked; the contracted fare is the live figure the
   confirmation prices from. */
input.fare-locked {
  background: var(--surface-2); color: var(--ink-3);
  border-style: dashed; cursor: not-allowed;
}
input.fare-live {
  border-color: var(--brand-600);
  box-shadow: 0 0 0 3px rgba(234, 88, 12, .12);
  font-weight: 600;
}


/* Add to this trip, under a segment's title. Quiet enough not to compete
   with the page, plain enough to find. */
.addstrip {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 6px 0 14px;
}
.addstrip-label { font-size: 12.5px; color: var(--ink-3); margin-right: 2px; }


/* "+ Add" on a closed capsule: opens it to the add row. Hidden once open,
   where the row itself is showing — and where clicking the summary would
   close the capsule rather than open it. */
.trip-addhint {
  font-size: 12px; font-weight: 700; color: var(--brand-700);
  padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface);
  margin-right: 8px;
}
.trip-addhint:hover { border-color: var(--brand-600); }
details.trip[open] .trip-addhint { display: none; }


/* A new trip whose dates meet one the coach already has. Under the dates,
   never a pop-up, and it never blocks typing. */
.overlapnote {
  margin: 4px 0 14px; padding: 11px 14px; border-radius: var(--radius-lg);
  background: #FFFBEB; border: 1px solid #FDE68A; color: #78350F;
  font-size: 13.5px; display: grid; gap: 8px; max-width: 640px;
}
.overlapnote[hidden] { display: none; }
.overlaprow { display: flex; flex-wrap: wrap; align-items: center;
              justify-content: space-between; gap: 8px; }
.overlapnote .btn { justify-self: start; }


/* The coach's way to change a flight request, while options are not out. */
.editreq { display: flex; align-items: center; gap: 10px; margin: -4px 0 14px;
           font-size: 13px; }
/* The desk's notice that a coach changed a request being priced. */
.editnote { white-space: pre-line; }


/* Free tickets, folded under a link on the flight confirmation form. */
.freefold { margin: 0 0 12px; }
.freefold > summary {
  cursor: pointer; display: inline-block; list-style: none;
  font-size: 13px; font-weight: 600; color: var(--brand-700);
}
.freefold > summary::-webkit-details-marker { display: none; }
.freefold > summary::before { content: '+ '; }
.freefold[open] > summary::before { content: '\2212  '; }


/* The email a manager is about to send, shown as the recipient sees it.
   In a frame, so its own styling cannot reach the page around it. */
.emailpane {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  width: min(680px, calc(100vw - 36px)); max-height: calc(86vh / var(--zoom));
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: 0 18px 50px rgba(0,0,0,.22);
}
.emailpane[hidden] { display: none; }
.emailpane-head, .emailpane-foot, .emailpane-subject {
  display: flex; align-items: center; gap: 8px; padding: 10px 14px;
}
.emailpane-head { border-bottom: 1px solid var(--line-soft); }
.emailpane-subject { border-bottom: 1px solid var(--line-soft); font-size: 13px; }
.emailpane-subject input { flex: 1; }
.emailpane-subject label { color: var(--ink-3); font-size: 12px; }
.emailpane-to { font-size: 12.5px; }
.emailpane-body { flex: 1; min-height: 320px; width: 100%; border: 0;
                  background: #f4f4f5; }
.emailpane-foot { border-top: 1px solid var(--line-soft); }
@media (max-width: 760px) {
  .emailpane { right: 8px; left: 8px; bottom: 8px; width: auto; }
}


/* Typing a flight change in by hand, folded inside its flight's row. */
.segedit { width: 100%; margin: 4px 0 2px; }
.segedit > summary { cursor: pointer; list-style: none; font-size: 12px;
                     font-weight: 600; color: var(--brand-700); }
.segedit > summary::-webkit-details-marker { display: none; }
.segedit > summary::before { content: '\270E  '; }
.segedit form { padding: 8px 0 2px; }


/* See it, then send it: the reminders on an RFP card. */
.staynote-row { display: flex; gap: 6px; align-items: stretch; }
.staynote-row form { flex: 1; }


/* The SelectHospitality confirmation's boxes, folded once it is issued. */
.hconf-fold > summary {
  cursor: pointer; list-style: none; padding: 10px 16px;
  font-size: 13px; font-weight: 600; color: var(--brand-700);
}
.hconf-fold > summary::-webkit-details-marker { display: none; }
.hconf-fold > summary::before { content: '+ '; }
.hconf-fold[open] > summary::before { content: '\2212  '; }


/* "AP" under the bus icon: an airport transfer and a coach kept with the
   team look the same otherwise, and a coach needs to know which. */
.svcmark { display: inline-flex; flex-direction: column; align-items: center;
           line-height: 1; }
.svcmark-tag {
  margin-top: 2px; font-size: 9px; font-weight: 800; letter-spacing: .06em;
  color: var(--ink-3);
}


/* A cancelled half of a round-trip transfer: struck through, still listed,
   because what was dropped matters as much as what stands. */
tr.struck td { text-decoration: line-through; color: var(--ink-3); }
tr.struck td:last-child { text-decoration: none; }


/* What a list is filtered to, and the way out of it. */
.filterchip {
  display: flex; align-items: center; gap: 10px; margin: 0 0 12px;
  padding: 8px 12px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line-soft);
  font-size: 13px;
}


/* Changing the dates of a bus, folded on both the coach's page and ours. */
.dateedit { margin: 4px 0 14px; }
.dateedit > summary { cursor: pointer; list-style: none; font-size: 13px;
                      font-weight: 600; color: var(--brand-700); }
.dateedit > summary::-webkit-details-marker { display: none; }
.dateedit > summary::before { content: '\1F4C5  '; }
.dateedit form { padding: 10px 0 2px; }
/* A quote given before the dates moved. */
.stalequote { color: #92400E; font-size: 12px; font-weight: 600; }


/* Options after the first, as one-line rows. Four priced options on a leg
   ran to four full blocks, and comparing them meant scrolling past the one
   you wanted. */
.optfold { border: 1px solid var(--line); border-radius: 8px;
           margin: 0 0 8px; background: var(--surface); }
.optfold > summary {
  cursor: pointer; list-style: none; padding: 10px 14px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 13.5px;
}
.optfold > summary::-webkit-details-marker { display: none; }
.optfold > summary::before { content: '▸'; color: var(--ink-3); }
.optfold[open] > summary::before { content: '▾'; }
.optfold[open] > summary { border-bottom: 1px solid var(--line-soft); }
.optfold-fare { margin-left: auto; font-weight: 700; }
.optfold .optcard { border: 0; margin: 0; }


/* Confirmed, on a coach's own pages: a thick green edge on a white card.
   The same mark on a hotel, a bus, a car and a flight, so "confirmed" looks
   like one thing wherever it appears. Not on the capsule — a band on every
   row there would fight the logos. */
.card.isconfirmed {
  border: 2px solid var(--ok-700);
  border-left: 6px solid var(--ok-700);
}

/* The one price on a confirmed flight card. The legs carry seat counts and
   nothing else, so this is the whole of the money on the page — right-aligned
   at the head, where the eye lands before the flights. */
.headfare {
  text-align: right;
  line-height: 1.25;
  max-width: 300px;
}
.headfare-line { font-size: 13px; color: var(--ink-500); }
.headfare-line b {
  font-size: 18px; font-weight: 700; color: var(--ink-900);
  margin-left: 6px; font-variant-numeric: tabular-nums;
}
.headfare-fine {
  display: block;
  font-size: 11.5px;
  color: var(--ink-400);
  margin-top: 1px;
}

/* Where the price used to be. A seat count set in 11px grey is not what
   anybody is scanning a booked flight for, so it takes the size the fare
   had and the word drops underneath it. */
.flightpick-price .seatcount {
  font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  /* The head wraps rather than squeezing a three-line price block and a chip
     into a phone's width. */
  .card-head { flex-wrap: wrap; }
  .headfare { max-width: none; text-align: left; flex-basis: 100%; }
}


/* The checkmark before a confirmed heading. */
.confcheck {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-right: 8px; border-radius: 50%;
  background: var(--ok-700); color: #fff; font-size: 13px; font-weight: 700;
  line-height: 1; vertical-align: -3px;
}


/* The window on the week-ahead page: 7, 10 or 14 days. */
.segmented { display: inline-flex; border: 1px solid var(--line);
             border-radius: var(--radius); overflow: hidden; }
.segbtn { padding: 6px 12px; font-size: 13px; color: var(--ink-2);
          text-decoration: none; background: var(--surface); }
.segbtn + .segbtn { border-left: 1px solid var(--line); }
.segbtn.on { background: var(--brand-50); color: var(--brand-700);
             font-weight: 600; }


/* A coach waiting to be told something, on the flight desk page. */
.deskrow { display: flex; align-items: center; gap: 9px; padding: 9px 0;
           border-top: 1px solid var(--line-soft); }
.deskrow:first-child { border-top: 0; }


/* The desk's emails for one request, folded: two buttons became seven. */
.tellfold { margin: 0 0 14px; border: 1px solid var(--line);
            border-radius: var(--radius); background: var(--surface); }
.tellfold > summary { cursor: pointer; list-style: none; padding: 10px 14px;
                      font-size: 13px; font-weight: 700; color: var(--brand-700); }
.tellfold > summary::-webkit-details-marker { display: none; }
.tellfold > summary::before { content: '\2709  '; }
.tellfold .tellcoach { border: 0; margin: 0; padding: 0 14px 12px; }


/* Cc and Bcc, typed on the way out — never stored, because a coordinator
   wants this week's stays and not next season's. */
.emailpane-cc { display: flex; align-items: center; gap: 8px;
                padding: 8px 14px; border-top: 1px solid var(--line-soft);
                font-size: 13px; }
.emailpane-cc label { color: var(--ink-3); font-size: 12px; }
.emailpane-cc input { flex: 1; min-width: 0; }

/* ==========================================================================
   `hidden` means hidden.

   The browser hides [hidden] with a rule of the lowest possible specificity,
   so any class of ours that sets a display beats it — `.lightbox { display:
   flex }` on an element marked hidden renders a full-screen overlay nobody
   can dismiss, and `.btn { display: inline-flex }` shows every button that
   was meant to appear later.

   This restores the browser's own intent, which is what !important is
   actually for. It goes last so nothing can come after it.
   ========================================================================== */
[hidden] { display: none !important; }
