/*
 * Creo CTE — front-end styles.
 *
 * MOBILE FIRST. The phone is the primary device: this gets opened standing in
 * a restaurant to add a bill, not at a desk. So the base rules below ARE the
 * phone layout — no min-width query needed to get it — and the two `min-width`
 * blocks at the bottom progressively add breathing room for tablet and desktop.
 * Anything added here must be checked at 320px wide before it is checked
 * anywhere else.
 *
 * Scoped under .cte-* throughout so the plugin can drop into any theme without
 * a fight. The palette is neutral by design: the only strong colours are green
 * for "you are owed" and red for "you owe", because those two states are what a
 * person opens this app to find out.
 */

:root {
  --cte-bg: #f6f7f9;
  --cte-surface: #ffffff;
  --cte-line: #e3e6ea;
  --cte-text: #1d2127;
  --cte-muted: #6b7480;
  --cte-accent: #2f6fed;
  --cte-positive: #12855a;
  --cte-negative: #c2374b;
  --cte-warn: #9a5b00;
  --cte-radius: 12px;

  /* Page gutter. Tight on a phone so content is not squeezed into a column
     inside a column, and it opens up from the tablet breakpoint. */
  --cte-gutter: 14px;
  /* Minimum comfortable touch target. 44px is the Apple HIG figure and the one
     that stops mis-taps on a moving train. */
  --cte-tap: 44px;
}

/* EVERY root the plugin renders has to be named here, not just .cte-app.
   This has bitten twice: modals are appended to document.body, and the
   signed-out gate used to render outside the app root. Both then missed
   border-box, and the symptom is never obviously a box-model problem — inputs
   silently grew from 44px to 66px tall, and a `width: 100%` button overflowed
   its padded container to the right. If you add another top-level container,
   add it here too. */
.cte-app,
.cte-app *,
.cte-overlay,
.cte-overlay *,
.cte-gate,
.cte-gate * {
  box-sizing: border-box;
}

/* Make the `hidden` attribute actually hide things.
   The browser's built-in rule is `[hidden] { display: none }` — a plain
   attribute selector, which ANY class selector that sets `display` outranks.
   .cte-scan-progress is `display: flex`, so it ignored `hidden` and sat on
   screen from the moment the sheet opened: empty thumbnail, no text, spinner
   running. Nothing in the JS was wrong; the attribute simply had no effect.
   This has to stay ahead of every component rule below. */
.cte-app [hidden],
.cte-overlay [hidden],
.cte-gate [hidden] {
  display: none !important;
}

.cte-app {
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--cte-text);
  background: var(--cte-bg);
  margin: 0;
  min-height: 100vh;
  /* dvh tracks the shrinking viewport as mobile Safari's address bar collapses;
     the vh above stays as the fallback for browsers without it. */
  min-height: 100dvh;
  /* The horizontal clip lives on .cte-wrap rather than here: the fixed bottom
     bar is a child of this element, and an ancestor that clips would cut it
     off entirely. */
}

.cte-wrap {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: 14px var(--cte-gutter);
  /* Clears the fixed bottom bar AND the iOS home indicator, so the last trip
     can always be scrolled out from under the button. */
  padding-bottom: calc(104px + env(safe-area-inset-bottom));

  /* Nothing may cause a sideways scroll. On a phone a single overflowing row
     makes the whole page slide, which reads as the app being broken.
     `clip` rather than `hidden` deliberately: `overflow-x: hidden` forces the
     other axis to `auto`, turning this into a scroll container and breaking
     `position: sticky` on the header. A browser too old to know `clip` just
     ignores the line, which loses the belt but keeps the braces, since every
     row already has min-width: 0. The clip margin lets the trip cards' shadows
     breathe past the edge instead of being sliced off. */
  overflow-x: clip;
  overflow-clip-margin: 6px;
}

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

.cte-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px var(--cte-gutter);
  padding-top: calc(10px + env(safe-area-inset-top));
  background: var(--cte-surface);
  border-bottom: 1px solid var(--cte-line);
  /* Stays put while a long expense list scrolls, so "back" is always reachable
     without scrolling to the top first. */
  position: sticky;
  top: 0;
  z-index: 20;
}

/* The two side slots share a width so the wordmark sits optically centred
   rather than merely in the middle of whatever space is left over. */
.cte-header-side {
  display: flex;
  align-items: center;
  /* Tight on a phone, where three icons share the slot with a centred
     wordmark; opened up with the labels at 600px. */
  gap: 10px;
  flex: 1 1 0;
  min-width: 0;
}

.cte-header-right {
  justify-content: flex-end;
}

.cte-brand {
  display: block;
  flex: 0 0 auto;
  line-height: 0;
}

.cte-brand img {
  display: block;
  height: 22px;
  width: auto;
}

/* Mark and name side by side in the header, stacked on the signed-out gate. */
.cte-brand-lockup {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cte-logo {
  display: block;
  height: 24px;
  width: auto;
}

.cte-gate-mark.cte-brand-lockup {
  flex-direction: column;
  gap: 12px;
  margin-bottom: 24px;
}

.cte-gate-mark .cte-logo {
  height: 62px;
}

.cte-wordmark-text {
  display: block;
  font-size: clamp(17px, 4.5vw, 19px);
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--cte-text);
  white-space: nowrap;
}

.cte-gate-mark .cte-wordmark-text {
  font-size: 26px;
}

/* The back control is an arrow alone on a phone — the label would squeeze the
   wordmark off centre — and gains its text once there is room. */
.cte-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--cte-tap);
  margin-left: -6px;
  padding: 0 6px;
  -webkit-tap-highlight-color: transparent;
}

.cte-back svg {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
}

.cte-back-label { display: none; }

/* The wp-admin and profile links are icons alone on a phone; their labels
   would push the centred wordmark off centre at 320px. */
.cte-icon-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cte-icon-link svg {
  /* An icon reads as slightly smaller than a letterform at the same size, so it
     gets a little more than the 19px the text beside it occupies. */
  width: 20px;
  height: 20px;
  display: block;
}

.cte-icon-label { display: none; }

/* The person's own name, above the balance. Small and quiet: the number is the
   headline, this is just orientation. */
.cte-greeting {
  margin: 2px 0 10px;
  font-size: 13px;
  color: var(--cte-muted);
}

/* The trip name, moved out of the header so it can wrap instead of truncating
   to a few characters between the back arrow and Log out. */
.cte-page-title {
  margin: 4px 0 12px;
  font-size: clamp(21px, 5.5vw, 26px);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.cte-back,
.cte-logout {
  color: var(--cte-muted);
  text-decoration: none;
  font-size: 13px;
  white-space: nowrap;
}

.cte-back:hover,
.cte-logout:hover {
  color: var(--cte-accent);
}

/* --- headline balance --------------------------------------------------- */

.cte-hero {
  background: var(--cte-surface);
  border: 1px solid var(--cte-line);
  border-radius: var(--cte-radius);
  padding: 20px 16px;
  text-align: center;
  margin-bottom: 14px;
}

.cte-hero-amount {
  font-size: clamp(30px, 9vw, 40px);
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.cte-hero.cte-positive .cte-hero-amount { color: var(--cte-positive); }
.cte-hero.cte-negative .cte-hero-amount { color: var(--cte-negative); }

.cte-hero-label {
  color: var(--cte-muted);
  font-size: 14px;
  margin-top: 2px;
}

.cte-hero-split {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 20px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--cte-line);
  font-size: 13px;
}

/* --- sections ----------------------------------------------------------- */

.cte-section {
  background: var(--cte-surface);
  border: 1px solid var(--cte-line);
  border-radius: var(--cte-radius);
  padding: 14px;
  margin-bottom: 14px;
}

.cte-section h3 {
  margin: 0 0 10px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--cte-muted);
}

.cte-subhead {
  margin: 18px 0 6px;
  font-size: 13px;
  color: var(--cte-muted);
}

.cte-empty {
  color: var(--cte-muted);
  font-size: 14px;
  margin: 8px 0;
}

/* A button introducing a list, rather than sitting in a row of actions. Full
   width on a phone: it is the primary action of that section and a thumb
   should not have to aim for it. */
.cte-section > .cte-btn {
  display: flex;
  width: 100%;
  margin-bottom: 12px;
}

/* --- lists -------------------------------------------------------------- */

.cte-people,
.cte-trips,
.cte-debts,
.cte-expenses {
  list-style: none;
  margin: 0;
  padding: 0;
}

.cte-person,
.cte-debt {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Tall enough to be a comfortable tap target in its own right. */
  min-height: var(--cte-tap);
  padding: 10px 2px;
  border-bottom: 1px solid var(--cte-line);
}

/* --- swipe-to-delete rows ----------------------------------------------- */

/* The row is now a track: the Delete button sits underneath and only
   .cte-swipe-body moves, so nothing reflows while a finger is down. */
.cte-expense {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--cte-line);
}

.cte-swipe-body {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--cte-tap);
  padding: 10px 2px;
  background: var(--cte-surface);
  transform: translateX(0);
  transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.3, 1);
  /* Tells the browser it still owns vertical scrolling, so a list scrolls on
     the compositor thread until the handler claims a horizontal gesture. */
  touch-action: pan-y;
}

/* No transition while a finger is down — the row must track the finger
   exactly, not lag behind it by the animation duration. */
.cte-swipe-body.cte-dragging {
  transition: none;
}

.cte-swipe.cte-open .cte-swipe-body {
  transform: translateX(-96px);
}

.cte-swipe-action {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 96px;
  display: flex;
}

.cte-swipe-delete {
  flex: 1;
  border: 0;
  background: var(--cte-negative);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* The × is the affordance for pointer devices, where there is no swipe to
   discover. On touch it only steals width from the title. */
@media (hover: none) {
  .cte-row-delete { display: none; }
}

@media (hover: hover) {
  .cte-swipe-delete:hover { background: #a82c3e; }
}

.cte-expense .cte-icon {
  min-width: var(--cte-tap);
}

.cte-person:last-child,
.cte-expense:last-child,
.cte-debt:last-child {
  border-bottom: 0;
}

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

/* Each trip is its own raised card with a gap around it and a chevron, rather
   than a row inside one shared block. On touch there is no hover to reveal
   that something is tappable, so the affordance has to be visible at rest. */
.cte-trip-card {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 62px;
  margin-bottom: 10px;
  padding: 12px 12px 12px 14px;
  background: var(--cte-surface);
  border: 1px solid var(--cte-line);
  border-radius: var(--cte-radius);
  box-shadow: 0 1px 2px rgba(20, 24, 31, 0.05);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

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

/* Presses in, so a tap is acknowledged before the next screen paints. */
.cte-trip-card:active {
  background: #f7f9fc;
  transform: scale(0.994);
}

.cte-chevron {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  color: #b6bdc7;
}

/* Smaller on an expense row than on a trip card: the row already carries an
   amount and a share, and this only has to say "there is more here". */
.cte-expense .cte-chevron {
  width: 15px;
  height: 15px;
  flex: 0 0 15px;
  margin-left: -2px;
}

/* --- expense detail sheet ----------------------------------------------- */

.cte-detail-amount {
  font-size: 30px;
  font-weight: 650;
  letter-spacing: -0.02em;
  text-align: center;
  margin-bottom: 14px;
}

.cte-detail {
  margin: 0 0 4px;
  border-top: 1px solid var(--cte-line);
}

.cte-detail > div {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--cte-line);
}

.cte-detail dt {
  flex: 0 0 84px;
  color: var(--cte-muted);
  font-size: 13px;
}

.cte-detail dd {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 14.5px;
}

.cte-detail-notes {
  margin: 12px 0 0;
  padding: 10px 12px;
  background: var(--cte-bg);
  border-radius: 9px;
  font-size: 14px;
}

.cte-detail-meta {
  margin: 14px 0 0;
  color: var(--cte-muted);
  font-size: 12.5px;
  text-align: center;
}

/* Heading for a list that is not wrapped in a section card. */
.cte-list-head {
  margin: 20px 0 10px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--cte-muted);
}

.cte-empty-block {
  background: var(--cte-surface);
  border: 1px dashed var(--cte-line);
  border-radius: var(--cte-radius);
  padding: 20px 16px;
  text-align: center;
  margin: 0;
}

/* --- pinned bottom action ----------------------------------------------- */

.cte-bottom-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  padding: 10px var(--cte-gutter);
  padding-bottom: calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--cte-line);
  /* Translucent so the list reads as continuing underneath rather than ending
     abruptly at the bar. */
  background: rgba(246, 247, 249, 0.88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

/* Without backdrop-filter the translucency only looks washed out, so fall back
   to a solid ground. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cte-bottom-bar { background: var(--cte-bg); }
}

.cte-bottom-bar-inner {
  max-width: 720px;
  margin: 0 auto;
}

.cte-btn-lg {
  width: 100%;
  min-height: 50px;
  font-size: 15.5px;
  font-weight: 550;
  border-radius: 11px;
}

.cte-trip-main,
.cte-expense-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  /* Without this a long title refuses to shrink and pushes the amount off the
     right edge — the single most common cause of a sideways scroll here. */
  min-width: 0;
}

.cte-expense-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex: 0 0 auto;
  /* Capped so the amount column cannot crowd the expense title out of
     existence on a narrow screen. */
  max-width: 46%;
}

.cte-expense-right .cte-trip-meta {
  white-space: nowrap;
}

.cte-trip-title,
.cte-expense-title {
  font-weight: 550;
  font-size: 15px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cte-trip-meta {
  color: var(--cte-muted);
  font-size: 12.5px;
}

/* The secondary line truncates like the title above it. Without this the title
   clips to a few characters while the meta below it wraps to four lines, and
   every row ends up a different height. */
.cte-expense-main .cte-trip-meta,
.cte-trip-main .cte-trip-meta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cte-person-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cte-amount {
  font-variant-numeric: tabular-nums;
  font-weight: 550;
  white-space: nowrap;
  flex: 0 0 auto;
}

.cte-positive { color: var(--cte-positive); }
.cte-negative { color: var(--cte-negative); }

.cte-pending {
  color: var(--cte-muted);
  font-size: 12px;
  font-style: normal;
}

/* --- who-pays-whom rows ------------------------------------------------- */

/* Two names, two avatars and an amount will not fit on one 320px line, so the
   parties form their own wrapping group and the amount holds the right edge.
   On a narrow screen the names wrap under each other; on a wide one it reads
   as a single line. */
.cte-debt {
  flex-wrap: wrap;
}

.cte-debt-parties {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.cte-debt-party {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.cte-debt-party span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cte-arrow {
  color: var(--cte-muted);
  font-size: 12.5px;
  flex: 0 0 auto;
}

/* --- avatars & badges --------------------------------------------------- */

.cte-avatar {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
  border-radius: 50%;
  background: #e7ecf6;
  color: #35507f;
  font-size: 11.5px;
  font-weight: 650;
  overflow: hidden;
}

/* The photo sits on top of the initials. If it fails to load — which is what
   Gravatar's 404 default produces for someone with no image — it is removed and
   the initials are simply already there, with nothing to swap in. */
.cte-avatar-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

.cte-status {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: #e7ecf6;
  color: #35507f;
}

.cte-status-closed  { background: #fdf0dc; color: var(--cte-warn); }
.cte-status-settled { background: #e2f3ea; color: var(--cte-positive); }

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

.cte-btn {
  font: inherit;
  font-size: 14px;
  /* Several of these are anchors, not <button>s — without this they render
     underlined with the label sitting off-centre. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  min-height: var(--cte-tap);
  padding: 10px 14px;
  border: 1px solid var(--cte-line);
  border-radius: 9px;
  background: var(--cte-surface);
  color: var(--cte-text);
  cursor: pointer;
  /* Stops iOS from flashing a grey box over the button on tap. */
  -webkit-tap-highlight-color: transparent;
}

.cte-btn-primary {
  background: var(--cte-accent);
  border-color: var(--cte-accent);
  color: #fff;
}

.cte-btn-warn {
  color: var(--cte-warn);
  border-color: #ecd7b0;
}

.cte-btn-danger {
  background: var(--cte-negative);
  border-color: var(--cte-negative);
  color: #fff;
}

.cte-confirm-text {
  margin: 0;
  color: var(--cte-muted);
  font-size: 14.5px;
}

.cte-btn[disabled] {
  opacity: 0.55;
  cursor: default;
}

.cte-icon {
  border: 0;
  background: none;
  color: var(--cte-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  /* A bare glyph is a tiny target; this gives it a real one without changing
     how it looks. */
  min-width: var(--cte-tap);
  min-height: var(--cte-tap);
  flex: 0 0 auto;
  -webkit-tap-highlight-color: transparent;
}

/* Hover styling only where a pointer actually exists. On a touch device these
   rules stick after a tap and leave rows looking selected. */
@media (hover: hover) {
  .cte-btn:hover { border-color: #c9ced6; }
  .cte-btn-primary:hover { background: #2560d4; }
  .cte-icon:hover { color: var(--cte-negative); }
  .cte-trip-card:hover { background: #fafbfc; }
  /* The body carries the background now, so hovering the track alone would
     never show through it. */
  .cte-expense:hover .cte-swipe-body { background: #fafbfc; }
  .cte-check:hover,
  .cte-split-row:hover { background: #f6f8fb; }
}

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

.cte-trip-head {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  margin-bottom: 14px;
}

/* Two even columns on a phone, so four actions make a tidy 2x2 block of real
   tap targets instead of a wrapped row of small ones. */
.cte-actions {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

.cte-actions .cte-btn {
  width: 100%;
  padding: 10px 8px;
}

/* An odd number of actions: the last one spans both columns rather than
   leaving a gap. */
.cte-actions .cte-btn:last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

.cte-notice {
  background: #fdf7ec;
  border: 1px solid #f0e0c2;
  color: #6d4c14;
  border-radius: var(--cte-radius);
  padding: 12px 14px;
  font-size: 13.5px;
  margin-bottom: 14px;
}

.cte-invite {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 0;
  border-bottom: 1px solid var(--cte-line);
}

.cte-invite:last-child { border-bottom: 0; }

.cte-invite .cte-btn {
  flex: 1;
  min-width: 110px;
}

/* --- modals ------------------------------------------------------------- */

/* On a phone a modal is a bottom sheet: anchored to the thumb, not floating in
   the middle of the screen out of reach. It becomes a centred dialog from the
   tablet breakpoint down the file. */
.cte-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 24, 31, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 9999;
}

.cte-modal {
  background: var(--cte-surface);
  border-radius: 16px 16px 0 0;
  width: 100%;
  /* Never taller than the screen; the body scrolls inside instead. */
  max-height: 92vh;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 -8px 40px rgba(20, 24, 31, 0.28);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--cte-text);
}

.cte-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--cte-line);
  flex: 0 0 auto;
}

.cte-modal-head h2 {
  margin: 0;
  font-size: 17px;
}

.cte-modal-body {
  padding: 14px;
  /* The one scrolling region, so the title and the submit button stay put
     while a long member list moves. */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  flex: 1 1 auto;
}

.cte-modal-foot {
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  padding-bottom: calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--cte-line);
  flex: 0 0 auto;
}

/* Full-width split footer buttons on a phone, primary on the right where the
   thumb rests. */
.cte-modal-foot .cte-btn {
  flex: 1;
}

/* --- forms -------------------------------------------------------------- */

.cte-field {
  display: block;
  margin-bottom: 12px;
}

.cte-field > span {
  display: block;
  font-size: 12.5px;
  color: var(--cte-muted);
  margin-bottom: 4px;
}

.cte-field input[type="text"],
.cte-field input[type="email"],
.cte-field input[type="date"],
.cte-field input[type="datetime-local"],
.cte-field select {
  width: 100%;
  font: inherit;
  /* MUST stay at 16px or larger. Mobile Safari zooms the whole page in when a
     focused input is under 16px, and it does not zoom back out — the app then
     looks broken for the rest of the session. */
  font-size: 16px;
  min-height: var(--cte-tap);
  padding: 10px 12px;
  border: 1px solid var(--cte-line);
  border-radius: 9px;
  background: #fff;
  color: inherit;
  /* iOS otherwise applies its own inset shadow and rounding to inputs. */
  -webkit-appearance: none;
  appearance: none;
}

.cte-field input:focus,
.cte-field select:focus {
  outline: 2px solid rgba(47, 111, 237, 0.35);
  outline-offset: 1px;
  border-color: var(--cte-accent);
}

/* Paired fields stack on a phone and sit side by side from tablet up. */
.cte-row {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.cte-row > .cte-field { flex: 1; }

.cte-checklist {
  max-height: 46vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--cte-line);
  border-radius: 9px;
  padding: 4px;
}

.cte-check {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--cte-tap);
  padding: 6px 8px;
  border-radius: 7px;
  cursor: pointer;
}

.cte-check input[type="checkbox"],
.cte-split-row input[type="checkbox"] {
  /* The browser default is around 13px, which is a poor target and visually
     lost next to a 28px avatar. */
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  accent-color: var(--cte-accent);
}

/* --- receipt scanning --------------------------------------------------- */

.cte-scan {
  margin-bottom: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--cte-line);
}

.cte-scan-btn {
  width: 100%;
  gap: 8px;
  border-style: dashed;
  color: var(--cte-accent);
  border-color: #c3d4f7;
  background: #f7f9ff;
}

/* Stacked, camera first: photographing the receipt at the table is the common
   case, and it should be the one under the thumb. */
.cte-scan-btn + .cte-scan-btn {
  margin-top: 8px;
}

.cte-scan-btn svg {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
}

/* Sits where the buttons were, so the sheet does not jump as it appears. */
.cte-scan-progress {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
  padding: 10px 12px;
  border: 1px solid #c3d4f7;
  border-radius: 10px;
  background: #f7f9ff;
}

/* The photo just taken, so it is obvious which image is being read — and that
   the camera actually captured something. */
.cte-scan-thumb {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  border-radius: 8px;
  object-fit: cover;
  background: #e7ecf6;
}

.cte-scan-status {
  flex: 1;
  min-width: 0;
}

.cte-scan-stage {
  font-size: 13.5px;
  font-weight: 550;
}

.cte-scan-sub {
  font-size: 12px;
  color: var(--cte-muted);
}

.cte-spinner {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  border-radius: 50%;
  border: 2px solid #c9d8f8;
  border-top-color: var(--cte-accent);
  animation: cte-spin 0.7s linear infinite;
}

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

.cte-scan-note {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--cte-muted);
  text-align: center;
}

/* --- split editor ------------------------------------------------------- */

.cte-segmented {
  display: grid;
  /* Four methods across a 320px screen would be ~70px each and unreadable, so
     they wrap to a 2x2 grid and go to a single row when there is room. */
  grid-template-columns: repeat(2, 1fr);
  border: 1px solid var(--cte-line);
  border-radius: 9px;
  overflow: hidden;
}

.cte-segmented button {
  font: inherit;
  font-size: 13px;
  min-height: 40px;
  padding: 8px 6px;
  border: 0;
  border-right: 1px solid var(--cte-line);
  border-bottom: 1px solid var(--cte-line);
  background: #fff;
  color: var(--cte-muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.cte-segmented button:nth-child(2n) { border-right: 0; }
.cte-segmented button:nth-last-child(-n+2) { border-bottom: 0; }

.cte-segmented button.cte-on {
  background: var(--cte-accent);
  color: #fff;
}

.cte-split-list {
  border: 1px solid var(--cte-line);
  border-radius: 9px;
  padding: 4px;
  margin-bottom: 8px;
}

.cte-split-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--cte-tap);
  padding: 6px;
  border-radius: 7px;
  cursor: pointer;
}

.cte-split-row.cte-off { opacity: 0.45; }

.cte-split-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cte-split-value {
  /* Narrow enough that checkbox + avatar + name + input + amount still fit at
     320px, wide enough for "100.00". */
  width: 68px;
  flex: 0 0 68px;
  font: inherit;
  font-size: 16px;
  min-height: 38px;
  text-align: right;
  padding: 6px 8px;
  border: 1px solid var(--cte-line);
  border-radius: 7px;
  -webkit-appearance: none;
  appearance: none;
}

.cte-split-amount {
  width: 68px;
  flex: 0 0 68px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 550;
  font-size: 14px;
}

.cte-split-total {
  font-size: 13px;
  color: var(--cte-muted);
  text-align: right;
  margin: 0;
}

/* --- assigning receipt lines to people ----------------------------------- */

.cte-item-btn {
  width: 100%;
  margin-top: 8px;
  border-style: dashed;
  color: var(--cte-accent);
  border-color: #c3d4f7;
  background: #f7f9ff;
}

.cte-items {
  list-style: none;
  margin: 0 0 4px;
  padding: 0;
}

.cte-item {
  padding: 10px 0;
  border-bottom: 1px solid var(--cte-line);
}

.cte-item:last-child { border-bottom: 0; }

.cte-item-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 8px;
}

.cte-item-name {
  flex: 1;
  min-width: 0;
  font-weight: 550;
  font-size: 14.5px;
}

.cte-item-people {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* A name chip is on by default and dims when tapped off — the row always shows
   who could be on the line, not just who is, so putting somebody back is the
   same gesture as taking them off. */
.cte-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 3px 10px 3px 3px;
  border: 1px solid var(--cte-line);
  border-radius: 999px;
  background: #fff;
  font: inherit;
  font-size: 13px;
  color: var(--cte-muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.cte-chip .cte-avatar {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  font-size: 10px;
}

.cte-chip.cte-on {
  border-color: var(--cte-accent);
  background: #eef4ff;
  color: var(--cte-text);
  font-weight: 550;
}

.cte-chip:not(.cte-on) {
  opacity: 0.55;
}

.cte-chip:not(.cte-on) .cte-avatar {
  filter: grayscale(1);
}

/* A skipped line stays visible and legible — struck through rather than
   removed — so it is obvious what is being left out and equally obvious how to
   put it back. */
.cte-item.cte-skipped .cte-item-name,
.cte-item.cte-skipped .cte-amount {
  text-decoration: line-through;
  color: var(--cte-muted);
}

/* Not decided yet: quiet, not struck through. Only a line somebody has
   actually emptied gets the skipped treatment. */
.cte-item.cte-untouched .cte-item-name {
  color: var(--cte-muted);
}

.cte-skip-badge {
  flex: 0 0 auto;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
  background: #fdf0dc;
  color: var(--cte-warn);
}

.cte-item-units {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--cte-muted);
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--cte-bg);
}

/* Per-unit assignment: a minus, the avatar, the count, a plus. */
.cte-stepper {
  gap: 2px;
  padding: 2px 4px 2px 2px;
}

.cte-step {
  width: 30px;
  min-height: 32px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 17px;
  line-height: 1;
  color: var(--cte-accent);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.cte-step[disabled] {
  color: #c9ced6;
  cursor: default;
}

.cte-step-count {
  min-width: 16px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 650;
}

/* The per-line mode switch. Quiet: most lines never need it. */
.cte-item-mode {
  margin-top: 8px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12.5px;
  color: var(--cte-accent);
  text-decoration: underline;
  cursor: pointer;
}

.cte-item-adjust {
  margin: 10px 0 0;
  padding: 10px 12px;
  border-radius: 9px;
  background: #fdf7ec;
  border: 1px solid #f0e0c2;
  color: #6d4c14;
  font-size: 13px;
}

/* Running totals: what each person had, and what they actually pay once the
   tax and tip are shared out. */
.cte-item-totals .cte-trip-meta {
  flex: 0 0 auto;
  margin-right: 8px;
}

/* --- close-trip comparison ---------------------------------------------- */

.cte-compare {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
}

.cte-compare > div {
  min-width: 0;
}

/* --- ledger table ------------------------------------------------------- */

/* The table keeps its natural width and scrolls sideways inside this box, so a
   seven-column audit trail is readable on a phone without the page itself
   moving. */
#cte-ledger {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-top: 10px;
}

.cte-ledger {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: 12.5px;
}

.cte-ledger th,
.cte-ledger td {
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--cte-line);
  white-space: nowrap;
}

.cte-ledger th {
  color: var(--cte-muted);
  font-weight: 550;
}

.cte-ledger .cte-right { text-align: right; }

/* Reversing rows are dimmed rather than hidden: the whole point of an
   append-only ledger is that the undone entry stays readable. */
.cte-ledger .cte-reversal td {
  color: var(--cte-muted);
  font-style: italic;
}

/* --- misc --------------------------------------------------------------- */

.cte-gate {
  max-width: 380px;
  margin: 0 auto;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 0 var(--cte-gutter);
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* Sized by its contents now that this is a mark plus a name, not a single
   image — the old fixed height clipped the lockup and let the name overlap the
   heading below it. */
.cte-gate-mark {
  margin: 0 auto 24px;
}

.cte-gate h2 {
  margin: 0 0 8px;
  font-size: 22px;
  letter-spacing: -0.01em;
}

.cte-gate-sub {
  margin: 0 0 24px;
  color: var(--cte-muted);
  font-size: 14.5px;
}

.cte-gate .cte-btn-lg {
  width: 100%;
}

.cte-loading {
  padding: 60px 20px;
  text-align: center;
  color: var(--cte-muted);
}

.cte-toast {
  position: fixed;
  left: 50%;
  bottom: calc(20px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  /* Stays inside the screen on a narrow phone instead of running off both
     edges when the message is long. */
  width: max-content;
  max-width: calc(100vw - 32px);
  background: #1d2127;
  color: #fff;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 14px;
  text-align: center;
  z-index: 10000;
  box-shadow: 0 8px 24px rgba(20, 24, 31, 0.3);
}

.cte-toast-error { background: var(--cte-negative); }

/* =========================================================================
 * Tablet and up — 600px is where two fields fit side by side comfortably.
 * ====================================================================== */

@media (min-width: 380px) {
  .cte-row {
    flex-direction: row;
    gap: 10px;
  }
}

@media (min-width: 600px) {
  :root { --cte-gutter: 18px; }

  .cte-brand img { height: 24px; }

  .cte-header-side { gap: 14px; }

  .cte-back-label,
  .cte-icon-label { display: inline; }

  .cte-icon-link svg { display: none; }

  /* Full-bleed is right under a thumb; on a wide screen it just looks heavy,
     so the button keeps its own size and centres in the bar. */
  .cte-bottom-bar-inner {
    display: flex;
    justify-content: center;
  }

  .cte-btn-lg {
    width: auto;
    min-width: 220px;
  }

  .cte-wrap { padding: 20px var(--cte-gutter) 64px; }

  .cte-section { padding: 16px 18px; }

  .cte-hero { padding: 24px; }

  /* Back to a normal inline button once there is room for it. */
  .cte-section > .cte-btn {
    display: inline-flex;
    width: auto;
  }

  .cte-trip-head {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

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

  .cte-actions .cte-btn {
    width: auto;
    min-height: 38px;
    padding: 8px 13px;
  }

  .cte-row {
    flex-direction: row;
    gap: 12px;
  }

  .cte-segmented {
    grid-template-columns: repeat(4, 1fr);
  }

  .cte-segmented button {
    border-bottom: 0;
    border-right: 1px solid var(--cte-line);
  }

  .cte-segmented button:last-child { border-right: 0; }

  .cte-compare {
    flex-direction: row;
    gap: 18px;
  }

  .cte-compare > div { flex: 1; }

  /* A centred dialog rather than a bottom sheet once the screen is big enough
     that the middle is still easy to reach. */
  .cte-overlay {
    align-items: flex-start;
    padding: 24px 12px;
    overflow-y: auto;
  }

  .cte-modal {
    max-width: 560px;
    border-radius: 14px;
    max-height: none;
    box-shadow: 0 18px 48px rgba(20, 24, 31, 0.22);
  }

  .cte-modal-body { overflow-y: visible; }

  .cte-modal-foot { justify-content: flex-end; }

  .cte-modal-foot .cte-btn { flex: 0 0 auto; }

  .cte-btn {
    min-height: 38px;
    padding: 8px 14px;
  }

  .cte-debt { flex-wrap: nowrap; }
}

/* =========================================================================
 * Desktop.
 * ====================================================================== */

@media (min-width: 900px) {
  :root { --cte-gutter: 20px; }

  .cte-header { padding: 14px 20px; }
}

/* Respect a reduced-motion preference. This has to name .cte-overlay too:
   modals are appended to <body>, so a rule scoped to .cte-app misses them —
   the same blind spot that cost the modals their box-sizing. */
@media (prefers-reduced-motion: reduce) {
  .cte-app *,
  .cte-overlay * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }

  /* A frozen ring reads as broken, so the spinner becomes a plain dot and the
     stage text carries the progress on its own. */
  .cte-spinner {
    border-color: var(--cte-accent);
    border-top-color: var(--cte-accent);
    opacity: 0.5;
  }
}
