/* ==========================================================================
   Hire.Limo design system
   Layered over Bootstrap: Bootstrap keeps the grid + the inherited djangobase
   pages (login, account, pricing) working; everything visual is ours.

   Dark-and-gold throughout: the page canvas itself is ink, not paper. Paper/
   paper-2/paper-3 are kept as tokens (still used by a few self-contained
   light elements — badges, the gold quote-card's white inputs) but they are
   no longer the default surface anywhere in the main content flow.
   ========================================================================== */

:root {
  --ink:        #0d1117;   /* near-black, the dominant surface */
  --ink-2:      #161b26;
  --ink-3:      #1f2532;
  --line:       #2a3140;

  --paper:      #ffffff;
  --paper-2:    #f6f7f9;
  --paper-3:    #eceef2;

  --brass:      #c8a457;   /* the single accent. Used sparingly. */
  --brass-dim:  #a8873f;
  --brass-glow: rgba(200, 164, 87, 0.16);

  --text:       #10141c;
  --text-mute:  #5b6472;
  --text-on-ink:#e8eaf0;
  --text-on-ink-mute: #98a1b3;

  --ok:         #1f8a5a;
  --warn:       #b4711c;
  --err:        #c0392b;

  --radius:     10px;
  --radius-lg:  16px;
  --shadow:     0 1px 2px rgba(13,17,23,.06), 0 8px 24px rgba(13,17,23,.08);
  --shadow-lg:  0 2px 4px rgba(13,17,23,.08), 0 24px 48px rgba(13,17,23,.14);

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --font-display: "Georgia", "Times New Roman", serif;

  /* Spacing scale — sections lean on this rather than one-off pixel values,
     so "more whitespace" is a token change here, not a hunt through every
     template. */
  --space-1: 8px;
  --space-2: 14px;
  --space-3: 22px;
  --space-4: 36px;
  --space-5: 56px;
  --space-6: 84px;
  --space-7: 112px;
  --space-8: 144px;
}

* { box-sizing: border-box; }

body {
  font-family: var(--font);
  color: var(--text-on-ink);
  background: var(--ink);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main { flex: 1 0 auto; }

h1, h2, h3, h4 { font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }
h1 { font-size: clamp(2rem, 4.2vw, 3.25rem); }
h2 { font-size: clamp(1.5rem, 2.6vw, 2.1rem); }
h3 { font-size: 1.2rem; }

p { line-height: 1.65; }
a { color: var(--brass); text-underline-offset: 3px; }
a:hover { color: var(--paper); }

.wrap { width: 100%; max-width: 1140px; margin: 0 auto; padding: 0 20px; }

/* Two narrow containers, and picking the wrong one is what made the left edge
   jump ~180px mid-scroll on /partners/, /safety/, a city page and the homepage
   (fixed 2026-09-04):

   .wrap-narrow  — a CENTERED narrow column. For a page that is a single
                   reading column all the way down (about, terms, privacy).
   .wrap-column  — a narrow column pinned to `.wrap`'s LEFT EDGE. For a narrow
                   block (an FAQ, a closing note) inside a page whose other
                   sections are full `.wrap` width. Centering it there reads as
                   a different page spliced in.

   Rule: one left edge per page. Never alternate .wrap and .wrap-narrow between
   adjacent sections. */
.wrap-narrow { max-width: 780px; }
.wrap-column { max-width: 1140px; }
.wrap-column > * { max-width: 760px; }

/* .prose carries its own 68ch cap, which inside .wrap-narrow's 740px box left
   a ~100px unbalanced right gutter and made a perfectly centered column look
   pushed off-centre. One measure governs, not two. */
.wrap-narrow > .prose, .wrap-column > .prose { max-width: none; }

.muted { color: var(--text-on-ink-mute); }
.tiny { font-size: .82rem; }
.eyebrow {
  text-transform: uppercase; letter-spacing: .14em; font-size: .72rem;
  font-weight: 700; color: var(--brass);
}

/* ---------- nav ---------------------------------------------------------- */
.hl-nav {
  background: var(--ink);
  border-bottom: 1px solid var(--line);
  padding: 14px 0;
  position: sticky; top: 0; z-index: 50;
}
.hl-nav .wrap { display: flex; align-items: center; gap: 28px; }
.hl-brand {
  font-family: var(--font-display);
  font-size: 1.35rem; font-weight: 700; letter-spacing: -0.01em;
  color: var(--paper); text-decoration: none; white-space: nowrap;
}
.hl-brand span { color: var(--brass); }
.hl-nav-links { display: flex; gap: 22px; margin-left: auto; align-items: center; }
.hl-nav-links a {
  color: var(--text-on-ink-mute); text-decoration: none; font-size: .93rem;
  font-weight: 500;
}
.hl-nav-links a:hover, .hl-nav-links a.active { color: var(--paper); }
.hl-nav-toggle {
  display: none; background: none; border: 0; color: var(--paper);
  font-size: 1.5rem; line-height: 1; margin-left: auto; cursor: pointer;
}

@media (max-width: 860px) {
  .hl-nav-toggle { display: block; }
  .hl-nav-links {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    background: var(--ink-2); flex-direction: column; align-items: stretch;
    gap: 0; padding: 8px 0; border-bottom: 1px solid var(--line);
  }
  .hl-nav-links.open { display: flex; }
  .hl-nav-links a { padding: 12px 20px; }
}

/* ---------- buttons ------------------------------------------------------
   Pill-shaped and tight. .btn-hl (gold) is the primary action everywhere;
   .btn-hl-dark is now the "light" variant for use on gold/light surfaces
   (name kept for compatibility); .btn-hl-ghost is the outline variant for
   dark surfaces, which is nearly everywhere now. */
.btn-hl, .btn-hl-ghost, .btn-hl-dark {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 600; font-size: .89rem; border-radius: 999px;
  padding: 11px 22px; border: 1px solid transparent; cursor: pointer;
  text-decoration: none; transition: background .15s, border-color .15s,
                                     transform .05s;
}
.btn-hl { background: var(--brass); color: var(--ink); }
.btn-hl:hover { background: var(--brass-dim); color: var(--ink); }
.btn-hl:active { transform: translateY(1px); }
.btn-hl-dark { background: var(--paper); color: var(--ink); }
.btn-hl-dark:hover { background: var(--paper-2); color: var(--ink); }
.btn-hl-ghost {
  background: transparent; color: var(--paper); border-color: var(--ink-3);
}
.btn-hl-ghost:hover { border-color: var(--brass); color: var(--brass); }
.btn-hl[disabled], .btn-hl-dark[disabled] { opacity: .5; cursor: not-allowed; }
.btn-block { width: 100%; }

/* ---------- hero --------------------------------------------------------- */
.hero {
  background:
    radial-gradient(900px 400px at 80% -10%, rgba(200,164,87,.10), transparent 60%),
    var(--ink);
  color: var(--text-on-ink);
  padding: 68px 0 0;
}
/* Centered independently of the quote form below it (which centers itself
   via .quote-card's own margin) so form labels don't inherit text-align.
   .eyebrow is an inline <span> elsewhere on the site (left-aligned inside
   its own block by design) — block+center is scoped to the hero only. */
.hero .eyebrow { display: block; text-align: center; }
.hero h1, .hero .lede { text-align: center; }
.hero h1 { color: var(--paper); max-width: 16ch; margin-left: auto; margin-right: auto; }
.hero .lede {
  color: var(--text-on-ink-mute); font-size: 1.12rem; max-width: 54ch;
  margin: 16px auto 0;
}
.hero-inner { display: grid; grid-template-columns: 1fr; gap: 32px; }

/* ---------- quote form -----------------------------------------------------
   Centered and capped in width, rather than stretching the full hero
   — reads as one clear "search bar" moment instead of a wide dense form.
   The card itself is solid gold now (not just an accent edge), with black
   used for every functional/contrast element on top of it — fields, the
   divider, focus states and the button all need their own treatment here
   since brass is the surface color, not a highlight, inside this card. */
.quote-card {
  background: var(--brass); color: var(--ink);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: 32px; margin: 36px auto -56px; max-width: 700px;
}
/* The primary button is scoped here because .btn-hl is used site-wide
   (gold-on-dark everywhere else) — on a gold card it has to invert to
   stay visible as the thing you click, rather than disappearing into the
   background it would otherwise match. */
.quote-card .btn-hl { background: var(--ink); color: var(--brass); padding: 12px 22px; }
.quote-card .btn-hl:hover { background: var(--ink-3); color: var(--brass); }
.quote-card .tiny.muted { color: rgba(13, 17, 23, .65); }
.quote-tabs { display: flex; justify-content: center; gap: 8px; margin-bottom: 22px; }
.quote-tab {
  flex: 0 0 auto; padding: 8px 16px; border-radius: 999px; font-weight: 600;
  font-size: .85rem; border: 1px solid var(--ink); background: var(--paper);
  color: var(--ink); cursor: pointer; transition: background .15s, color .15s, border-color .15s;
}
.quote-tab.active {
  background: var(--ink); color: var(--brass); border-color: var(--ink);
}
.field-grid {
  display: grid; grid-template-columns: repeat(12, 1fr); gap: 16px 14px;
}
/* Full-width hairline between the route fields (city/pick-up/drop-off) and
   the trip-detail fields (date/time/passengers/bags) — an actual element
   rather than a per-cell border, since a grid cell's own border-top can't
   span the whole row. Splits one long field list into "where" and
   "when/who" at a glance. */
.field-divider { grid-column: 1 / -1; border-top: 1px solid rgba(13, 17, 23, .18); margin: 2px 0 4px; }
.field { display: flex; flex-direction: column; gap: 7px; }
/* .field/.field-error are reused outside the gold quote-card too (book.html,
   pay.html, operator apply/dashboard/offer) where the surrounding surface is
   the dark page background, not gold — so the base colors below are tuned
   for THAT majority case, with the gold card overriding just its own. */
.field label {
  font-size: .76rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--text-on-ink-mute);
}
.quote-card .field label { color: var(--ink); }
/* Visible confirmation that the City dropdown was set for the visitor by
   /api/geo/, not just silently changed underneath them. Toggled via JS in
   index.html; normal-case + lighter weight so it doesn't compete with the
   bold uppercase label it sits next to. */
.city-detected {
  text-transform: none; font-weight: 500; letter-spacing: normal;
  opacity: .75;
}
.field input, .field select, .field textarea {
  width: 100%; padding: 10px 14px; border: 1px solid var(--ink);
  border-radius: 10px; font-size: .93rem; font-family: var(--font);
  background: var(--paper); color: var(--text); height: 42px;
}
/* The shared `height: 42px` above is right for an input and wrong for a
   textarea: it collapsed every multi-line field in the site to a single line,
   `rows` and all — including book.html's "anything the chauffeur should know"
   and the whole contact form's message box. Found 2026-09-04. */
.field textarea { height: auto; min-height: 108px; resize: vertical; padding-top: 12px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(13, 17, 23, .18);
}
/* Prefixed on purpose: Bootstrap also ships .col-4/.col-3/.col-6/.col-12, and
   its `width: 33.333%` resolves against our grid AREA — every field collapsed
   to a third of its column and the form looked broken. Do not rename these
   back to bare .col-*. */
.f-12 { grid-column: span 12; }
.f-6  { grid-column: span 6; }
.f-4  { grid-column: span 4; }
.f-3  { grid-column: span 3; }
@media (max-width: 760px) {
  .f-6, .f-4, .f-3 { grid-column: span 12; }
  .quote-card { margin-bottom: -40px; }
}

.field-error { color: #ff8a80; font-size: .82rem; }
.form-banner {
  background: rgba(192, 57, 43, .16); border: 1px solid rgba(192, 57, 43, .4);
  color: #ff8a80; padding: 12px 14px; border-radius: var(--radius);
  font-size: .9rem; margin-bottom: 16px;
}
/* Darker red reads better against the gold card than the light-on-dark
   default above. */
.quote-card .field-error { color: var(--err); }
.quote-card .form-banner {
  background: #fdf1f0; border: 1px solid #f2c9c4; color: var(--err);
}

/* ---------- trust strip -------------------------------------------------- */
.trust {
  padding: var(--space-7) 0 var(--space-3); background: var(--ink-2);
}
.trust-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3);
}
.trust-item h3 { font-size: 1rem; margin: 10px 0 4px; }
.trust-item p { font-size: .92rem; color: var(--text-on-ink-mute); margin: 0; }
.trust-mark { color: var(--brass); font-size: 1.4rem; }
@media (max-width: 860px) { .trust-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .trust-grid { grid-template-columns: 1fr; } }

/* ---------- sections -------------------------------------------------------
   .section sits on the plain ink canvas; .section-alt and .section-callout
   step to a slightly lighter dark shade for rhythm as you scroll, rather
   than ever dropping back to a light/paper background. */
.section { padding: var(--space-7) 0; }
.section-tight { padding: var(--space-4) 0; }
.section-alt { background: var(--ink-2); }
.section-callout { background: var(--ink-2); border-top: 2px solid var(--brass); }
.section-head { max-width: 62ch; margin-bottom: var(--space-5); }
.section-head p { color: var(--text-on-ink-mute); margin: 10px 0 0; }

/* ---------- use-case list -------------------------------------------------
   Short, honest one-paragraph cards for "who this is for" — deliberately
   plainer than .card-hl (no shadow/border chrome) so a page of these reads
   as calm text, not a wall of product tiles. */
.use-case { padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.use-case:first-child { border-top: 0; }
.use-case h3 { margin: 0 0 6px; font-size: 1.05rem; }
.use-case p { margin: 0; color: var(--text-on-ink-mute); max-width: 62ch; }

/* ---------- stat line ------------------------------------------------------
   For real, computed numbers only (never a placeholder). See dataviz/copy
   rule: no stat renders below its honesty threshold — the caller omits the
   element entirely rather than pass a hollow "0". Numbers are gold, the one
   place on a dark section that gets the full accent rather than a muted one. */
.stat-line { display: flex; gap: var(--space-5); flex-wrap: wrap; }
.stat-line .stat b {
  display: block; font-size: 2rem; font-weight: 700; color: var(--brass);
  font-family: var(--font-display);
}
.stat-line .stat span { font-size: .86rem; color: var(--text-on-ink-mute); }

/* ---------- cards -------------------------------------------------------- */
.card-grid { display: grid; gap: 18px; }
.cols-2 { grid-template-columns: repeat(2, 1fr); }
.cols-3 { grid-template-columns: repeat(3, 1fr); }
.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .cols-3, .cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .cols-2, .cols-3, .cols-4 { grid-template-columns: 1fr; } }

/* A lifted dark panel rather than transparent — on a dark section a
   borderless/backgroundless card had no definition at all. */
.card-hl {
  background: var(--ink-3); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 22px; box-shadow: none;
  transition: background-color .15s, border-color .15s;
}
.card-hl h3 { margin: 0 0 6px; }
.card-hl p { color: var(--text-on-ink-mute); font-size: .93rem; margin: 0; }
a.card-hl { text-decoration: none; color: inherit; display: block; }
a.card-hl:hover { border-color: var(--brass); }

/* ---------- vehicle / fare cards ----------------------------------------- */
.fare {
  display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: center;
  background: var(--ink-2); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 20px 22px; margin-bottom: 12px;
}
.fare.dimmed { opacity: .55; }
.fare-name { font-weight: 700; font-size: 1.08rem; margin: 0; }
.fare-models { color: var(--text-on-ink-mute); font-size: .88rem; margin: 3px 0 8px; }
.fare-specs { display: flex; gap: 16px; font-size: .85rem; color: var(--text-on-ink-mute); }
.fare-price { font-size: 1.6rem; font-weight: 700; white-space: nowrap; text-align: right; color: var(--brass); }
.fare-price small { display: block; font-size: .72rem; font-weight: 500; color: var(--text-on-ink-mute); }
.fare-cta { text-align: right; }
@media (max-width: 620px) {
  .fare { grid-template-columns: 1fr; }
  .fare-price, .fare-cta { text-align: left; }
}

/* ---------- itinerary / summary ------------------------------------------ */
.summary {
  background: var(--ink-2); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 20px;
}
.summary dl { display: grid; grid-template-columns: auto 1fr; gap: 8px 18px; margin: 0; }
.summary dt { color: var(--text-on-ink-mute); font-size: .86rem; }
.summary dd { margin: 0; font-size: .94rem; font-weight: 500; }

.breakdown { list-style: none; padding: 0; margin: 0; }
.breakdown li {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 9px 0; border-bottom: 1px dashed var(--line); font-size: .92rem;
}
.breakdown li:last-child { border-bottom: 0; }
.breakdown .total { font-weight: 700; font-size: 1.15rem; padding-top: 14px; color: var(--brass); }

/* ---------- tables ------------------------------------------------------- */
.table-hl { width: 100%; border-collapse: collapse; font-size: .94rem; }
.table-hl th, .table-hl td {
  text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--line);
}
.table-hl th { font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-on-ink-mute); }
.table-wrap { overflow-x: auto; }

/* ---------- badges / status -----------------------------------------------
   Self-contained pastel chips — legible regardless of page background, so
   left as-is rather than dark-themed. */
.badge-hl {
  display: inline-block; padding: 4px 10px; border-radius: 999px;
  font-size: .74rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em;
}
.badge-ok      { background: #e4f4ec; color: var(--ok); }
.badge-wait    { background: #fdf1e0; color: var(--warn); }
.badge-err     { background: #fdeceb; color: var(--err); }
.badge-neutral { background: var(--paper-3); color: var(--text-mute); }

/* ---------- prose (city/airport copy) ------------------------------------ */
.prose { max-width: 68ch; }
.prose p { margin: 0 0 18px; font-size: 1.02rem; }
.prose h2 { margin: 34px 0 12px; }

/* ---------- faq ---------------------------------------------------------- */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); padding: 16px 0; }
.faq summary {
  cursor: pointer; font-weight: 600; font-size: 1rem; list-style: none;
  display: flex; justify-content: space-between; gap: 16px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '+'; color: var(--brass); font-weight: 700; }
.faq details[open] summary::after { content: '–'; }
.faq p { color: var(--text-on-ink-mute); margin: 12px 0 0; }

/* ---------- footer ------------------------------------------------------- */
.hl-footer {
  background: var(--ink); color: var(--text-on-ink-mute);
  padding: 48px 0 28px; margin-top: 64px; font-size: .9rem;
}
.hl-footer a { color: var(--text-on-ink-mute); text-decoration: none; }
.hl-footer a:hover { color: var(--brass); }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 28px; }
.footer-grid h4 {
  color: var(--paper); font-size: .8rem; text-transform: uppercase;
  letter-spacing: .1em; margin: 0 0 12px;
}
.footer-grid ul { list-style: none; padding: 0; margin: 0; }
.footer-grid li { margin-bottom: 8px; }
.footer-bottom {
  border-top: 1px solid var(--line); margin-top: 32px; padding-top: 20px;
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
@media (max-width: 760px) { .footer-grid { grid-template-columns: 1fr 1fr; } }

/* ---------- misc --------------------------------------------------------- */
.notice {
  border-left: 3px solid var(--brass); background: var(--ink-2);
  padding: 14px 18px; border-radius: 0 var(--radius) var(--radius) 0;
  font-size: .93rem;
}
.msg-list { list-style: none; padding: 0; margin: 0 0 20px; }
.msg-list li {
  padding: 12px 16px; border-radius: var(--radius); margin-bottom: 8px;
  font-size: .93rem;
}
.msg-success { background: #e4f4ec; color: var(--ok); }
.msg-error   { background: #fdeceb; color: var(--err); }
.msg-info    { background: var(--ink-2); color: var(--text-on-ink-mute); }
.stack > * + * { margin-top: 14px; }
.row-between { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; }

/* ==========================================================================
   Hero video
   The poster is the LCP element and is painted by CSS on the section itself,
   so it shows whether or not a <video> is ever attached. `.has-video` is added
   by JS only once a source has actually been attached — without it the <video>
   elements stay hidden, so a phone/reduced-motion/save-data session never
   shows an empty black box.
   ========================================================================== */
.hero-video {
  position: relative;
  /* Deliberately NOT overflow:hidden — the quote card hangs 56px below the
     hero by design, and clipping it would slice the submit button in half.
     The video and scrim are both inset:0 so neither escapes anyway. */
  background-color: var(--ink);
  background-image: var(--hero-poster);
  background-size: cover;
  background-position: center 60%;
}
.hero-video__media {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
  opacity: 0;
  transition: opacity .6s ease;
}
.hero-video.has-video .hero-video__media { opacity: 1; }
/* The sharp tier sits on top of the small one and fades in once it can play
   through, so the upgrade is never a visible cut or a stall. */
.hero-video__media--hi { z-index: 1; opacity: 0; }
.hero-video.has-video .hero-video__media--hi { opacity: 0; }
.hero-video.has-video .hero-video__media--hi.is-ready { opacity: 1; }

/* Scrim. Two layers: a vertical gradient so the nav edge and the quote card
   both have something to sit on, and a left-weighted wash so the headline
   column keeps contrast whatever the traffic is doing behind it. */
.hero-video::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(13,17,23,.72) 0%, rgba(13,17,23,.30) 28%,
                                rgba(13,17,23,.26) 55%, rgba(13,17,23,.78) 100%),
    linear-gradient(to right, rgba(13,17,23,.72) 0%, rgba(13,17,23,.22) 58%,
                              rgba(13,17,23,.04) 100%);
}
.hero-video > .wrap { position: relative; z-index: 3; }

/* Text sits on moving footage now, so it needs its own contrast floor. */
.hero-video h1 {
  text-shadow: 0 2px 12px rgba(13,17,23,.8), 0 4px 34px rgba(13,17,23,.6);
}
.hero-video .lede {
  color: #cdd5e2;
  text-shadow: 0 1px 9px rgba(13,17,23,.88), 0 2px 22px rgba(13,17,23,.6);
}
.hero-video .eyebrow { color: var(--brass); }

@media (max-width: 760px) {
  /* Portrait crop, and a poster framed the same way, so the hero reads as a
     city at night rather than a smear of tarmac. */
  .hero-video { background-image: var(--hero-poster-portrait); }
}

@media (prefers-reduced-motion: reduce) {
  /* Belt and braces: the JS already returns early, but if a video is somehow
     attached it must not animate. */
  .hero-video__media { display: none; }
}

/* ==========================================================================
   Utility / auth pages
   The single-purpose pages — log in, sign up, verify, contact, refund, the
   error pages — arrived from djangobase as raw Bootstrap: a white `.card
   shadow-sm` and a blue `.btn-primary` on this site's ink-and-brass canvas,
   flush against the nav because `.container` carries no vertical padding.
   They are converted to the components below (2026-09-04).

   The split is deliberate and is the site's layout rule:
     - a CONTENT page (about, pricing, a city, an operator application) is
       left-aligned inside `.wrap`, because it is read top-to-bottom;
     - a SINGLE-PURPOSE page — one form, one message, one decision — is
       centered in a `.panel`, because there is nothing to scan, only a thing
       to do. Centering a long page of prose would be worse, not more
       consistent.
   ========================================================================== */

/* Centered head for a single-purpose page. Capped in ch so the subtitle wraps
   into a readable block rather than one long line on a wide monitor. */
.page-head { text-align: center; max-width: 54ch; margin: 0 auto var(--space-4); }
.page-head h1 { font-size: clamp(1.6rem, 3vw, 2.2rem); margin: 10px 0 0; }
.page-head p { color: var(--text-on-ink-mute); margin: 12px 0 0; }
/* .eyebrow is an inline span by default (left-aligned inside its own block
   elsewhere); inside a centered head it has to become a block to center. */
.page-head .eyebrow { display: block; }

/* The dark equivalent of Bootstrap's white card. Same surface as .card-hl but
   sized for a form rather than a grid tile. */
.panel {
  background: var(--ink-2); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 28px;
  margin-left: auto; margin-right: auto;
}
.panel-narrow { max-width: 430px; }
.panel-wide   { max-width: 620px; }
.panel > h2 { font-size: 1.05rem; margin: 0 0 16px; }
/* The "Don't have an account? Sign up" rail under a form. Replaces a bare
   <hr> + .text-center, which on a dark panel drew a hard white line. */
.panel-foot {
  border-top: 1px solid var(--line); margin-top: 24px; padding-top: 18px;
  text-align: center; font-size: .92rem; color: var(--text-on-ink-mute);
}
.panel-foot:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
/* Centered action row — one or two buttons under a message. Wraps rather than
   overflowing on a phone. */
.panel-actions {
  display: flex; justify-content: center; gap: 12px; flex-wrap: wrap;
  margin-top: var(--space-3);
}

/* Destructive actions (cancel subscription, delete account). Outline rather
   than solid red: it must read as available but never as the primary action
   on the page. */
.btn-hl-danger {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 600; font-size: .89rem; border-radius: 999px;
  padding: 11px 22px; cursor: pointer; text-decoration: none;
  background: transparent; color: #ff8a80; border: 1px solid rgba(192,57,43,.55);
  transition: background .15s, border-color .15s, color .15s;
}
.btn-hl-danger:hover { background: rgba(192,57,43,.14); border-color: var(--err); color: #ff8a80; }
.btn-hl-sm { padding: 8px 16px; font-size: .82rem; }

/* Success counterpart to .form-banner (which is the error case). */
.form-banner-ok {
  background: rgba(31, 138, 90, .16); border: 1px solid rgba(31, 138, 90, .45);
  color: #7fd3a8; padding: 12px 14px; border-radius: var(--radius);
  font-size: .9rem; margin-bottom: 16px;
}

/* ---------- error pages ---------------------------------------------------
   The status code is set in the display serif and dimmed: on a 404 the useful
   content is the way out, not the number. /airport-transfers/ served a bare
   `<h1>404</h1>` from the main nav of every page until 2026-09-04. */
/* Selector carries .page-head deliberately: `.page-head p` (0,1,1) outranks a
   bare `.error-code` (0,1,0), so the status code rendered in the muted body
   grey instead of brass. */
.page-head .error-code, .error-code {
  font-family: var(--font-display); font-size: clamp(4rem, 12vw, 7rem);
  line-height: 1; color: var(--brass); opacity: .85; margin: 0;
  letter-spacing: -0.03em;
}
.error-links {
  display: flex; justify-content: center; gap: 10px 22px; flex-wrap: wrap;
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: 1px solid var(--line); font-size: .92rem;
}

/* ---------- key/value rail (account page) --------------------------------- */
.kv { display: grid; grid-template-columns: auto 1fr; gap: 10px 18px; margin: 0; }
.kv dt { color: var(--text-on-ink-mute); font-size: .86rem; }
.kv dd { margin: 0; font-size: .94rem; font-weight: 500; word-break: break-all; }

/* Bootstrap's modal is still used for the cancel-subscription confirm; give it
   this site's surface instead of the default white sheet. */
.modal-content.panel { border: 1px solid var(--line); }
.modal-content.panel .modal-header,
.modal-content.panel .modal-footer { border-color: var(--line); }
.modal-content.panel .btn-close { filter: invert(1) grayscale(1); opacity: .7; }

/* The captcha widget renders its own <img> plus a hidden and a text input.
   Inside a .field (flex column) the image would otherwise stretch to the
   column width and go blurry. */
.captcha-field img.captcha {
  border-radius: var(--radius); background: var(--paper);
  align-self: flex-start; max-width: 200px;
}

/* ---------- payment status glyphs -----------------------------------------
   templates/svgs/payment-*.html are 16px octicons whose <path> carries no
   fill, so they inherit the default black and were invisible on this canvas —
   the entire Status column of the billing history rendered blank. They are
   also the only consumer of `.payment-status`, which had no rule anywhere:
   static/css/styles.css (djangobase's) still defines .pricing-card and friends
   but is not loaded by base.html at all. */
.payment-status svg, .payment-status svg path { fill: currentColor; }
.payment-status svg { width: 18px; height: 18px; vertical-align: middle; }
.payment-status.success { color: #7fd3a8; }
.payment-status.failed  { color: #ff8a80; }
.payment-status.pending { color: var(--brass); }

/* Same glyph, page-scale, for a confirmation screen. */
.success-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 58px; height: 58px; border-radius: 50%;
  border: 2px solid var(--brass); color: var(--brass);
  margin: 0 auto var(--space-1);
}
.success-mark svg, .success-mark svg path { fill: currentColor; }
.success-mark svg { width: 26px; height: 26px; }

/* ==========================================================================
   Feedback widget — palette override only
   shared/feedback_widget.html is a FLEET-SHARED template kept close to
   byte-identical across ~100 sites, and it draws itself on Bootstrap's own
   custom properties (--bs-body-bg, --bs-primary) so that each site's palette
   drives it. This site never sets those, so it fell back to the literals in
   that file — a white pill and a blue button, floating over an ink-and-brass
   page on every single view.

   The fix belongs HERE, not in the shared template: overriding the tokens from
   the host stylesheet is exactly the extension point that file documents.
   Selectors are body-scoped because the widget's <style> block is inline in
   <body> and therefore later in the document than this file — equal
   specificity would lose.
   ========================================================================== */
body .fb-pill {
  background: var(--ink-2); color: var(--text-on-ink-mute);
  border-color: var(--line); box-shadow: 0 6px 20px rgba(0, 0, 0, .35);
}
body .fb-pill:hover { color: var(--brass); border-color: var(--brass); }
body .fb-pill:focus-visible { outline-color: var(--brass); }

#siteFeedbackWidget .modal-content {
  background: var(--ink-2); color: var(--text-on-ink);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
}
#siteFeedbackWidget .modal-header { border-bottom-color: var(--line); }
#siteFeedbackWidget .btn-close { filter: invert(1) grayscale(1); opacity: .7; }
#siteFeedbackWidget .text-muted { color: var(--text-on-ink-mute) !important; }
#siteFeedbackWidget .form-control {
  background: var(--paper); color: var(--text);
  border: 1px solid var(--ink); border-radius: 10px;
}
#siteFeedbackWidget .form-control:focus {
  border-color: var(--brass); box-shadow: 0 0 0 3px var(--brass-glow);
}
/* The submit keeps Bootstrap's .btn sizing (the widget's JS toggles nothing
   else on it) and takes this site's colours. */
#siteFeedbackWidget #siteFbSubmit {
  background: var(--brass); color: var(--ink); border-color: var(--brass);
  border-radius: 999px;
}
#siteFeedbackWidget #siteFbSubmit:hover { background: var(--brass-dim); color: var(--ink); }

/* Centred call-to-action row for a `.hero`.
   `.hero h1`, `.hero .lede` and `.hero .eyebrow` are centred by the rules
   above, but a bare `<p><a class="btn-hl">` under them is not — on /partners/
   that put the only button on the page hard against the left margin below a
   centred headline, which is what "buttons not centred" looked like. */
.hero-actions {
  display: flex; justify-content: center; gap: 12px; flex-wrap: wrap;
  margin-top: 28px;
}

/* A stat line that IS the content, rather than a footnote under a paragraph.
   /safety/ rendered one lonely figure inside a full `.section` (112px of
   padding top and bottom) and it read as a ~300px hole in the page. */
.stat-line-inline { margin-top: var(--space-4); gap: var(--space-5); }
