/* THE hidden ATTRIBUTE HAS TO ACTUALLY HIDE.
   Its default is display:none from the UA sheet, which any rule with a
   display of its own beats - and a lot of rows here are display:flex. So
   `el.hidden = true` sets the attribute, the element stays on screen, and
   the JavaScript looks correct: the booking form's special-item steppers
   were drawn on all sixteen rows, ticked or not, because .count-controls
   is flex. css/site.css learned this the same way (a car rental form
   showing the car and bus panels stacked on top of each other); this is
   the same rule for the logged-in product's stylesheet. */
[hidden] { display: none !important; }

:root {
  color-scheme: light;
  /* SAFEUP brand palette (from the official logo/brand board) */
  --brand: #00bfa6;
  --brand-bright: #00e0b5;
  --brand-dark: #0d182a;
  --bg: #f5f7fb;
  --surface: #ffffff;
  --text: #0d182a;
  --muted: #5b6472;
  --border: #e2e6ed;
  --danger: #d92d20;
  --success: #12805c;

  /* Elevation: soft, diffused, multi-layer (Stripe's approach) rather
     than one hard drop-shadow - each level stacks a tight "contact"
     shadow with a wider, softer ambient one so cards read as sitting
     just above the surface instead of pasted on top of it. */
  --shadow-sm: 0 1px 2px rgba(13, 24, 42, 0.04), 0 1px 1px rgba(13, 24, 42, 0.03);
  --shadow-md: 0 2px 6px rgba(13, 24, 42, 0.05), 0 8px 20px -8px rgba(13, 24, 42, 0.12);
  --shadow-lg: 0 4px 10px rgba(13, 24, 42, 0.06), 0 20px 44px -16px rgba(13, 24, 42, 0.22);

  /* Generous, consistently-rounded corners (Airbnb's warmth) applied
     everywhere via these two tokens rather than one-off radius values
     per component. */
  --radius-md: 12px;
  --radius-lg: 20px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: "Manrope", -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: 700;
  letter-spacing: -0.02em;
}

header.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 32px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

header.topbar .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--brand-dark);
  text-decoration: none;
}

header.topbar .brand-icon {
  height: 30px;
  width: auto;
  display: block;
}

/* SAFEUP wordmark - per the brand board: Poppins, "SAFE" in the dark
   brand color and "UP" in the bright brand teal. Used anywhere the brand
   name itself is the thing being displayed (header, footer) rather than
   just mentioned in passing inside a sentence. */
.brand-wordmark {
  font-family: "Poppins", "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
  font-weight: 800;
}

.brand-wordmark .up {
  color: var(--brand-bright);
}

header.topbar nav {
  display: flex;
  align-items: center;
  gap: 20px;
}

header.topbar nav a {
  color: var(--text);
  text-decoration: none;
  font-size: 0.95rem;
}

header.topbar .lang-select {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 6px 10px;
  font-size: 0.85rem;
  color: var(--text);
  background: var(--surface);
}

header.topbar .lang-select:hover,
header.topbar .lang-select:focus {
  border-color: var(--brand);
  outline: none;
}

/* THE TOP BAR ON A PHONE.
   Thirty-three pages share this bar and not one of them had a breakpoint
   for it. At 390px the brand, the language selector and the links all sat
   on one row and flexbox did what flexbox does: it squeezed them. The
   selector read "Bahasa Indones" on the narrow pages and was given
   TWENTY-TWO pixels of its hundred and forty-three on booking.html and
   itinerary.html - present, unreadable, and impossible to spot in the
   page-overflow sweep, because a squeezed flex item never makes the page
   any wider.

   So: the bar may wrap, the nav may wrap, and the selector is the one
   thing that may not shrink. When the row cannot hold it the row breaks
   instead, which is the difference between a control that moved and a
   control that was cut in half. */
@media (max-width: 719px) {
  header.topbar {
    flex-wrap: wrap;
    padding: 12px 16px;
    row-gap: 10px;
    column-gap: 12px;
  }

  header.topbar .brand {
    font-size: 1.05rem;
    gap: 8px;
  }

  header.topbar .brand-icon { height: 26px; }

  /* THE NAV GETS ITS OWN ROW, and the measurements are why.

     The bar has 358px of content width at 390px. The wordmark takes 102.
     The language selector takes 208 - a <select> sizes to its widest
     OPTION, and the widest here is "Bahasa Indonesia", which is the whole
     point of a language picker and not something to trim. Add the login
     link and the nav needs 265. 102 + 12 + 265 = 379. It does not fit,
     and no amount of flex tuning makes 379 into 358.

     Three attempts proved that the hard way: letting the nav wrap
     internally squeezed it into a column beside the brand; forbidding the
     wrap overflowed the bar by up to 167px; pinning its basis to
     max-content left it at 208 and wrapping anyway.

     So the nav is simply given the second row. Two rows on a phone header
     is ordinary; a language selector reading "Bahasa Indones" is not. It
     is left-aligned under the wordmark rather than pushed right, so the
     bar reads as one block instead of leaving a hole in the top corner.
     The internal wrap stays for the pages carrying more links than one
     row holds - booking.html and itinerary.html - which is the only place
     it is ever needed. */
  header.topbar nav {
    flex: 1 1 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 12px;
    min-width: 0;
  }

  /* Sized by its own longest label, never by what is left over - and
     never by the form rule either. style.css sets width:100% on every
     select for form fields, which is right in a form and wrong in a
     header: with the nav on its own row that made the picker span the
     whole 358px with the login link stranded underneath it. */
  header.topbar .lang-select {
    flex: 0 0 auto;
    width: auto;
  }
}

main {
  max-width: 960px;
  margin: 0 auto;
  padding: 40px 24px;
}

/* ===================================================================
   Landing page (index.html only) - hero, feature/step grids, trust
   row, CTA banner, and scroll-reveal. Everything below is namespaced
   to these classes precisely so it never touches .stat-grid/.stat-card,
   which the admin/merchant/crew/track dashboards rely on for their own
   (much plainer, data-first) look.
   =================================================================== */

.hero {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 104px 24px 84px;
  margin: -40px -24px 56px;
  background:
    radial-gradient(60% 90% at 20% 0%, rgba(0, 224, 181, 0.35), transparent 60%),
    radial-gradient(50% 70% at 85% 15%, rgba(0, 191, 166, 0.25), transparent 55%),
    linear-gradient(180deg, rgba(13, 24, 42, 0.86) 0%, rgba(13, 24, 42, 0.74) 45%, rgba(13, 24, 42, 0.93) 100%),
    url("/img/hero-airport-pickup.jpg");
  background-size: auto, auto, auto, cover;
  background-position: center, center, center, center 35%;
  color: #fff;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.hero .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-bright);
  background: rgba(0, 224, 181, 0.12);
  border: 1px solid rgba(0, 224, 181, 0.35);
  padding: 6px 16px;
  border-radius: 999px;
  margin-bottom: 22px;
}

.hero h1 {
  font-size: clamp(2.1rem, 4.8vw, 3.4rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.14;
  margin: 0 0 18px;
  max-width: 740px;
  margin-left: auto;
  margin-right: auto;
}

.hero h1 .accent {
  background: linear-gradient(90deg, var(--brand-bright), #7ff5d9);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero p {
  color: #c7d0dd;
  font-size: 1.12rem;
  max-width: 560px;
  margin: 0 auto 36px;
  line-height: 1.6;
}

.hero-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}

.hero .btn {
  padding: 14px 30px;
  font-size: 1rem;
  box-shadow: 0 10px 30px -8px rgba(0, 224, 181, 0.55);
}

.hero .btn.secondary {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow: none;
}

.hero .btn.secondary:hover {
  background: rgba(255, 255, 255, 0.14);
}

.hero-links {
  font-size: 0.9rem;
}

.hero-links a {
  color: #c7d0dd;
}

.hero-links a:hover {
  color: #fff;
}

.trust-row {
  display: flex;
  justify-content: center;
  gap: 28px;
  flex-wrap: wrap;
  margin-top: 40px;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.trust-row .trust-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: #c7d0dd;
}

.trust-row svg {
  width: 18px;
  height: 18px;
  color: var(--brand-bright);
  flex-shrink: 0;
}

.btn {
  display: inline-block;
  padding: 12px 24px;
  border-radius: var(--radius-md);
  background: var(--brand);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  border: none;
  cursor: pointer;
  font-size: 1rem;
  box-shadow: var(--shadow-sm);
  transition: background-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}

.btn:hover {
  background: var(--brand-dark);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(1px);
  box-shadow: var(--shadow-sm);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}

.btn.secondary {
  background: transparent;
  color: var(--brand);
  border: 1px solid var(--brand);
}

.btn.secondary:hover {
  background: rgba(0, 191, 166, 0.08);
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px;
  margin-bottom: 20px;
  box-shadow: var(--shadow-sm);
}

.form-group {
  margin-bottom: 16px;
}

label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.9rem;
  font-weight: 600;
}

input, select, textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 1rem;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(0, 191, 166, 0.15);
}

input:disabled, select:disabled, textarea:disabled {
  background: var(--bg);
  color: var(--muted);
  cursor: not-allowed;
}

.alert {
  padding: 12px 16px;
  border-radius: var(--radius-md);
  margin-bottom: 16px;
  font-size: 0.95rem;
}

.alert.error {
  background: #fef3f2;
  color: var(--danger);
  border: 1px solid #fda29b;
}

.alert.success {
  background: #ecfdf3;
  color: var(--success);
  border: 1px solid #a6f4c5;
}

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

th, td {
  text-align: left;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 0.92rem;
}

th {
  background: #f0f2f6;
  font-weight: 600;
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

tbody tr {
  transition: background-color 0.1s ease;
}

tbody tr:hover {
  background: var(--bg);
}

/* "Sudah dipesan" / "Belum dipesan" against an agenda item.
   Shared, because the planner and the customer's landing page both show
   it and must not describe the same state two different ways - the words
   and the tone come from services/itinerary/coverage.js. */
.coverage-badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.coverage-badge.ok { background: #ecfdf3; color: var(--success); }
.coverage-badge.warn { background: #fff8e6; color: #b45309; }
/* Deliberately the loudest of the three: an unbooked meeting tomorrow is
   the one thing on this page the customer has to act on. */
.coverage-badge.open { background: #fef2f2; color: #b42318; }

/* A table cannot shrink below the width its columns need, so on a phone a
   wide one stops being 100% of its card and starts being 100% of what it
   wants - dragging the whole page sideways with it. Wrapping one in this
   keeps the scrolling inside the table's own box, where it belongs. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* For a table the customer ACTS on rather than scans - their own orders,
   with a Pay button in the last column - scrolling sideways is the wrong
   answer: the amount and the button are the two things they came for, and
   both sit off the right-hand edge. Below tablet width each row becomes
   its own block instead, labelled from the column heading it lost.
   Labels come from data-label on each cell; a cell without one (the
   "No bookings yet." row that spans the table) is left alone. */
@media (max-width: 719px) {
  .stacked-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .stacked-table,
  .stacked-table tbody,
  .stacked-table tr,
  .stacked-table td {
    display: block;
    width: 100%;
  }

  .stacked-table tr {
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
  }

  .stacked-table tr:last-child {
    border-bottom: none;
  }

  .stacked-table tr:hover {
    background: transparent;
  }

  .stacked-table td[data-label] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 5px 14px;
    border-bottom: none;
    text-align: right;
  }

  .stacked-table td[data-label]::before {
    content: attr(data-label);
    flex: none;
    color: var(--muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-align: left;
  }

  /* An order with nothing to do about it right now leaves the Actions
     cell empty; a lone "ACTIONS" label with a blank beside it reads like
     something failed to load. */
  .stacked-table td[data-label]:empty {
    display: none;
  }

  .stacked-table td:not([data-label]) {
    border-bottom: none;
  }

  /* A cell that only exists to label the one beside it across a desktop
     row - "Total" spanning three columns. Stacked, the value below it
     carries its own label, so the spanning cell would just say "Total"
     twice. */
  .stacked-table td.stack-hide {
    display: none;
  }
}

tbody tr:last-child td {
  border-bottom: none;
}

.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: capitalize;
}

.badge.waiting_confirmation { background: #fff4e5; color: #b54708; }
.badge.accepted { background: #eff8ff; color: #175cd3; }
.badge.assigned { background: #f4f3ff; color: #5925dc; }
.badge.en_route { background: #eefdf7; color: #067a5f; }
.badge.arrived { background: #ecfdf3; color: #067647; }
.badge.in_progress { background: #f0f9ff; color: #026aa2; }
.badge.completed { background: #ecfdf3; color: #12805c; }
.badge.cancelled { background: #fef3f2; color: #d92d20; }

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 18px;
  border-top: 3px solid var(--brand);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.stat-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.stat-card .label {
  color: var(--muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
}

.stat-card .value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--brand-dark);
}

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

/* ---- Photo + copy split (landing page "story" sections) ---- */

.photo-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
  margin: 0 0 24px;
}

.photo-split.reverse .photo-split-media {
  order: 2;
}

.photo-split-media img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.photo-split-copy .eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 10px;
}

.photo-split-copy h2 {
  font-size: 1.7rem;
  margin: 0 0 14px;
}

.photo-split-copy p {
  color: var(--muted);
  line-height: 1.65;
  margin: 0 0 20px;
}

.photo-split-copy ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 12px;
}

.photo-split-copy ul li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.95rem;
}

.photo-split-copy ul svg {
  width: 20px;
  height: 20px;
  color: var(--brand);
  flex-shrink: 0;
}

@media (max-width: 760px) {
  .photo-split {
    grid-template-columns: 1fr;
  }
  .photo-split.reverse .photo-split-media {
    order: 0;
  }
}

/* ---- Poster gallery (one branded image per service) ---- */

.poster-gallery {
  display: grid;
  gap: 20px;
  margin-bottom: 24px;
}

.poster-gallery img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

/* ---- Landing page sections ---- */

.section-head {
  text-align: center;
  max-width: 560px;
  margin: 0 auto 36px;
}

.section-head .eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 10px;
}

.section-head h2 {
  font-size: 1.9rem;
  margin: 0 0 10px;
}

.section-head p {
  color: var(--muted);
  margin: 0;
  line-height: 1.6;
}

.step-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 24px;
  position: relative;
}

.step-card {
  text-align: center;
  padding: 8px 12px;
}

.step-card .step-num {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--brand-dark);
  color: #fff;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 16px;
}

.step-card h3 {
  font-size: 1.02rem;
  margin: 0 0 8px;
}

.step-card p {
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.55;
  margin: 0;
}

.cta-banner {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 60px 24px;
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
  color: #fff;
  box-shadow: var(--shadow-lg);
}

.cta-banner h2 {
  margin: 0 0 12px;
  font-size: 1.7rem;
}

.cta-banner p {
  color: rgba(255, 255, 255, 0.85);
  max-width: 520px;
  margin: 0 auto 24px;
  line-height: 1.6;
}

.cta-banner .btn {
  background: #fff;
  color: var(--brand-dark);
}

.cta-banner .btn:hover {
  background: #eafffa;
}

.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;
}

.site-footer {
  padding: 48px 24px 32px;
  color: var(--muted);
  font-size: 0.85rem;
  border-top: 1px solid var(--border);
}

.site-footer .footer-top {
  max-width: 1120px;
  margin: 0 auto 32px;
}

.site-footer .footer-about {
  max-width: 640px;
  line-height: 1.6;
}

.site-footer .footer-columns {
  max-width: 1120px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}

.site-footer .footer-col {
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

.site-footer .footer-col h3 {
  margin: 0 0 12px;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--brand-dark);
}

.site-footer .footer-col-standalone h3 {
  margin: 0;
}

.site-footer .footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.site-footer .footer-col-standalone ul {
  gap: 14px;
}

.site-footer .footer-col a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s ease;
}

.site-footer .footer-col-standalone a {
  color: var(--brand-dark);
  font-weight: 700;
}

.site-footer .footer-col a:hover {
  color: var(--brand);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.site-footer .footer-bottom {
  max-width: 1120px;
  margin: 32px auto 0;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  text-align: center;
}

.site-footer .footer-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 700;
  color: var(--brand-dark);
  margin-bottom: 8px;
}

.site-footer .footer-brand img {
  height: 22px;
  width: auto;
}

@media (min-width: 720px) {
  .site-footer .footer-columns {
    grid-template-columns: repeat(3, 1fr);
    gap: 40px;
  }

  .site-footer .footer-col {
    padding: 0;
    border-bottom: 0;
  }
}

/* Scroll-reveal: elements start faded/lowered, JS toggles .visible via
   IntersectionObserver as each one enters the viewport. Falls back to
   fully visible with no observer support/JS disabled (no [hidden] state,
   just no animation). */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.reveal.visible {
  opacity: 1;
  transform: none;
}

/* ---------------------------------------------------------------------
   Agreement checkboxes on the signup forms.

   Deliberately not small print. The whole point of replacing the old
   one-line notice was that a person should be able to see what they are
   agreeing to without hunting for it, so these sit at normal reading
   size with the document titles as real links.
   --------------------------------------------------------------------- */
.agree-box { margin: 18px 0 16px; display: grid; gap: 10px; }

.agree-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  align-items: start;
  font-size: 0.87rem;
  line-height: 1.55;
  color: var(--text);
  cursor: pointer;
}

.agree-row input[type="checkbox"] {
  /* Aligns the box with the first line of text rather than the middle of
     a wrapped paragraph. */
  margin-top: 3px;
  width: 17px;
  height: 17px;
  flex: none;
  accent-color: var(--brand);
  cursor: pointer;
}

.agree-row a { color: var(--brand-dark); font-weight: 600; text-decoration: underline; }
.agree-row a:hover { color: var(--brand); }

/* The version is part of what is being agreed to, so it is shown - but
   it is not what the reader needs to weigh, so it is quieter. */

/* ==========================================================================
   The member card
   ==========================================================================
   Lives here rather than inside app.html because the same card is shown
   on the app home screen and on the account page in a browser - one
   definition, so the two cannot drift into different cards.

   Four materials, one structure. The tier is carried by the face's
   surface and its ink, never by the layout: a Silver card and a Black
   card are the same object in different metal, which is what makes them
   read as one family rather than four unrelated designs. */

.mcard {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  max-width: 420px;
}

/* The face keeps a bank card's proportions (85.6 x 54mm). People know
   what that shape means without being told, and it is the shape the
   printed card will be. */
.mcard__face {
  position: relative;
  aspect-ratio: 1.586;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  color: #fff;
}

/* A sheen across the face, angled so it catches the top-left corner the
   way light falls on a real card held at an angle. Each tier tints it. */
.mcard__face::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(110% 70% at 88% -15%, rgba(255, 255, 255, 0.22), transparent 62%),
    linear-gradient(118deg, rgba(255, 255, 255, 0.14) 0%, transparent 38%);
  pointer-events: none;
}

.mcard__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  position: relative;
  z-index: 1;
}

.mcard__brand {
  font-family: "Poppins", "Inter", -apple-system, sans-serif;
  font-weight: 800;
  font-size: 17px;
  letter-spacing: -0.01em;
}
/* The wordmark's two halves, per the brand board. On a card face the
   "UP" keeps the bright teal on every tier except Corporate, whose own
   ground is already that colour. */
.mcard__brand span { color: var(--brand-bright); }

.mcard__tier {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid currentColor;
  white-space: nowrap;
  opacity: 0.85;
}

/* The contact plate. Drawn, not an image, so it stays crisp at any size
   and costs no request. */
.mcard__chip {
  position: relative;
  z-index: 1;
  margin: 16px 0 auto;
  width: 34px;
  height: 26px;
  border-radius: 5px;
  background:
    linear-gradient(135deg, #e8d9a8 0%, #c8ab63 45%, #f0e4bd 55%, #b8974f 100%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
}
.mcard__chip::before,
.mcard__chip::after {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  height: 1px;
  background: rgba(0, 0, 0, 0.22);
}
.mcard__chip::before { top: 9px; }
.mcard__chip::after { top: 16px; }

.mcard__holder {
  position: relative;
  z-index: 1;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  /* One line. A long name that wraps turns a card into a paragraph. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mcard__foot {
  position: relative;
  z-index: 1;
  margin-top: 10px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}

/* Monospaced and spaced out, like the order code on the journey document
   - it is a number people read aloud over a counter or a phone. */
.mcard__code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.1em;
}

.mcard__valid { text-align: right; line-height: 1.25; }
.mcard__valid i {
  display: block;
  font-style: normal;
  font-size: 8px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.6;
}
.mcard__valid b { font-size: 12.5px; font-weight: 700; letter-spacing: 0.04em; }

/* ---- the four materials ---- */

/* Silver: brushed steel. Dark ink, because light ink on light metal is
   the one combination that fails in sunlight at a kerbside. */
.mcard--silver .mcard__face {
  background: linear-gradient(145deg, #f2f4f7 0%, #c9ced8 42%, #eef1f5 58%, #aeb6c2 100%);
  color: #1c2433;
}
.mcard--silver .mcard__brand { color: #0d182a; }
.mcard--silver .mcard__brand span { color: #0a8a78; }
.mcard--silver .mcard__tier { opacity: 0.72; }

/* Gold: champagne rather than yellow. Also dark ink. */
.mcard--gold .mcard__face {
  background: linear-gradient(145deg, #f7e6bd 0%, #d9b76a 44%, #f6e7c0 58%, #c39c4e 100%);
  color: #2a2110;
}
.mcard--gold .mcard__brand { color: #2a2110; }
.mcard--gold .mcard__brand span { color: #0a6f60; }
.mcard--gold .mcard__tier { opacity: 0.75; }

/* Black Elite: near-black with a faint warm graphite grain. The tier
   marks and the code go champagne, which is the only place on any card
   where the accent is not the brand teal - it is what "elite" reads as
   without writing the word twice. */
.mcard--black .mcard__face {
  background:
    radial-gradient(120% 100% at 15% 0%, #2b2f38 0%, transparent 55%),
    linear-gradient(150deg, #14171d 0%, #05070a 60%, #16191f 100%);
  color: #f4f1ea;
}
.mcard--black .mcard__brand span { color: #e6cd94; }
.mcard--black .mcard__tier { color: #e6cd94; opacity: 1; }
.mcard--black .mcard__code { color: #e6cd94; }

/* Corporate: SAFEUP's own navy running into brand teal. It is the
   company's card, so it wears the company's colours. */
.mcard--corporate .mcard__face {
  background:
    radial-gradient(120% 90% at 92% -10%, rgba(0, 224, 181, 0.42), transparent 58%),
    linear-gradient(152deg, #10314a 0%, var(--brand-dark) 55%, #06202f 100%);
  color: #eaf6f4;
}
.mcard--corporate .mcard__tier { color: var(--brand-bright); opacity: 1; }
.mcard--corporate .mcard__code { color: var(--brand-bright); }

/* ---- the tear line, borrowed from the journey document ---- */

/* The journey document punches two notches out of the card's sides here.
   This card cannot: it clips its own overflow so the face's corners stay
   rounded, and a notch filled with --bg would in any case be invisible
   against a white card - the two colours are a hair apart. So the tear is
   the dashed rule alone, with the strip below it on --bg so the fold
   reads as a fold rather than as a stray line. */
.mcard__tear {
  height: 0;
  margin: 0 20px;
  border-top: 1.5px dashed var(--border);
}

/* ---- the quota strip ---- */

.mcard__quota {
  padding: 16px 20px 18px;
  display: grid;
  gap: 13px;
  /* A shade off white, so the strip reads as the stub below the fold
     rather than as more of the same card. */
  background: linear-gradient(180deg, #fbfcfe 0%, var(--surface) 40%);
}

.mcard__quotahead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}

.mq__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.mq__lab { font-size: 13px; font-weight: 600; }
.mq__n b { font-size: 15px; font-weight: 800; }
.mq__n i { font-style: normal; font-size: 12px; color: var(--muted); }

.mq__bar {
  margin-top: 6px;
  height: 5px;
  border-radius: 999px;
  background: #eceff4;
  overflow: hidden;
}
.mq__bar span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--brand), var(--brand-bright));
}

/* The two sides of a split quota, named. A member with none of the
   expensive side left needs to see that before they arrive at an
   international terminal expecting to be waved through. */
.mq__split {
  display: block;
  margin-top: 5px;
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.01em;
}

/* Spent, not broken: the row stays legible and simply stops claiming to
   be available. */
.mq--spent .mq__lab,
.mq--spent .mq__n b { color: var(--muted); }
.mq--spent .mq__bar span { background: #cfd5de; }

.mcard__note {
  margin: 2px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--muted);
}

/* What a quota is spent on, named under its own row. A member reading
   "Airport Assistance 8x" should not have to guess whether Porter counts
   - guessing wrong means arriving at a terminal expecting to be waved
   through. Quieter than the label, because it is a reminder of what they
   already bought rather than the number they came to check. */
.mq__covers {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--muted);
}
