/*!*************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[3]!./app/globals.css ***!
  \*************************************************************************************************************************************************************************************************************************************************************/
/*
 * Theme: light blue, white rounded cards, pill buttons, bottom tab bar
 * pinned to the edge. Presentation only - no component logic depends on these
 * names beyond the class strings already in the markup.
 */
:root {
  /* Height of the fixed brand bar; read by the body padding and by the
     screen header's sticky offset, so the two can never disagree. */
  --brand-h: 46px;
  /* Width of the desktop navigation rail. The body padding and the rail
     itself both read it, so they cannot disagree. */
  --rail-w: 214px;
  --bg: #e4eef9;
  --surface: #ffffff;
  --surface-2: #eef3fb;
  --surface-3: #d8e6f6;
  --border: #d5e2f1;
  --border-strong: #b7cfe9;
  --text: #17222e;
  /* Darkened from the old washed-out grey so secondary text is actually
     readable rather than decorative. */
  --muted: #55708a;
  /* Tab-bar labels sit on white and need more contrast than --muted gives. */
  --nav-label: #33506e;
  --accent: #2b82d4;
  --accent-dark: #1f6cb5;
  --accent-soft: rgba(43, 130, 212, 0.12);
  --accent-text: #ffffff;
  --danger: #e0484d;
  --danger-soft: rgba(224, 72, 77, 0.09);
  --ok: #12a077;
  --radius: 18px;
  /* Type scale. Raised across the board for readability - nothing here is
     smaller than 14px, and body copy is 17px. */
  --fs-body: 17px;
  --fs-small: 15px;
  --fs-label: 14px;
  --fs-h1: 21px;
  --radius-sm: 12px;
  --shadow: 0 2px 12px rgba(29, 43, 48, 0.07);
  --shadow-lg: 0 6px 22px rgba(29, 43, 48, 0.12);
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  font-size: var(--fs-body);
  line-height: 1.5;
}

/* 16px minimum on inputs, or iOS Safari zooms the whole page on focus. */
input,
select,
textarea,
button {
  font: inherit;
  /* 16px is the iOS zoom-on-focus threshold; 17 clears it comfortably. */
  font-size: var(--fs-body);
}

.wrap {
  max-width: 680px;
  margin: 0 auto;
  padding: 16px;
  /* Clearance for the pinned tab bar + the home indicator. */
  padding-bottom: calc(96px + env(safe-area-inset-bottom));
}

/* -------------------------------------------------------------- header --- */

/* ---- brand bar ----------------------------------------------------------
   Pinned to the top and out of the way: it slides up as you scroll down a
   long list of receipts and comes straight back when you scroll up, so the
   account chip is always one gesture away without costing a slot in the
   bottom bar. */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.brand-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--brand-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 14px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  z-index: 30;
  transition: transform 0.22s ease;
}

html.brand-hidden .brand-bar {
  transform: translateY(-100%);
}

.brand-name {
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: var(--accent-dark);
  text-decoration: none;
  white-space: nowrap;
}

.brand-user {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.brand-user-name {
  font-size: 0.9rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 42vw;
}

/* The circle chip: initials rather than an icon, so at a glance you can
   tell WHICH account you are signed in as. */
.brand-chip {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

/* Body is padded once and never changes, so hiding the bar cannot make the
   page jump. The screen header simply re-sticks to the top. */
body.has-brand {
  padding-top: var(--brand-h);
}

body.has-brand header.app {
  top: var(--brand-h);
  transition: top 0.22s ease;
}

html.brand-hidden body.has-brand header.app {
  top: 0;
}

header.app {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 10;
}

header.app h1 {
  font-size: var(--fs-h1);
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.01em;
}

header.app .muted {
  font-size: var(--fs-small);
}

header.app a {
  color: var(--accent-dark);
  text-decoration: none;
  font-size: 16px;
  font-weight: 600;
}

/* --------------------------------------------------------------- cards --- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px;
  margin-bottom: 14px;
}

/* A tinted panel, like the login form block in the reference. */
.card.tinted {
  background: var(--surface-2);
  border-color: var(--border);
  box-shadow: none;
}

label {
  display: block;
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 6px;
  letter-spacing: 0.01em;
}

/**
 * The title of a panel.
 *
 * Whichever label opens a card is naming the card, not captioning the row
 * under it - in the muted grey every other label uses, it read as the
 * latter and the panels ran together down the page.
 *
 * Matched by POSITION rather than a class on purpose: some of these are
 * <FieldLabel> and some are a plain <label>, and the first one in the card
 * is the title either way. Field labels inside the card keep the muted
 * treatment, which is what makes the title read as a title.
 */
.card > label:first-child,
/* The same thing, wearing a heading ROW: a panel whose title sits beside a
   button still opens with a title, and it was the only one rendering at
   field-label weight while its neighbours were bold. */
.card > .details-head:first-child > label {
  color: var(--text);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: 0;
  margin-bottom: 10px;
}

/* ...except the row supplies that spacing itself, so the label inside it
   must not add a second gap below the heading. */
.card > .details-head:first-child > label {
  margin-bottom: 0;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="number"],
select,
textarea {
  width: 100%;
  padding: 14px 15px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  margin-bottom: 12px;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

input::placeholder,
textarea::placeholder {
  color: #9db3cc;
}

/* -------------------------------------------------------------- buttons --- */

button {
  cursor: pointer;
  border: none;
  /* Pill buttons are the signature of the reference design. */
  border-radius: 999px;
  padding: 16px 22px;
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 700;
  letter-spacing: 0.02em;
  width: 100%;
  box-shadow: 0 2px 8px rgba(43, 130, 212, 0.26);
  transition: background 0.15s, transform 0.05s;
}

button:hover:not(:disabled) {
  background: var(--accent-dark);
}

button:active:not(:disabled) {
  transform: translateY(1px);
}

button.secondary {
  background: var(--surface);
  color: var(--accent-dark);
  border: 1.5px solid var(--border-strong);
  box-shadow: none;
}

button.secondary:hover:not(:disabled) {
  background: var(--surface-2);
}

button:disabled {
  opacity: 0.5;
  cursor: default;
  box-shadow: none;
}

/* Paired with .secondary this is red text on white - the quiet form, used
   for destructive actions sitting among ordinary ones. */
button.secondary.danger {
  color: var(--danger);
  border-color: rgba(224, 72, 77, 0.35);
}

/* On its own it is a solid red button. It inherited the blue fill before,
   which left red text on blue and was genuinely hard to read. */
/* A touch deeper than --danger so white text on it clears 4.5:1. The
   lighter red reads fine as an accent or a border, but white on it lands
   at about 4:1, which is under the line for text this size. */
button.danger:not(.secondary) {
  background: #c2383d;
  color: #fff;
  border-color: transparent;
  box-shadow: 0 2px 8px rgba(194, 56, 61, 0.32);
}

button.danger:not(.secondary):hover:not(:disabled) {
  background: #a82f34;
}

/* Deleting sits apart from Save/Cancel and below them: it is the one
   action in the edit panel that pressing Escape cannot undo. */
.danger-zone {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.danger-zone .muted {
  font-size: var(--fs-label);
}

button.tiny {
  width: auto;
  padding: 9px 15px;
  font-size: var(--fs-label);
  font-weight: 600;
  box-shadow: none;
}

/* The capture tile: the whole point of the mobile view. */
.capture-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 210px;
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font-size: 20px;
  font-weight: 700;
  box-shadow: none;
  letter-spacing: 0;
}

.capture-btn:hover:not(:disabled) {
  background: #e6eefb;
  border-color: var(--accent);
}

.capture-btn .icon {
  font-size: 48px;
  line-height: 1;
}

.capture-btn .muted {
  font-weight: 500;
}

/* ------------------------------------------------------------ elements --- */

.muted {
  color: var(--muted);
  font-size: var(--fs-small);
}

.row {
  display: flex;
  gap: 10px;
  align-items: flex-end;
}

.row > * {
  flex: 1 1;
  /* Without this a flex child refuses to shrink below its content's
     intrinsic width, and a native date input is wide - which is how two of
     them side by side pushed the row off a 320px screen. */
  min-width: 0;
}

/* Two date fields will not fit side by side on a narrow phone and stay
   readable: "mm/dd/yyyy" plus a calendar button has a floor. Below this
   they stack, which costs one row of height and nothing else. */
@media (max-width: 480px) {
  .row.dates {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .row.dates > * {
    width: 100%;
  }

  .row.dates .date-field {
    max-width: none;
  }
}

/* The big receipt on the expense page.
 *
 * Written as a COMPOUND selector because it is only ever used alongside
 * .mini - it is the same button, shown large. A bare `.thumb` would depend
 * on being declared after `.mini` to win, which is the kind of thing that
 * breaks silently the next time this file is reordered.
 *
 * `contain`, not `cover`: this is the receipt being read rather than a
 * thumbnail being recognised, and cropping it would cut off the total. */
.mini.thumb {
  width: 100%;
  height: auto;
  max-height: 260px;
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
  cursor: zoom-in;
}

.mini.thumb img {
  height: auto;
  max-height: 258px;
  object-fit: contain;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  border-radius: 999px;
  font-size: var(--fs-label);
  font-weight: 600;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--muted);
}

.pill.ok {
  color: var(--accent-dark);
  background: var(--accent-soft);
  border-color: rgba(43, 130, 212, 0.35);
}

.pill.fail {
  color: var(--danger);
  background: var(--danger-soft);
  border-color: rgba(224, 72, 77, 0.3);
}

.error {
  color: var(--danger);
  background: var(--danger-soft);
  border: 1px solid rgba(224, 72, 77, 0.3);
  border-radius: var(--radius-sm);
  padding: 12px 15px;
  font-size: var(--fs-small);
  margin-bottom: 12px;
}

.spin {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  vertical-align: -2px;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

ul.list {
  list-style: none;
  margin: 0;
  padding: 0;
}

ul.list li {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

ul.list li:last-child {
  border-bottom: none;
}

a.plain {
  color: var(--accent-dark);
  text-decoration: none;
  font-weight: 600;
}

/* ------------------------------------------------------ brand / auth --- */

.brand {
  text-align: center;
  padding: 34px 16px 10px;
}

.brand h1 {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: 0.06em;
  margin: 14px 0 8px;
  text-transform: uppercase;
}

.brand p {
  color: var(--muted);
  font-size: 16px;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 320px;
}

.brand-mark {
  width: 104px;
  height: 104px;
  margin: 0 auto;
  display: block;
}

/* Log in / Sign up switcher from the reference. */
.tabs {
  display: flex;
  gap: 26px;
  padding: 0 4px 14px;
}

.tabs a {
  font-size: 18px;
  font-weight: 700;
  color: var(--muted);
  text-decoration: none;
  padding-bottom: 6px;
  border-bottom: 3px solid transparent;
}

.tabs a.on {
  color: var(--text);
  border-bottom-color: var(--accent);
}

/* -------------------------------------------------------- bottom nav --- */

/* Pinned flush to the bottom edge - part of the device, not a floating
   card. The safe-area padding keeps the labels clear of the home indicator. */
.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: center;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -2px 14px rgba(29, 43, 48, 0.08);
  padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
  z-index: 40;
}

.bottom-nav a,
.bottom-nav button {
  all: unset;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 6px 0;
  color: var(--nav-label);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
  line-height: 1.2;
  white-space: nowrap;
}

/* A sixth slot appears only for team members; everyone else keeps five, so
   the bar is never crowded for a solo user. */
.bottom-nav.with-team {
  grid-template-columns: repeat(6, 1fr);
}

/* Labels at 12px get tight on small phones - shrink the text, never the
   tap target. */
@media (max-width: 380px) {
  .bottom-nav a,
  .bottom-nav button {
    font-size: 11px;
  }
  .bottom-nav {
    padding: 8px 2px calc(8px + env(safe-area-inset-bottom));
  }
}

.bottom-nav .ico {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--accent-dark);
}

.bottom-nav .on {
  color: var(--accent-dark);
}

.bottom-nav .on .ico {
  background: var(--accent-soft);
}

/* The raised centre action, as in the reference bar. */
.bottom-nav .fab .ico {
  width: 52px;
  height: 52px;
  margin-top: -22px;
  background: var(--accent);
  color: var(--accent-text);
  box-shadow: 0 4px 12px rgba(43, 130, 212, 0.42);
  border: 3px solid var(--surface);
}

.bottom-nav .fab {
  color: var(--accent-dark);
}

/* ------------------------------------------------- desktop review screen --- */

.wrap.wide {
  max-width: 1180px;
}

table.tbl {
  width: 100%;
  border-collapse: collapse;
}

table.tbl td,
table.tbl th {
  padding: 10px 8px;
  font-size: 16px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}

table.tbl th {
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

table.tbl .num {
  text-align: right;
}

table.tbl tr.total td {
  border-top: 2px solid var(--border-strong);
  border-bottom: none;
  font-weight: 800;
}

table.expenses input,
table.expenses select {
  margin-bottom: 0;
  padding: 9px 10px;
  font-size: 16px;
  background: var(--surface-2);
  border-color: var(--border);
}

table.expenses input.num {
  text-align: right;
}

/* Unreviewed rows are marked, not hidden - the point is to see at a glance
   how much is left to check before generating the report. */
table.expenses tr.unreviewed td:first-child {
  box-shadow: inset 3px 0 0 var(--accent);
}

/* The receipt thumbnail.
 *
 * The class sits on a BUTTON - tapping the picture is how the lightbox
 * opens - so every one of the pill-button defaults above has to come back
 * off, `width: 100%` most of all: inherited, it turns a 44px thumbnail into
 * a full-width blue pill with the image collapsed inside it.
 *
 * Also used on a bare div for the placeholder, so the box lives here and
 * nothing about it assumes a particular element. */
.mini {
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  padding: 0;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: none;
  cursor: zoom-in;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mini img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* A PDF receipt has no thumbnail, so the slot says what it is rather than
   sitting empty and looking like a broken image. */
.mini-pdf {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.actions {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
}

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(14, 32, 36, 0.82);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 50;
  cursor: zoom-out;
}

.lightbox img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--radius-sm);
}

@media (max-width: 720px) {
  table.expenses {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
}

/* ------------------------------------------------------------ warnings --- */

.warn-box {
  border: 1px solid rgba(224, 72, 77, 0.32);
  background: var(--danger-soft);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 14px;
}

.warn-box strong {
  display: block;
  color: var(--danger);
  margin-bottom: 6px;
}

.warn-box p {
  margin: 0 0 10px;
  font-size: var(--fs-small);
  color: var(--muted);
  line-height: 1.5;
}

.ok-box {
  border: 1px solid rgba(18, 160, 119, 0.3);
  background: rgba(18, 160, 119, 0.08);
  color: var(--ok);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 14px;
  font-weight: 600;
}

/* ------------------------------------------------- inline trip rename --- */

.title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.title-row h1 {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Small square affordance next to a heading - not a pill like the rest. */
.icon-btn {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--accent-dark);
  border: 1px solid var(--border);
  box-shadow: none;
}

.icon-btn:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.name-edit {
  display: flex;
  align-items: center;
  gap: 6px;
}

.name-edit input {
  margin-bottom: 0;
  padding: 9px 12px;
  font-size: 17px;
  font-weight: 700;
  min-width: 0;
  flex: 1 1;
}

/* ------------------------------------------------ expense list rows --- */

.ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Keeps rows aligned when a receipt image has been deleted. */
.mini.placeholder {
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  cursor: default;
}

/* PDFs open in an iframe, which needs real dimensions and an explicit way
   out - the backdrop click is swallowed by the frame itself. */
.lightbox-pdf {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  max-width: 900px;
  gap: 10px;
  cursor: default;
}

.lightbox-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.lightbox-bar a {
  color: #fff;
  font-weight: 700;
}

.lightbox-bar button {
  width: auto;
  flex: 0 0 auto;
}

/* <object> as well as <iframe>: the viewer embeds a PDF with <object> so a
   browser that will not render one still shows the fallback link inside. */
.lightbox-pdf iframe,
.lightbox-pdf object {
  flex: 1 1;
  min-height: 0;
  width: 100%;
  border: 0;
  border-radius: var(--radius-sm);
  background: #fff;
}

/* The receipt's own text is the link that opens it - there is no separate
   edit affordance to aim at, which matters most on a phone. */
.row-link {
  flex: 1 1;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.row-link:hover .ellipsis:first-child {
  color: var(--accent);
}

/* Membership toggles: the same chip shape as the receipt filters, pressed
   when the person is in the team. */
.member-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

/* Whose costs go on the GMAP claim.
   Ticks rather than the pressed-chip shape used for team membership: this
   is a set of people to INCLUDE, all of them ticked to begin with, and a
   button that already looks pressed invites the click that removes one. */
.member-checks {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.member-checks label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--rule, #d5e2f1);
  border-radius: 8px;
  cursor: pointer;
  margin: 0;
  font-weight: 600;
}

.member-checks label:has(input:checked) {
  border-color: var(--accent);
  background: var(--tint, #f2f7fd);
}

.member-checks input {
  width: auto;
  margin: 0;
  flex: 0 0 auto;
}

/**
 * A group of fields inside a card.
 *
 * A trip form is eight controls that are really three decisions: what it is
 * called, where it went and when, and which state programme is paying. In
 * one flat column they read as eight unrelated things running together.
 * Boxed, the grouping does the explaining and no extra headings are needed.
 */
.subpanel {
  border: 1px solid var(--rule, #d5e2f1);
  border-radius: 10px;
  padding: 12px 14px 14px;
  margin-top: 16px;
  background: var(--tint, #f2f7fd);
}

/* The box supplies the top spacing, so whatever leads it must not add more
   of its own - several of these children carry their own margin because
   they also appear outside a subpanel. */
.subpanel > :first-child {
  margin-top: 0;
}

.subpanel > :last-child {
  margin-bottom: 0;
}

/* The deduction between total spend and total claimed. */
.claim-line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 2px 0;
}

.grand-total.claimed {
  border-top: 1px solid var(--border);
  color: var(--accent-dark);
}

/* The live claim figure under Non-reimbursable. Not help text - it is a
   number derived from what you just typed. */
.claim-hint {
  margin: -8px 0 14px;
}

/* The MDED programme on the trip header - a badge, not a sentence. */
.mded-tag {
  margin-left: 8px;
}

/* The trip name and its team-trip switch share a row. */
.name-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
}

.name-row input {
  flex: 1 1;
  min-width: 0;
}

.name-row-switch {
  flex: 0 0 auto;
  align-self: center;
  margin-bottom: 14px;
  white-space: nowrap;
}

/* Two date fields on one row: narrow enough that they fit a phone side by
   side, which is what the .dates stacking rule otherwise prevents. */
@media (max-width: 480px) {
  .row.dates.narrow {
    flex-direction: row;
    gap: 8px;
  }

  .row.dates.narrow .date-field,
  .row.dates.narrow input[type="date"] {
    max-width: none;
    width: 100%;
    padding-left: 8px;
    padding-right: 4px;
    font-size: 15px;
  }
}

/* Trip status, sitting on the page background rather than in a card - it is
   a label on the trip, not a field you fill in. */
.status-strip {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 2px 0 14px;
}

/* While the trip edit form is open ----------------------------------------
   The form renders inside the screen header. Sticky is right for a title
   bar and wrong for a tall form: a sticky box taller than the viewport
   pins itself and everything below it becomes unreachable. */

body.trip-editing header.app {
  position: static;
}

/* The tab bar is a fixed overlay, which on a phone lands on top of the last
   field and argues with the soft keyboard. Nothing in it is wanted mid-edit. */
body.trip-editing .bottom-nav {
  display: none;
}

/* Room to scroll past the last control once the bar is gone. */
body.trip-editing header.app {
  padding-bottom: calc(28px + env(safe-area-inset-bottom));
}

/* The trip itself goes away while its own details are being edited. The
   summary, the reports and the personnel panel are all about the trip as it
   stands; reading them under a form that is mid-change is confusing, and on
   a phone it buries the Save button under a page of figures. */
body.trip-editing .wrap {
  display: none;
}

/* ---- switch -------------------------------------------------------------
   For settings that are genuinely on or off. A switch shows its state in
   its shape, where a pair of chips makes you compare two labels. */

.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 14px;
}

.switch-label {
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--muted);
}

.switch {
  flex: 0 0 auto;
  width: 50px;
  height: 29px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--border-strong);
  box-shadow: none;
  cursor: pointer;
  transition: background 0.15s;
}

.switch.on {
  background: var(--accent);
}

.switch-knob {
  display: block;
  width: 23px;
  height: 23px;
  margin-left: 3px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(23, 34, 46, 0.3);
  transition: transform 0.15s;
}

.switch.on .switch-knob {
  transform: translateX(21px);
}

/* A city and a state, side by side. The state is narrow because it is two
   letters and a closed list. */
.location-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}

.location-row input {
  flex: 1 1;
  min-width: 0;
}

.location-row .location-state {
  flex: 0 0 auto;
  width: 86px;
  min-width: 0;
}

/* ---- per diem ----------------------------------------------------------- */

.perdiem-fields {
  margin-top: 4px;
}

.perdiem-note {
  margin: 6px 0 0;
  font-size: var(--fs-label);
}

.perdiem-options {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

/* Each candidate rate is a full-width choice, not a chip - the county name
   beside it is the thing you are actually reading. */
button.perdiem-option {
  width: 100%;
  text-align: left;
  white-space: normal;
  line-height: 1.35;
}

/* The daily rows that stand in for meal receipts. */
.perdiem-days li {
  padding-top: 7px;
  padding-bottom: 7px;
}

.perdiem-days .perdiem-rate-note {
  border-bottom: 0;
  padding-top: 4px;
}

.perdiem-days .perdiem-rate-note .muted {
  font-size: var(--fs-label);
}

/* Choosing a destination: a state, then one of the places GSA prices for
   it. The list is scrollable because a big state publishes dozens. */
.locality-picker {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.locality-picker .perdiem-options {
  max-height: 260px;
  overflow-y: auto;
}

/* ---- GMAP letter -------------------------------------------------------- */

.gmap-preview {
  margin-top: 4px;
}

.gmap-preview .gmap-total td {
  font-weight: 800;
  border-top: 2px solid var(--text);
}

/* Things the letter will say that you probably did not intend - a missing
   location, no personnel, an unconfigured signatory. */
.warn-box {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: rgba(224, 72, 77, 0.08);
  border: 1px solid rgba(224, 72, 77, 0.3);
  font-size: var(--fs-small);
}

.warn-box > div + div {
  margin-top: 4px;
}

/* A link that has to look like the primary button next to it. */
.download-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1;
  padding: 16px 22px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(43, 130, 212, 0.26);
}

.download-btn:hover {
  background: var(--accent-dark);
}

/* ---- key personnel -----------------------------------------------------
   A list of people rather than money, so the rows are text-first and the
   actions sit to the side. */

.person-list li {
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 8px;
}

.person-name {
  font-weight: 700;
}

/* Purpose is the one field that is a sentence, so it wraps instead of
   ellipsing - truncating "why we met" loses the whole point of recording it. */
.person-purpose {
  white-space: normal;
  margin-top: 2px;
}

.person-actions {
  display: flex;
  gap: 6px;
  flex: 0 0 auto;
}

.person-form {
  width: 100%;
  padding: 12px;
  margin-bottom: 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.person-form .row {
  margin-top: 4px;
}

li.person-editing {
  padding: 0;
  border: 0;
}

/* Colleagues' entries on a shared journey - visibly theirs, and not
   editable from here. */
.team-personnel {
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-strong);
}

.team-personnel-head {
  font-size: var(--fs-label);
  margin-bottom: 4px;
}

.person-owner {
  flex: 0 0 auto;
  font-size: var(--fs-label);
  align-self: flex-start;
}

/* ---- field help ---------------------------------------------------------
   The explanation that used to sit under a field, moved behind an (i). */

.label-row {
  display: flex;
  align-items: center;
  gap: 7px;
  position: relative;
  /* The row now carries the spacing the label used to. */
  margin-bottom: 6px;
}

.label-row label {
  margin-bottom: 0;
}

/* Anchored under the label rather than floating: it must never cover the
   field it is describing, or you cannot read the note and type at once. */
.help-bubble {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 25;
  width: min(340px, calc(100vw - 48px));
  margin-top: 2px;
  padding: 11px 30px 11px 13px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-small);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text);
  text-transform: none;
  letter-spacing: normal;
}

/* Hangs off the right edge instead, for a label near the window edge. */
.help-bubble.flip {
  left: auto;
  right: 0;
}

.help-close {
  position: absolute;
  top: 4px;
  right: 6px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}

/* ---- Team view ---------------------------------------------------------
   Read-only throughout: these are figures to look at, not controls. */

.back-link {
  display: inline-block;
  margin-bottom: 12px;
  font-weight: 700;
  color: var(--accent);
  text-decoration: none;
}

/* Period picker: the quarter selector only appears alongside "By quarter",
   so the row has to cope with one control or two. */
.period-row {
  display: flex;
  gap: 10px;
}

.period-row select {
  flex: 1 1;
  margin-bottom: 0;
}

/* A team in the chooser is a button, not a link - picking one switches the
   view in place rather than navigating. */
button.team-pick {
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  font: inherit;
  color: inherit;
  cursor: pointer;
}

/* The line under the trip rows that everything above adds up to. */
.team-grand {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 2px solid var(--text);
  font-size: 1.15rem;
  font-weight: 800;
}

.team-grand > span:last-child {
  text-align: right;
}

.team-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 1.45rem;
  font-weight: 800;
  padding: 2px 0;
}

.team-total .muted {
  font-size: 0.9rem;
  font-weight: 600;
}

/* The same three tiers the report prints: main category, then the specific
   types under it. */
.cat-block {
  margin-bottom: 10px;
}

.cat-main {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-weight: 800;
  padding: 6px 0 2px;
  /* Matches .grp-head: the rule under the heading is what separates one
     group from the next, so it carries the weight instead of a dotted
     leader running through the heading row itself. */
  border-bottom: 2px solid var(--border-strong);
}

/* Icon and label read as one thing, so the icon never drifts away from the
   name on a narrow screen. */
.cat-head-name {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.cat-icon {
  flex: 0 0 auto;
  color: var(--accent);
}

.cat-sub {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0 3px 14px;
}

.details-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.details-head button {
  width: auto;
  flex: 0 0 auto;
}

/* Not yet reviewed - a marker, not a hiding place. */
ul.list li.unreviewed-row {
  box-shadow: inset 3px 0 0 var(--accent);
  padding-left: 10px;
}

/* The pencil is an <a> in lists and a <button> in headers. */
a.icon-btn {
  text-decoration: none;
}

/* --------------------------------------------- category grouping --- */

.cat-group {
  margin-bottom: 18px;
}

.cat-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 8px 0 6px;
  border-bottom: 2px solid var(--border-strong);
  font-weight: 700;
  /* A step up from 16px: these headings carry an icon now, and at the old
     size the icon crowded the text rather than sitting beside it. */
  font-size: 17px;
}

.cat-head > span:last-child {
  text-align: right;
  white-space: nowrap;
}

.grand-total {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 0 4px;
  margin-top: 6px;
  border-top: 3px solid var(--text);
  font-weight: 800;
  font-size: 19px;
}

/* ------------------------------------------------------ trip rows --- */

/* The whole row is the link - no separate "open" control to aim at. */
.trip-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 12px;
  margin: 0 -12px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid var(--border);
}

.trip-row:last-child {
  border-bottom: none;
}

.trip-row:hover {
  background: var(--surface-2);
}

.trip-row-name {
  font-weight: 700;
  font-size: 17px;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* The name is the only part allowed to shrink - a tag pushed out of view is
   a tag that may as well not exist. */
.trip-row-name > .ellipsis {
  min-width: 0;
  flex: 0 1 auto;
}

.trip-row-name > .tag {
  flex: 0 0 auto;
}

.trip-row-total {
  text-align: right;
  font-weight: 700;
  white-space: nowrap;
  flex: 0 0 auto;
}

/* A label, not a button - the old pill read as tappable and was not. */
.tag {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent-dark);
  background: none;
  padding: 0;
  border: none;
}

.tag.muted-tag {
  color: var(--muted);
}

/* A button that must read as a link - used for "Forgot your password?" */
button.linklike {
  width: auto;
  padding: 0;
  background: none;
  box-shadow: none;
  border: none;
  color: var(--accent-dark);
  font-weight: 600;
  font-size: var(--fs-small);
  text-decoration: underline;
}

button.linklike:hover:not(:disabled) {
  background: none;
  color: var(--text);
}

/* Running AI cost. Quiet by design: an operating cost, not an expense. */
.cost-footer {
  margin: 0 0 8px;
  padding: 10px 14px;
  font-size: var(--fs-small);
  color: var(--muted);
  text-align: center;
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
}

.cost-footer strong {
  color: var(--text);
}

/* ------------------------------------------------- add-receipt sheet --- */

.sheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(14, 26, 40, 0.5);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 60;
}

.sheet {
  width: min(560px, 100%);
  background: var(--surface);
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 18px 16px calc(18px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 -6px 26px rgba(29, 43, 48, 0.2);
}

/* Upload failures from the nav have nowhere else to surface. */
.nav-error {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(86px + env(safe-area-inset-bottom));
  background: var(--danger-soft);
  border: 1px solid rgba(224, 72, 77, 0.4);
  color: var(--danger);
  border-radius: var(--radius-sm);
  padding: 12px 15px;
  font-size: var(--fs-small);
  text-align: center;
  z-index: 50;
  cursor: pointer;
}

.bottom-nav .fab .spin.light {
  border-color: rgba(255, 255, 255, 0.45);
  border-top-color: #fff;
}

/* Trip dates sit under the title - informational, not a form. */
.trip-dates {
  font-size: var(--fs-small);
}

/* ------------------------------------------------------ filter chips --- */

/* Sized to their text and wrapping, rather than a stretched grid - a row of
   full-width buttons reads as five separate actions, not one choice. */
.filter-bar {
  margin-bottom: 14px;
}

.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.filter-chip {
  width: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--muted);
  font-size: var(--fs-label);
  font-weight: 600;
  box-shadow: none;
  letter-spacing: 0;
}

.filter-chip:hover:not(:disabled) {
  background: var(--surface-2);
  color: var(--text);
}

/* Toggle chips use aria-pressed; a mutually exclusive set is a radiogroup
   and uses aria-checked. Both look the same when selected. */
.filter-chip[aria-pressed="true"],
.filter-chip[aria-checked="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}

.filter-chip .count {
  font-size: 12px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
}

.filter-chip[aria-pressed="true"] .count,
.filter-chip[aria-checked="true"] .count {
  background: rgba(255, 255, 255, 0.24);
  color: var(--accent-text);
}

/* A date input stretched across a phone is mostly empty box. The native
   control still opens the OS picker on tap - the date is never typed. */
.date-field {
  max-width: 220px;
}

/* The native picker indicator sits at the right edge of the field. It is
   tiny and low-contrast by default, which is why the field reads as plain
   text and nobody realises it opens a calendar. */
.date-field::-webkit-calendar-picker-indicator {
  margin-left: auto;
  padding: 4px;
  cursor: pointer;
  opacity: 0.75;
  transform: scale(1.25);
}

.date-field::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
}

/* Shown, not stored: subtotal is always total minus tax, so it is displayed
   the same way a total line on a receipt is - read, not typed. */
input.derived {
  background: var(--surface-2);
  color: var(--muted);
  cursor: default;
}

/* --------------------------------------------------- report viewer --- */

/* Full-screen PDF with a persistent way out. Opening the file directly left
   no route back on a phone. */
.pdf-viewer {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

.pdf-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px calc(10px + env(safe-area-inset-top));
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}

.pdf-frame {
  flex: 1 1;
  width: 100%;
  border: 0;
  background: #fff;
}

/* A link that sits comfortably beside .tiny buttons. */
.tiny-link {
  display: inline-flex;
  align-items: center;
  padding: 9px 15px;
  border-radius: 999px;
  border: 1.5px solid var(--border-strong);
  background: var(--surface);
  color: var(--accent-dark);
  font-size: var(--fs-label);
  font-weight: 600;
  text-decoration: none;
}

.tiny-link:hover {
  background: var(--surface-2);
}

/* ------------------------------------- receipts + trip drop panel --- */

/* Single column by default. The trip panel only appears where drag and
   drop actually works - HTML5 DnD does not exist on touch, and on a phone
   the Trip dropdown on the receipt page is the way to file something. */
.receipts-layout {
  display: block;
}

.trip-panel {
  display: none;
}

@media (min-width: 900px) {
  .receipts-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    grid-gap: 14px;
    gap: 14px;
    align-items: start;
  }

  .trip-panel {
    display: block;
    position: -webkit-sticky;
    position: sticky;
    top: 88px;
  }
}

/* ---- desktop navigation rail -------------------------------------------
   The same markup as the bottom bar, laid out down the left instead. A
   phone has no room for a persistent rail and a desktop has no need for a
   thumb-reach bar at the bottom of a 27-inch screen, so the breakpoint
   simply swaps which one the nav behaves as.

   1024px rather than the 900px used by the receipts side panel: below that,
   taking 214px away would squeeze the two-column receipt list. */
@media (min-width: 1024px) {
  body {
    padding-left: var(--rail-w);
  }

  .bottom-nav {
    top: var(--brand-h);
    bottom: 0;
    right: auto;
    width: var(--rail-w);
    /* Overrides the grid used by the bar, including its .with-team variant:
       a rail is a column however many items are in it. */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 16px 12px;
    border-top: 0;
    border-right: 1px solid var(--border);
    box-shadow: none;
  }

  .bottom-nav a,
  .bottom-nav button {
    flex-direction: row;
    justify-content: flex-start;
    gap: 12px;
    padding: 11px 12px;
    border-radius: var(--radius-sm);
    font-size: 15px;
    text-align: left;
  }

  .bottom-nav a:hover {
    background: var(--surface-2);
  }

  .bottom-nav .on {
    background: var(--accent-soft);
  }

  /* The raised circle belongs to the bottom bar. Here Add is simply the
     first and most prominent item in the list. */
  .bottom-nav .fab {
    order: -1;
    margin-bottom: 10px;
    background: var(--accent);
    color: var(--accent-text);
    box-shadow: 0 3px 10px rgba(43, 130, 212, 0.35);
  }

  .bottom-nav .fab .ico,
  .bottom-nav .on .ico {
    width: auto;
    height: auto;
    margin-top: 0;
    background: none;
    border: 0;
    box-shadow: none;
    color: inherit;
  }

  /* No bar at the bottom to clear any more. */
  .wrap {
    padding-bottom: 32px;
  }

  /* Hiding the header was a way to reclaim phone screen. On a desktop it
     would just leave a gap above the rail. */
  html.brand-hidden .brand-bar {
    transform: none;
  }

  html.brand-hidden body.has-brand header.app {
    top: var(--brand-h);
  }
}

/* Receipt rows are draggable on desktop. */
@media (min-width: 900px) {
  ul.list li[draggable="true"] {
    cursor: -webkit-grab;
    cursor: grab;
  }
}

ul.list li.dragging {
  opacity: 0.45;
}

.trip-drop {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  margin-bottom: 8px;
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  transition: border-color 0.12s, background 0.12s, transform 0.12s;
}

.trip-drop:last-child {
  margin-bottom: 0;
}

/* Unmistakable target while a receipt is over it. */
.trip-drop.over {
  border-color: var(--accent);
  border-style: solid;
  background: var(--accent-soft);
  transform: scale(1.02);
}

/* A trip in the panel is also a link to that trip, so it must not inherit
   the underlined link look - it is a card you can click, not a word. */
a.trip-drop {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

a.trip-drop:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* "Remove from trip" reads as an out-tray, not another destination. */
.trip-drop.unfiled-drop {
  background: var(--surface);
  border-color: var(--border);
  margin-bottom: 14px;
}

.trip-drop.unfiled-drop.over {
  border-color: var(--danger);
  background: var(--danger-soft);
}


/* Non-reimbursable: the part of a receipt nobody is claiming.
   Muted and small - it is a footnote to the amount beside it, not a
   warning, and a trip with several of them should not look alarming. */
.nonreimb-note {
  font-size: 11px;
  color: #8a6d3b;
  white-space: nowrap;
}
.struck {
  text-decoration: line-through;
  color: #8296ab;
  font-size: 12px;
}

/* A card that folds away. The heading keeps the ordinary card-heading
   styling so the panel does not look like a different kind of thing; the
   caret on the right is the only sign it collapses. */
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.panel-head .label-row {
  margin-bottom: 0;
}
.panel-head .label-row label {
  margin-bottom: 0;
}
.panel-caret {
  flex: 0 0 auto;
  width: auto;
  background: none;
  border: 0;
  /* Padded out to a finger-sized target around a deliberately small mark. */
  padding: 8px 4px 8px 12px;
  margin: 0;
  line-height: 0;
  cursor: pointer;
  color: var(--muted);
}
.panel-caret .caret {
  display: block;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid currentColor;
  transition: transform 140ms ease;
}
.panel-caret[aria-expanded="true"] .caret {
  transform: rotate(180deg);
}

/* ---------------------------------------------- M&IE rate and actuals --- */

/* "Set M&IE per diem rate" sits on the Meals heading row. A link rather
   than a button: it opens a dialog, it does not change anything by itself,
   and a button there would compete with the subtotal beside it. */
.linkish {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  /* Buttons default to full width in this design; a text link must not. */
  width: auto;
  box-shadow: none;
  font: inherit;
  font-weight: 500;
  font-size: 13px;
  color: var(--accent, #1f6cb5);
  text-decoration: underline;
  cursor: pointer;
}
.perdiem-set {
  margin-left: 10px;
  white-space: nowrap;
}

.mie-block {
  padding: 8px 0 4px;
}

/* Claimed against captured, on one line - the whole point of showing
   actuals on a trip whose claim is a fixed daily rate. Ruled off from the
   day list above it, which is what it is being compared against. */
.mie-compare {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0 3px;
  margin-top: 4px;
  border-top: 1px solid var(--border, #d5e2f1);
  font-size: 14px;
}

/* "Day 1 (75%)" carries the weight; the date beside it is reference. */
.perdiem-day-n {
  font-weight: 600;
}
.mie-over {
  color: #8a4b2b;
  margin-left: 6px;
}
.mie-under {
  color: #2d6a4a;
  margin-left: 6px;
}

.warn-inline {
  margin: 4px 0 8px;
  padding: 8px 10px;
  border-radius: 6px;
  background: #fdf3f3;
  border: 1px solid #e7b9b9;
  color: #8d2525;
  font-size: 13px;
}

/* ------------------------------------------------------------- modal ---- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(23, 34, 46, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 60;
}
.modal {
  background: var(--card, #fff);
  border-radius: 10px;
  padding: 18px;
  width: 100%;
  max-width: 460px;
  /* Taller than the phone on a multi-city trip, so it scrolls itself
     rather than pushing its buttons off the bottom. */
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}
.modal-title {
  margin: 0 0 8px;
  font-size: 17px;
}
.modal-note {
  margin: 0 0 12px;
  font-size: 13px;
}

.perdiem-leg + .perdiem-leg {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border, #d5e2f1);
}
.perdiem-leg-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: baseline;
  margin-bottom: 6px;
  font-size: 14px;
}

/* Who an outgoing report will reach. Listed plainly rather than counted:
   the point of showing it is that a wrong address is spotted first. */
.recipient-list {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
}
.recipient-list li {
  padding: 1px 0;
}

/* Costs kept on the trip but claimed somewhere other than the expense
   report. Dimmed, so the eye skips them when reading the claim, without
   them disappearing - a receipt that seems to have vanished is alarming. */
.unclaimed-list li {
  opacity: 0.72;
}

/* One leg reads as a plain location and dates; several label themselves. */
.itinerary-leg + .itinerary-leg {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border, #d5e2f1);
}
.itinerary-leg-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 13px;
  margin-bottom: 4px;
}

/* GMAP terms - the activity and the share. Both appear only while the
   programme is switched on, indented so they read as belonging to the
   switch above rather than as two more trip fields. */
.gmap-terms {
  margin: 8px 0 4px;
  padding-left: 12px;
  border-left: 2px solid var(--border, #d5e2f1);
}

/* Three fixed options on one row: the choice is small, so it should not
   look like a section of its own. */
.gmap-rate {
  border: 0;
  padding: 0;
  margin: 6px 0 0;
}
.gmap-rate legend {
  padding: 0;
  font-size: 13px;
  margin-bottom: 4px;
}
.gmap-rate-options {
  display: flex;
  gap: 16px;
}
.gmap-rate-option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 15px;
}
.gmap-rate-option input {
  width: auto;
  margin: 0;
}

/* One Reports panel holding three documents. They go to three different
   organisations and are computed three different ways, so each gets its
   own heading and a rule between them rather than running together. */
.report-block + .report-block {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border, #d5e2f1);
}

/* The share each GMAP line is claimed at, under its heading. */
.gmap-rate-note {
  font-size: 11px;
}

/* ------------------------------------------------------ cropping ------- */

/* Both take the full overlay and lay out top-down, like .lightbox-pdf.
   Centring them instead let a tall receipt push the toolbar off the top of
   the screen, where it could be seen but not reached. */
.lightbox-image,
.crop {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  max-width: 900px;
  gap: 10px;
  cursor: default;
}

/* The toolbar never scrolls away and never sits under the dimming overlay
   the selection paints - both of which made the Crop button unclickable. */
.lightbox-image > .lightbox-bar,
.crop-bar {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
}

/* The picture takes what is left and is centred within it. min-height:0 is
   what lets a flex child actually shrink rather than overflow its parent. */
.lightbox-image > img,
.crop-frame {
  flex: 1 1;
  min-height: 0;
  align-self: center;
  max-width: 100%;
  object-fit: contain;
}

.crop-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  color: #fff;
  font-size: 13px;
}
.crop-bar .muted {
  color: #c7d5e4;
}
.crop-bar button {
  width: auto;
  flex: 0 0 auto;
}

/* The image is the drag surface, so the browser's own gestures - panning,
   text selection, the long-press menu - have to get out of the way. */
.crop-frame {
  position: relative;
  line-height: 0;
  touch-action: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  cursor: crosshair;
  /* Shrink-wraps the image so the selection box, which is positioned
     against this element, lines up with the pixels underneath it. */
  display: inline-flex;
}
.crop-frame img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  pointer-events: none;
}
.crop-box {
  position: absolute;
  border: 2px solid #fff;
  /* Everything outside the box dimmed, so the selection reads as "this is
     what you keep" rather than "this is a rectangle". */
  box-shadow: 0 0 0 9999px rgba(10, 18, 28, 0.55);
}

/* ---- several receipts on one expense ------------------------------------ */

/*
 * A purchase often has two proofs - the vendor's receipt and the card
 * receipt showing the charge cleared. They sit side by side so it reads as
 * one expense with two documents, not two expenses.
 */
.receipt-gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-start;
}
.receipt-gallery figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 100%;
}
.receipt-gallery figcaption {
  font-size: 12px;
}
.add-receipt {
  display: inline-block;
  margin-top: 12px;
  cursor: pointer;
}
/**
 * An <a> that has to look like a button.
 *
 * These stay anchors rather than buttons because a download IS a
 * navigation: right-click, long-press and "save link as" all work on one
 * and none of them work on a <button>. Only the look is borrowed.
 *
 * Scoped to a.btn-like deliberately. The other two things wearing this
 * class are a <label> over a file input and a <span>, both of which style
 * themselves from their own context and must not pick this up.
 */
a.btn-like {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1;
  cursor: pointer;
  border-radius: 999px;
  padding: 16px 22px;
  background: var(--surface);
  color: var(--accent-dark);
  border: 1.5px solid var(--border-strong);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  text-decoration: none;
  transition: background 0.15s;
}

a.btn-like:hover {
  background: var(--surface-2);
}

/* A file input cannot be styled, so the label carries the button's look. */
.add-receipt .btn-like {
  display: inline-block;
  padding: 6px 12px;
  border: 1px solid var(--rule, #d5e2f1);
  border-radius: 8px;
  font-size: 13px;
}
.add-receipt input:disabled + .btn-like {
  opacity: 0.6;
}

/* ---- foreign currency --------------------------------------------------- */

.fx-box {
  border-left: 3px solid var(--rule, #d5e2f1);
  padding-left: 12px;
  margin: 14px 0;
}
/*
 * The ISO code beside an amount, shown only when a trip holds more than one
 * currency. Small and quiet: it is there to disambiguate a "$" that might
 * be Canadian, not to compete with the number.
 */
.ccy {
  font-size: 0.75em;
  margin-left: 3px;
  opacity: 0.7;
  font-weight: 500;
}

/* ---- pasting a screenshot in as a receipt -------------------------------- */

.paste-sheet {
  gap: 10px;
}
.paste-title {
  margin: 0 0 4px;
  font-size: 17px;
}
/*
 * The target for Ctrl+V. Dashed and roomy so it reads as somewhere to put
 * something, rather than as a message about something that went wrong.
 */
.paste-target {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 140px;
  padding: 20px;
  border: 2px dashed var(--rule, #d5e2f1);
  border-radius: 10px;
  text-align: center;
}
.paste-target .muted {
  font-size: 13px;
}
/* Capped so a 4K snip does not push the buttons off the bottom. */
.paste-preview {
  display: block;
  max-width: 100%;
  max-height: 46vh;
  object-fit: contain;
  border: 1px solid var(--rule, #d5e2f1);
  border-radius: 8px;
  background: #fff;
}
.paste-hint {
  margin: 0;
  font-size: 12px;
  text-align: center;
}
.paste-note {
  margin: 0;
}
.paste-sheet:focus {
  outline: none;
}

/* ---- choosing whose spend goes on a GMAP claim --------------------------- */

.gmap-pick-line {
  margin-top: 14px;
}
.gmap-pick-line h4 {
  margin: 0 0 6px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted, #55708a);
  border-bottom: 1px solid var(--rule, #d5e2f1);
  padding-bottom: 3px;
}
.gmap-pick-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  cursor: pointer;
}
/* A single contributor has nothing to decide, so no box - but the row still
   lines up with the ones that do. */
.gmap-pick-row.single {
  cursor: default;
  padding-left: 24px;
}
.gmap-pick-row input {
  width: auto;
  margin: 0;
  flex: 0 0 auto;
}
.gmap-pick-row .num {
  margin-left: auto;
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
}

/* ---- choosing what kind of container to make ---------------------------- */

.kind-choice {
  display: flex;
  gap: 10px;
  margin-bottom: 14px;
}
.kind-choice label {
  flex: 1 1;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--rule, #d5e2f1);
  border-radius: 8px;
  cursor: pointer;
  margin: 0;
}
.kind-choice label:has(input:checked) {
  border-color: var(--accent);
  background: var(--tint, #f2f7fd);
}
.kind-choice input {
  width: auto;
  margin: 2px 0 0;
  flex: 0 0 auto;
}
.kind-choice span {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.kind-choice .muted {
  font-size: 12px;
}

/* The "Filing into X" line above the capture buttons. Quiet - it is a
   confirmation, not an instruction. */
.sheet-dest {
  margin: 0 0 0.35rem;
  font-size: 0.85rem;
  color: var(--muted);
  text-align: center;
}
.sheet-dest strong {
  color: var(--text);
}

/* ------------------------------------------------- the trip summary --- */

/* What the trip comes to, grouped the way the report groups it: a heading
   per main category with its subtotal, the receipts under it, and the
   per-diem days standing in for meal receipts on a per-diem trip. */
.summary {
  display: flex;
  flex-direction: column;
}

.grp + .grp {
  margin-top: 18px;
}

.grp-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 6px;
  /* The rule UNDER the heading is what separates one group from the next,
     so it carries the weight. The dotted leader that used to run through
     the heading row itself is gone: with a rule this solid directly beneath
     it, two lines a few pixels apart were competing to do one job. */
  border-bottom: 2px solid var(--border-strong);
}

.grp-label {
  font-weight: 700;
  flex: 1 1;
  min-width: 0;
}

.grp-total {
  font-weight: 700;
}

/* The negotiated daily rate, stated beside the group it explains. */
.chip.rate {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-dark);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}

.grp-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
}

.grp-row:last-child {
  border-bottom: 0;
}

.exp-row .exp-main {
  display: flex;
  flex-direction: column;
  flex: 1 1;
  min-width: 0;
}

.exp-vendor {
  font-weight: 600;
}

.exp-row:hover .exp-vendor {
  color: var(--accent);
}

.day-row .day-name {
  font-weight: 600;
  flex: 0 0 auto;
}

.day-row .day-meta {
  flex: 1 1;
  min-width: 0;
}

/* Actual meal spend against the allowance being claimed. Not a warning -
   under is normal and over is allowed; it is simply worth seeing. */
.actuals-row .delta {
  color: var(--accent-dark);
}

.grand-row {
  border-top: 2px solid var(--ink, #17222e);
  border-bottom: 0;
  margin-top: 10px;
  padding-top: 10px;
}

.grand-label {
  font-weight: 700;
  flex: 1 1;
}

.grand-row .grand-total {
  font-weight: 700;
  font-size: 1.05rem;
}

/* --------------------------------------------- reports on a trip ------ */

/* A divider between the documents a trip can produce. They are separate
   decisions - one is filed, one is emailed, one goes to a state agency -
   and running them together as three identical buttons invites the wrong
   one being pressed. */
.rule {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 18px 0 14px;
}

/* The actuals report, previewed before it is sent. */
.prepared {
  margin-top: 4px;
}

.recipients {
  margin: 0 0 12px;
  padding-left: 22px;
  font-size: 0.92rem;
}

.recipients li {
  padding: 1px 0;
}

/* Cancel and confirm, side by side and equal - the destructive-ish one is
   not the one your thumb lands on by default. */
.actions.two-up {
  display: flex;
  gap: 10px;
  flex-wrap: nowrap;
}

.actions.two-up button {
  flex: 1 1;
}

/* A link that acts as a button: View and Download are navigations, so they
   have to be anchors, but they sit in a row of buttons and must not look
   like loose text. Mirrors the button rules above deliberately. */
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: none;
  border-radius: 999px;
  padding: 10px 18px;
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 700;
  font-size: var(--fs-body);
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
}

a.btn.secondary {
  background: var(--surface);
  color: var(--accent-dark);
  border: 1.5px solid var(--border-strong);
}

a.btn:hover {
  background: var(--accent-dark);
}

a.btn.secondary:hover {
  background: var(--surface-2);
}

/* The row of actions on a generated report sits tight to the right rather
   than stretching - these are small, frequent, low-stakes controls. */
.list .actions button,
.list .actions a.btn {
  width: auto;
  padding: 10px 18px;
}

/* ------------------------------------------------- leader rules ------- */

/* A dotted rule running from a heading to its subtotal.
 *
 * On a wide screen the label sits at the left and the figure at the far
 * right, and the eye has to cross empty space to pair them - the wider the
 * card, the easier it is to read a total against the wrong row. The leader
 * is the same device a table of contents uses, for the same reason.
 *
 * The GRAND TOTAL only, now. Every group heading carries a solid rule
 * directly beneath it instead, and a dotted line through the heading row as
 * well was two lines competing to do one job. Detail rows never had one:
 * they are read as a list, not looked up a row at a time.
 *
 * Built from a pseudo-element so no markup carries a presentational span.
 * The label becomes the flex container and the leader takes the slack. */
.grand-label {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1;
  min-width: 0;
}

.grand-label::after {
  content: "";
  flex: 1 1;
  /* Never let the leader squeeze the label out; below this it reads as a
     rendering fault rather than a guide. */
  min-width: 16px;
  /* Sits on the text baseline rather than through the middle of it. */
  align-self: flex-end;
  margin-bottom: 0.34em;
  border-bottom: 1px dotted var(--border-strong);
}

/* The grand total is the figure everything else adds up to, so its leader
   is solid and its own weight rather than a dotted hint. */
.grand-label::after {
  border-bottom-style: solid;
  border-bottom-color: var(--border);
}

/* The result of generating a document: what you can now DO with it, in
   the place the button was. The buttons are small and side by side - these
   are four cheap choices, not a form to fill in. */
.ok-box .actions button,
.ok-box .actions a.btn {
  width: auto;
  padding: 9px 16px;
  font-size: var(--fs-small);
}

.ok-box .actions {
  gap: 8px;
}

/* What to do with a crop box, said above the controls. Without it the
   lightbox is an image and two buttons, and on a phone it is not obvious
   that the picture itself is the thing you drag on. */
.crop-hint {
  margin: 8px 0 0;
  text-align: center;
  font-size: var(--fs-small);
}

