/* Buraq public storefront.

   Built on static/buraq/css/tokens.css — the palette, type scale, spacing
   rhythm and motion values all live there and are shared with the staff
   dashboard. This file defines only the components a customer-facing
   booking site needs, and never redefines a token.

   ── Layout model ───────────────────────────────────────────────────────
   Two columns from 960px up: a sticky filter rail and the departures list.
   Below that it's one column, filters collapsed behind a summary/details
   disclosure so a phone opens straight onto departures rather than onto a
   wall of controls it has to scroll past.

   ── What makes this read as a timetable ────────────────────────────────
   Departures are RULED ROWS inside one sheet, not a stack of cards. That is
   the single biggest structural decision here: fifteen floating cards with
   their own borders and shadows is what every booking site looks like, and
   it turns a scannable column of times into fifteen separate things to
   read. One sheet with hairlines between rows lets the eye run down the
   departure column the way it does on a real board.

   Cards do exist — but only where something genuinely is a discrete object
   (the checkout summary, a ticket, a payment method). */

/* ---- shell ----------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--rule);
}
.site-header__inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: var(--s-3) var(--s-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}
.site-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--t-md);
  font-variation-settings: "opsz" 24;
  letter-spacing: -0.015em;
}
.site-brand:hover { text-decoration: none; }
.site-brand__mark {
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
  background: var(--brand);
  color: #fff;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.site-brand__mark .ico { width: 18px; height: 18px; }
/* An uploaded logo, uncropped at its own aspect ratio. Height sets the size;
   the width cap keeps a very long wordmark from crowding the header links. */
.site-brand__logo {
  display: block;
  height: 56px;
  width: auto;
  max-width: 260px;
  object-fit: contain;
  object-position: left center;
  flex-shrink: 0;
}
.site-brand--logo .site-brand__name { display: none; }
.site-brand--mark-only .site-brand__name { display: inline; }
/* Logos are drawn for light paper — dark lettering vanishes on the dark
   theme's header. A company's dark-ground variant (Tenant.logo_dark) is
   swapped in by theme, so the site's own theme toggle works too, not only
   the OS setting; a logo without one sits on a white plate instead, which
   keeps it legible without recolouring anyone's brand. */
.site-brand__logo--dark { display: none; }
:root[data-theme="dark"] .site-brand--has-dark .site-brand__logo--light { display: none; }
:root[data-theme="dark"] .site-brand--has-dark .site-brand__logo--dark { display: block; }
:root[data-theme="dark"] .site-brand:not(.site-brand--has-dark) .site-brand__logo {
  background: #fff;
  border-radius: var(--r-md);
  padding: 4px 8px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .site-brand--has-dark .site-brand__logo--light { display: none; }
  :root:not([data-theme="light"]) .site-brand--has-dark .site-brand__logo--dark { display: block; }
  :root:not([data-theme="light"]) .site-brand:not(.site-brand--has-dark) .site-brand__logo {
    background: #fff;
    border-radius: var(--r-md);
    padding: 4px 8px;
  }
}
@media (max-width: 720px) {
  .site-brand__logo { height: 40px; max-width: 180px; }
}

.site-header__links { display: flex; align-items: center; gap: var(--s-5); }
.site-header__links .u-label { white-space: nowrap; }
/* Narrow screens: passengers' "Manage booking" keeps its place; staff find
   their sign-in in the footer, where it also is on every screen. */
.site-header__manage { display: inline-flex; align-items: center; gap: 6px; }
.site-header__account { display: inline-flex; align-items: center; gap: 6px; }
/* Below tablet width the account link is its icon alone (name kept for
   screen readers and the tooltip), so the header never overflows a phone. */
@media (max-width: 720px) {
  .site-header__account-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* Call to book: a filled pill in the company's accent — the number where
   there's room, the phone glyph alone where there isn't. */
.site-header__call {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: var(--brand-2);
  color: var(--brand-2-ink);
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
}
.site-header__call:hover { text-decoration: none; filter: brightness(1.08); }
@media (max-width: 1100px) {
  .site-header__call-text { display: none; }
  .site-header__call { width: 34px; padding: 0; justify-content: center; }
}
@media (max-width: 560px) {
  .site-header__links { gap: var(--s-3); }
  .site-header__staff { display: none; }
}
/* The smallest phones: the ticket icon alone (its name stays for screen
   readers and as the tooltip). */
@media (max-width: 440px) {
  .site-header__manage-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .site-header__manage { padding: 8px; margin: -8px; }
  .site-header__account-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .site-header__account { padding: 8px; margin: -8px; }
}
/* ---- theme toggle ---------------------------------------------------- */
/* Hidden until the pre-paint script in base.html marks the document as
   scripted. A control that silently does nothing is worse than an absent
   one, and with scripting off tokens.css's `color-scheme: light dark`
   already follows the OS, so nothing is actually lost. */
.theme-toggle { display: none; }
.js .theme-toggle {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  padding: 0;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.theme-toggle:hover { color: var(--brand-2); border-color: var(--brand-2); }
/* The script stamps the RESOLVED theme on the button, so the icon shown is
   the scheme you are in. Doing the swap off that one attribute keeps it in
   step with the OS-preference case, which no CSS selector can see without
   repeating the media query. */
.theme-toggle[data-theme="dark"] .theme-toggle__moon,
.theme-toggle[data-theme="light"] .theme-toggle__sun { display: none; }
/* Before the script paints, show neither rather than both stacked. */
.theme-toggle:not([data-theme]) .theme-toggle__sun { display: none; }

/* ---- language switch --------------------------------------------------
   Same pill language as .theme-toggle, sitting right beside it — both are
   "how this page presents itself to you" controls. Unlike the theme toggle
   this one needs no JS gate: it's a plain form to Django's own set_language
   view (real POST, real submit buttons), so it works identically with
   scripting on or off. */
.lang-switch {
  display: flex;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.lang-switch__opt {
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: var(--track-label);
  padding: 0 var(--s-3);
  height: 34px;
  border: 0;
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.lang-switch__opt + .lang-switch__opt { border-left: 1px solid var(--rule-strong); }
.lang-switch__opt:hover { color: var(--brand-2); }
.lang-switch__opt--on { background: var(--brand-2-wash); color: var(--brand-2); cursor: default; }

.site-main { max-width: 1240px; margin: 0 auto; padding: var(--s-7) var(--s-5) var(--s-10); }
.site-main--narrow { max-width: 860px; }

.site-footer {
  border-top: 1px solid var(--rule);
  margin-top: var(--s-10);
  padding: var(--s-6) var(--s-5);
}
.site-footer__item { display: inline-flex; align-items: center; gap: 6px; }
.site-footer__inner {
  max-width: 1240px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-6);
  justify-content: space-between;
  align-items: center;
}

/* Buraq, quietly: the platform's mark at the foot of the operator's site. */
.powered-by {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink-3);
}
.powered-by img { height: 22px; width: auto; display: block; }

/* ---- icons ----------------------------------------------------------- */
.ico {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: inherit;
}
.ico--sm { width: 15px; height: 15px; }
.ico--lg { width: 22px; height: 22px; }

/* ---- icons in headings, labels and fields --------------------------- */
/* A section heading's icon sits on a small tile in the company's accent
   wash, so every panel on every page opens the same way. */
.ico-tile {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 30px; height: 30px;
  border-radius: var(--r-md);
  background: var(--brand-2-wash);
  color: var(--brand-2);
  margin-right: var(--s-3);
  vertical-align: middle;
}
.ico-tile .ico { width: 16px; height: 16px; }
.ico-tile--lg { width: 48px; height: 48px; border-radius: var(--r-lg); margin: 0; }
.ico-tile--lg .ico { width: 24px; height: 24px; }
.panel__head h2,
.panel__head h3 { display: flex; align-items: center; }
/* A small glyph before an uppercase label (form fields, filter groups). */
.ico--label { display: inline-block; width: 13px; height: 13px; vertical-align: -2px; margin-right: 3px; color: var(--ink-3); }
/* A field with its icon inside, on the left — From, To, Date. */
.field-ico { position: relative; display: block; }
.field-ico__i {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px; height: 16px;
  color: var(--brand-2);
  pointer-events: none;
  z-index: 1;
}
.field-ico > .select,
.field-ico > .input { padding-left: 38px; }

/* ---- why book here ---------------------------------------------------- */
.perks { margin-top: var(--s-9); }
.perks__title { font-size: var(--t-xl); margin-bottom: var(--s-5); }
.perks__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-4);
}
.perk {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  box-shadow: var(--shadow-1);
}
.perk h3 { font-size: var(--t-md); margin: var(--s-4) 0 var(--s-2); }
.perk p { margin: 0; font-size: var(--t-sm); color: var(--ink-2); }

/* ---- messages -------------------------------------------------------- */
.messages { list-style: none; max-width: 1240px; margin: var(--s-4) auto 0; padding: 0 var(--s-5); }
.message {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid;
  font-size: var(--t-sm);
  margin-bottom: var(--s-2);
}
.message.success { background: var(--positive-wash); border-color: color-mix(in srgb, var(--positive) 35%, transparent); color: var(--positive); }
.message.error,
.message.warning { background: var(--critical-wash); border-color: color-mix(in srgb, var(--critical) 35%, transparent); color: var(--critical); }
.message.info { background: var(--info-wash); border-color: color-mix(in srgb, var(--info) 35%, transparent); color: var(--info); }

/* ---- page head ------------------------------------------------------- */
.page-head { margin-bottom: var(--s-6); }
.page-head h1 { margin-bottom: var(--s-2); }
.page-head__lede { color: var(--ink-2); max-width: 56ch; font-size: var(--t-md); }
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}

/* ---- operator band ----------------------------------------------------
   The top of the home page belongs to the bus company: their name, a line
   on what the site does, and their numbers, on their own brand colour. The
   search capsule rides up over the band's lower edge, inset from its sides.

   --brand is whatever the company picked, and a company can pick a light
   one — so the band darkens it rather than trusting it under white text.
   A soft wash of --brand-2 in one corner keeps a single flat colour from
   reading as an error state. */
.hero {
  --hero-overlap: 34px;
  margin-bottom: var(--s-6);
}
.opband {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  color: #fff;
  background:
    radial-gradient(120% 140% at 100% 0%, color-mix(in oklab, var(--brand-2) 38%, transparent), transparent 60%),
    color-mix(in oklab, var(--brand), black 38%);
  padding: var(--s-6) var(--s-7) calc(var(--hero-overlap) + var(--s-5));
}
/* On the dark theme a dark band would melt into the page; a faint edge keeps
   it an object. */
:root[data-theme="dark"] .opband { box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.08); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .opband { box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.08); }
}
.opband__title {
  color: inherit;
  font-size: var(--t-2xl);
  line-height: 1.05;
  margin: 0 0 var(--s-2);
}
.opband__lede {
  margin: 0 0 var(--s-3);
  max-width: 60ch;
  font-size: var(--t-md);
  color: rgb(255 255 255 / 0.86);
}
.opband__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-1) var(--s-2);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: rgb(255 255 255 / 0.78);
}
.opband__meta a { color: #fff; text-decoration-color: rgb(255 255 255 / 0.45); }
:lang(bn) .opband__meta { letter-spacing: normal; }
/* Everything written on the band sits above its artwork. */
.opband > :not(.opband__art):not(.opband__horse) { position: relative; z-index: 1; }
.opband { min-height: 236px; }
/* The default backdrop (search.html): road, sun and route, right-aligned. */
.opband__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* The centre line drifts toward the horizon, slowly — a road in motion. */
.opband__lane { animation: opband-lane 2.8s linear infinite; }
@keyframes opband-lane { to { stroke-dashoffset: -68; } }
/* Buraq's flying horse, over the road and heading for the sun. */
.opband__horse {
  position: absolute;
  right: 4%;
  top: 10%;
  height: 64%;
  width: auto;
  pointer-events: none;
  filter: drop-shadow(0 10px 24px rgb(0 0 0 / 0.35));
  animation: opband-glide 6s ease-in-out infinite;
}
@keyframes opband-glide {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(-7px) rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) {
  .opband__lane, .opband__horse { animation: none; }
}
/* The company's own photo instead of the drawn scene: darkened on the left,
   where the name and text sit, clear on the right. */
.opband--photo {
  background:
    linear-gradient(90deg,
      color-mix(in oklab, var(--brand), black 45%) 0%,
      color-mix(in oklab, color-mix(in oklab, var(--brand), black 45%) 78%, transparent) 42%,
      transparent 78%),
    linear-gradient(0deg, rgb(0 0 0 / 0.35), transparent 45%),
    var(--hero-photo) center / cover no-repeat,
    color-mix(in oklab, var(--brand), black 38%);
  min-height: 300px;
}
/* The comfort line: what the company's buses have, as quiet glass chips. */
.opband__comfort {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: var(--s-4) 0 0;
  padding: 0;
  max-width: 62%;
}
.opband__comfort li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 500;
  color: #fff;
  background: rgb(255 255 255 / 0.12);
  border: 1px solid rgb(255 255 255 / 0.2);
  backdrop-filter: blur(6px);
  white-space: nowrap;
}
.opband__comfort .ico { width: 14px; height: 14px; }

/* Sits above the band it overlaps. */
.hero .searchbar {
  position: relative;
  z-index: 1;
  margin: calc(var(--hero-overlap) * -1) var(--s-5) 0;
}
@media (max-width: 720px) {
  .hero { --hero-overlap: 28px; }
  .opband { padding: var(--s-5) var(--s-5) calc(var(--hero-overlap) + var(--s-5)); }
  .opband__title { font-size: var(--t-xl); }
  .opband { min-height: 0; }
  .opband--photo { min-height: 220px; }
  /* Smaller and to the top right, behind nothing that has to be read. */
  .opband__horse { height: 24%; top: 6%; right: 3%; opacity: .6; }
  .opband__comfort { max-width: none; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-top: var(--s-3); }
  .opband__comfort::-webkit-scrollbar { display: none; }
  /* The name and the numbers carry it; the departures need the room. */
  .opband__lede { display: none; }
  .opband__title { margin-bottom: var(--s-3); }
  .hero .searchbar { margin-inline: var(--s-3); }
}

.searchbar {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  padding: var(--s-3);
  margin-bottom: var(--s-6);
}
.searchbar__grid {
  display: grid;
  gap: var(--s-2);
  grid-template-columns: 1fr auto 1fr 1fr auto;
  align-items: end;
}
.searchbar__field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.searchbar__field > .u-label { padding-left: var(--s-3); }
.searchbar__swap {
  align-self: end;
  margin-bottom: 3px;
  width: 38px; height: 38px;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule);
  background: var(--surface);
  color: var(--ink-2);
  display: grid; place-items: center;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.searchbar__swap:hover { color: var(--brand-2); border-color: var(--brand-2); }

/* Clear search: the swap button's twin, at the end of the row. An extra
   grid column only while it's showing, so the capsule is unchanged when
   there's nothing to clear. */
.searchbar__grid:has(> .searchbar__reset:not([hidden])) { grid-template-columns: 1fr auto 1fr 1fr auto auto; }
/* Small labelled pill — "✕ Clear" — centred on the 38px control row. */
.searchbar__reset {
  align-self: end;
  margin-bottom: 7px;
  height: 24px;
  padding: 0 9px 0 7px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong);
  background: var(--surface-sunken);
  color: var(--ink-2);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.searchbar__reset .ico { width: 11px; height: 11px; }
.searchbar__reset[hidden] { display: none; }
.searchbar__reset:hover {
  color: var(--critical);
  border-color: color-mix(in srgb, var(--critical) 45%, transparent);
  background: var(--critical-wash);
  text-decoration: none;
}
.searchbar__reset:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }
@media (max-width: 860px) {
  /* Stacked capsule: the pill sits centred under Search. */
  .searchbar__grid:has(> .searchbar__reset:not([hidden])) { grid-template-columns: 1fr 1fr; }
  .searchbar__reset { grid-column: 1 / -1; justify-self: center; margin: 2px 0 0; }
}

/* The From/To selects, date input and Search button were sitting at the
   sitewide 44px touch-target height (see the note on .input/.select below)
   while .searchbar__swap next to them was already 38px — the one row where
   that mismatch was visible, since every other control here is grouped
   with only its own kind. Scoped to the capsule rather than lowering
   .input/.select/.btn themselves: the rest of the site (checkout, filters)
   keeps the full touch target, this row just reads as one consistent set
   of components instead of one oddly small one among four larger ones. */
.searchbar__grid .select,
.searchbar__grid .input {
  min-height: 38px;
  padding-top: 8px;
  padding-bottom: 8px;
}
/* .btn.searchbar__submit, not .searchbar__submit alone: .btn's own
   min-height: 44px (below, in the buttons section) is the same specificity
   and comes later in the file, so a single-class override here would lose
   to it regardless of what's written above. Two classes outranks one. */
.btn.searchbar__submit { min-height: 38px; }

@media (max-width: 860px) {
  .searchbar__grid { grid-template-columns: 1fr 1fr; }
  .searchbar__swap { display: none; }
  .searchbar__field--date { grid-column: 1 / -1; }
  .searchbar__submit { grid-column: 1 / -1; }
}

/* ---- form controls --------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--s-4); min-width: 0; }
.field__hint { font-size: var(--t-xs); color: var(--ink-3); }
.field__error { font-size: var(--t-xs); color: var(--critical); display: flex; align-items: center; gap: 6px; }
.field--invalid .input { border-color: var(--critical); }

.input,
.select {
  width: 100%;
  font-family: inherit;
  font-size: var(--t-base);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-md);
  padding: 11px var(--s-3);
  /* 44px minimum touch target — this is a phone-first booking flow and a
     10px-padded input on a 15px font falls short of it. */
  min-height: 44px;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.input::placeholder { color: var(--ink-3); }
.input:focus,
.select:focus {
  outline: none;
  border-color: var(--brand-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-2) 18%, transparent);
}
.select {
  appearance: none;
  padding-right: var(--s-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 19px) calc(50% + 1px), calc(100% - 13px) calc(50% + 1px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  cursor: pointer;
}
input[type="date"].input { min-width: 0; }
textarea.input { min-height: 92px; resize: vertical; line-height: var(--lh-body); }

/* ---- buttons --------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  font-family: inherit;
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.005em;
  min-height: 44px;
  padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(0.5px); }

.btn--primary {
  background: var(--brand-2);
  color: var(--brand-2-ink);
  /* Tinted with the button's own hue instead of the neutral --shadow-*
     ramp. A grey shadow under a saturated fill greys the fill's edge;
     this lifts it off the card without dulling it. */
  box-shadow: 0 1px 1px rgb(16 22 28 / 0.05),
              0 6px 14px -8px color-mix(in srgb, var(--brand-2) 75%, transparent);
}
.btn--primary:hover {
  background: color-mix(in srgb, var(--brand-2) 86%, #000);
  box-shadow: 0 1px 2px rgb(16 22 28 / 0.07),
              0 10px 20px -8px color-mix(in srgb, var(--brand-2) 75%, transparent);
}
.btn--ghost { background: transparent; border-color: var(--rule-strong); color: var(--ink); }
.btn--ghost:hover { background: var(--surface-hover); border-color: var(--ink-3); }
.btn--quiet { background: transparent; color: var(--ink-2); padding: 0 var(--s-3); }
.btn--quiet:hover { color: var(--brand-2); }
.btn--danger { background: transparent; border-color: color-mix(in srgb, var(--critical) 45%, transparent); color: var(--critical); }
.btn--danger:hover { background: var(--critical-wash); }
.btn--lg { min-height: 52px; font-size: var(--t-md); padding: 0 var(--s-6); }
.btn--block { width: 100%; }
.btn--sm { min-height: 36px; font-size: var(--t-xs); padding: 0 var(--s-4); }

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* ---- chips ----------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--t-xs);
  font-weight: 500;
  padding: 7px var(--s-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink-2);
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.chip:hover { border-color: var(--ink-3); color: var(--ink); text-decoration: none; }
.chip[aria-pressed="true"],
.chip--on {
  background: var(--brand-2-wash);
  border-color: var(--brand-2);
  color: var(--brand-2);
}
.chip-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }
/* Phones: the home page's popular routes stay one row that scrolls sideways
   (like the date strip above them) — wrapped, six routes took three rows and
   pushed the departures off the first screen. */
@media (max-width: 720px) {
  .chip-row--scroll { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 2px; }
  .chip-row--scroll::-webkit-scrollbar { display: none; }
  .chip-row--scroll > * { flex: 0 0 auto; white-space: nowrap; }
}

/* ---- status badges --------------------------------------------------- */
/* Always word + colour, never colour alone — a colour-only status is
   invisible to a colourblind reader and gone entirely on a thermal print. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  white-space: nowrap;
}
.badge--positive { background: var(--positive-wash); color: var(--positive); border-color: color-mix(in srgb, var(--positive) 28%, transparent); }
.badge--caution { background: var(--caution-wash); color: var(--caution); border-color: color-mix(in srgb, var(--caution) 28%, transparent); }
.badge--critical { background: var(--critical-wash); color: var(--critical); border-color: color-mix(in srgb, var(--critical) 28%, transparent); }
.badge--info { background: var(--info-wash); color: var(--info); border-color: color-mix(in srgb, var(--info) 28%, transparent); }
.badge--quiet { background: var(--surface-sunken); color: var(--ink-3); border-color: var(--rule); }

/* ---- layout: rail + results ------------------------------------------ */
.board-layout {
  display: grid;
  grid-template-columns: 244px minmax(0, 1fr);
  gap: var(--s-7);
  align-items: start;
  /* Every control on the search page navigates to #board (see search.html).
     Landing hard on the board would push the date strip off the top, so a
     visitor picking a second date would have to scroll back up for it.
     This reserves roughly the strip-plus-popular-routes height above the
     anchor, which keeps both on screen with the departures — plus the
     sticky header's own ~81px, which stays pinned over the top of it. */
  scroll-margin-top: 231px;
}
@media (max-width: 960px) {
  .board-layout { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
}
/* The rail collapses to a one-line disclosure here, so less sits above the
   anchor and reserving the desktop amount would leave a dead band. */
@media (max-width: 720px) {
  .board-layout { scroll-margin-top: 212px; }  /* the strip and chips (~139px) + the 65px header */
}

.rail { position: sticky; top: 78px; }
@media (max-width: 960px) { .rail { position: static; } }

/* Carries .sheet__head in the markup and takes its padding, ground and
   bottom rule from there — this only sets what differs, so the two columns'
   headers can't drift apart. Its title matches the board's ("6 departures"). */
.sheet__head.rail__head { align-items: center; flex-wrap: nowrap; gap: var(--s-2); padding-inline: var(--s-4); }
.rail__title {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-size: var(--t-lg);
}
.rail__title .ico-tile { margin-right: 2px; }
.rail__head .rail__clear { margin-left: auto; flex: none; }
.rail__clear {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px 4px 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink-2);
  font-size: var(--t-xs);
  font-weight: 600;
  text-decoration: none;
}
.rail__clear:hover { color: var(--critical); border-color: color-mix(in srgb, var(--critical) 45%, transparent); background: var(--critical-wash); text-decoration: none; }
.rail__clear .ico { width: 12px; height: 12px; }

/* Each facet is a ticket, like the departures it filters (.dep): its title
   above a perforation notched at both edges, the options below. */
.rail__group {
  position: relative;
  overflow: hidden;
  padding: 0 var(--s-3) var(--s-3);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
.rail__group-title {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0 calc(var(--s-3) * -1) var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-bottom: 2px dashed var(--rule);
  color: var(--ink) !important;
  font-weight: 600;
}
.rail__group-title .ico--label {
  width: 26px; height: 26px;
  padding: 5px;
  margin: 0;
  box-sizing: border-box;
  border-radius: var(--r-sm);
  background: var(--brand-2-wash);
  color: var(--brand-2);
  vertical-align: middle;
}
/* Notches where the perforation meets the edges, cut to the rail's ground. */
.rail__group-title::before,
.rail__group-title::after {
  content: "";
  position: absolute;
  bottom: -11px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--brand-2) 5%, var(--surface-sunken));
  box-shadow: inset 0 0 0 1px var(--rule);
}
.rail__group-title::before { left: -11px; }
.rail__group-title::after { right: -11px; }
.rail__group > .check:first-of-type { margin-top: var(--s-1); }
.rail__group .price-range { padding: var(--s-2) var(--s-1) 0; }

/* On phones the whole rail collapses into a disclosure so the page opens
   on departures, not on controls. */
.rail__disclosure > summary {
  display: none;
  align-items: center;
  gap: var(--s-2);
  cursor: pointer;
  list-style: none;
  font-size: var(--t-sm);
  font-weight: 600;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  margin-bottom: var(--s-4);
}
.rail__disclosure > summary::-webkit-details-marker { display: none; }
@media (max-width: 960px) {
  .rail__disclosure > summary { display: flex; }
  .rail__disclosure > summary .ico:last-child { margin-left: auto; transition: transform var(--dur) var(--ease); }
  .rail__disclosure[open] > summary .ico:last-child { transform: rotate(180deg); }
}

.check {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 7px var(--s-2);
  margin: 1px 0;
  border-radius: var(--r-md);
  font-size: var(--t-sm);
  color: var(--ink-2);
  cursor: pointer;
  min-height: 38px;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.check:hover { color: var(--ink); background: var(--surface-sunken); }
/* A ticked option is lit, like a selected row on a board. */
.check:has(input:checked) { background: var(--brand-2-wash); color: var(--ink); font-weight: 600; }
.check input {
  appearance: none;
  width: 18px; height: 18px;
  flex-shrink: 0;
  margin: 0;
  border: 1.5px solid var(--rule-strong);
  border-radius: 5px;
  background: var(--surface);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.check input:checked { background: var(--brand-2); border-color: var(--brand-2); }
.check input:checked::after {
  content: "";
  width: 9px; height: 5px;
  border-left: 2px solid var(--brand-2-ink);
  border-bottom: 2px solid var(--brand-2-ink);
  transform: rotate(-45deg) translate(1px, -1px);
}
.check input:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }
/* Counts on mini split-flap tiles — the departure board's own vocabulary. */
.check__count,
.flap--mini {
  margin-left: auto;
  min-width: 22px;
  height: 24px;
  padding: 0 5px;
  box-sizing: border-box;
  display: inline-grid;
  place-items: center;
  border-radius: 5px;
  background: linear-gradient(#232c3a 0 50%, #1b2230 50% 100%);
  color: #fbf3df;
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 700;
  position: relative;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .08);
}
.check__count::after,
.flap--mini::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: rgb(0 0 0 / .5);
}
.flap--mini { width: auto; margin-left: var(--s-1); font-size: var(--t-xs); }
.check .ico { color: var(--ink-3); }
.check > span:not(.check__count) { flex: 1; min-width: 0; line-height: 1.3; }

.price-range { display: flex; align-items: center; gap: var(--s-2); }
.price-range .input { padding: 9px var(--s-3); min-height: 40px; font-family: var(--font-mono); font-size: var(--t-sm); }
.price-range__dash { color: var(--ink-3); }

/* ---- results sheet --------------------------------------------------- */
.sheet {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--brand-2) 5%, var(--surface-sunken));
}
.sheet__head .u-label,
.group-head .u-label { color: var(--ink-2); }
.sheet__title { display: flex; align-items: baseline; gap: var(--s-3); flex-wrap: wrap; }
.sheet__sort { display: flex; align-items: center; gap: var(--s-2); }
.sheet__sort .select { min-height: 38px; padding: 8px var(--s-8) 8px var(--s-3); font-size: var(--t-sm); width: auto; }

.sheet__empty { padding: var(--s-9) var(--s-5); text-align: center; }
.sheet__empty .ico { width: 34px; height: 34px; color: var(--ink-3); margin: 0 auto var(--s-4); }

/* ---- departure card -------------------------------------------------- */
/* The core object of the whole site. Each departure is its own card: the
   sheet holds a stack of them rather than one ruled list, so a result
   reads as a separate thing you can pick, not a line in a table.

   --shadow-1 is the lightest of the three (tokens.css) and is doing the
   separating here, which is why the card also needs its own background and
   a gap around it — a shadow cast onto the next row's edge, with no space
   between, reads as a smudge rather than a lift. The rule that used to
   divide the rows is gone for the same reason: a border AND a shadow on
   the same edge is two separators doing one job. */
/* The sunken ground a stack of cards sits on, inside a .sheet. Both columns
   share it: the filter facets on the left and the departures on the right are
   the same object at different sizes, so they get one definition rather than
   two that drift. */
.dep-list,
.rail__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-3);
  /* A few percent of the tenant's action colour mixed into the sunken
     ground. Not decoration: the white cards were floating on a cream that
     was almost exactly their own value, so --shadow-1 had nothing to
     separate them against and the stack read as one flat block. Tinting the
     ground rather than darkening it keeps the paper warmth and ties the
     board to the brand at the same time. */
  background: color-mix(in srgb, var(--brand-2) 5%, var(--surface-sunken));
}
/* A departure reads as a ticket off a terminal departures board:
     date block | the journey (departure time on split-flap tiles) | stub
   The stub — fare, seats left, the button — carries the route's own
   colour, behind a perforation notched top and bottom where a ticket is
   torn. One memorable thing (the flaps); everything around it quiet. */
.dep {
  /* .dep-list's own ground, which the stub's notches are cut out to. */
  --dep-ground: color-mix(in srgb, var(--brand-2) 5%, var(--surface-sunken));
  --dep-line: var(--line, var(--rule-strong));
  /* Text on the route colour: white on the light theme's deep line colours,
     near-black on the dark theme's lighter ones. */
  --dep-on-line: light-dark(#ffffff, #10161c);
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr) 210px;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  position: relative;
  overflow: hidden;
  transition: box-shadow var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.dep:hover {
  box-shadow: var(--shadow-3);
  border-color: color-mix(in srgb, var(--dep-line) 45%, var(--rule));
  transform: translateY(-2px);
}
/* Sold out, or only sold at the counter: still listed (a passenger can buy
   it at the counter), but quieter, so the bookable ones lead. */
.dep--muted { box-shadow: none; }
.dep--muted .dep__main, .dep--muted .dep__day { opacity: .6; }
.dep--muted:hover { transform: none; box-shadow: var(--shadow-1); }
@media (prefers-reduced-motion: reduce) {
  .dep { transition: box-shadow var(--dur-fast) var(--ease); }
  .dep:hover { transform: none; }
}

/* ---- date block: the route's colour, like a ticket's coloured edge ---- */
.dep__day {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: var(--dep-line);
  color: var(--dep-on-line);
  text-align: center;
  line-height: 1;
  padding: var(--s-3) 0;
}
.dep__day-dow, .dep__day-mon {
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  opacity: .88;
}
.dep__day-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 34px;
  font-variation-settings: "opsz" 48;
  letter-spacing: -0.02em;
  margin: 2px 0;
}
:lang(bn) .dep__day-dow, :lang(bn) .dep__day-mon { letter-spacing: normal; }

.dep__main { min-width: 0; padding: var(--s-4) var(--s-5) var(--s-4); }

.dep__route {
  display: flex;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  margin-bottom: var(--s-4);
  flex-wrap: wrap;
}
/* The inline date: phones only, where the date block folds away. */
.dep__date {
  display: none;
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--dep-on-line);
  background: var(--dep-line);
  border-radius: var(--r-sm);
  padding: 3px 7px;
}
:lang(bn) .dep__date { letter-spacing: normal; }
.dep__route-name {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--t-md);
  font-variation-settings: "opsz" 24;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.dep__arrow { color: var(--dep-line); font-family: var(--font-body); font-weight: 600; margin: 0 2px; }
/* Wayfinding dot — the route's fixed line colour (still used by chips). */
.line-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--line); }
.line-1 { --line: var(--line-1); }
.line-2 { --line: var(--line-2); }
.line-3 { --line: var(--line-3); }
.line-4 { --line: var(--line-4); }
.line-5 { --line: var(--line-5); }
.line-6 { --line: var(--line-6); }

/* ---- the journey ------------------------------------------------------ */
.leg {
  display: grid;
  grid-template-columns: auto minmax(60px, 1fr) auto;
  gap: var(--s-4);
  align-items: center;
  margin-bottom: var(--s-4);
  max-width: 640px;
}

/* The signature: the departure time on split-flap tiles, as on the
   boards over terminal counters (and Buraq's own terminal TV screens).
   Fixed dark tiles in both themes — a flap board is dark — with a hairline
   where the flap folds. Hovering the card flips them once, in sequence. */
.flaps { display: inline-flex; align-items: center; gap: 3px; }
.flap {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 40px;
  border-radius: 6px;
  background: linear-gradient(#232c3a 0 50%, #1b2230 50% 100%);
  color: #fbf3df;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 25px;
  font-weight: 700;
  line-height: 1;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .08), 0 2px 4px rgb(0 0 0 / .18);
  transform-origin: 50% 50%;
}
.flap::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: rgb(0 0 0 / .55);
  box-shadow: 0 1px 0 rgb(255 255 255 / .06);
}
.flaps__sep { font-family: var(--font-mono); font-weight: 700; font-size: 22px; color: var(--ink-3); margin: 0 1px; }
:root[data-theme="dark"] .flap { box-shadow: inset 0 0 0 1px rgb(255 255 255 / .09), 0 2px 4px rgb(0 0 0 / .4); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .flap { box-shadow: inset 0 0 0 1px rgb(255 255 255 / .09), 0 2px 4px rgb(0 0 0 / .4); }
}
.dep:hover .flap { animation: flap-turn 420ms cubic-bezier(.3, .7, .3, 1) calc(var(--i, 0) * 60ms) both; }
@keyframes flap-turn {
  0%   { transform: perspective(160px) rotateX(0); }
  45%  { transform: perspective(160px) rotateX(-88deg); filter: brightness(.7); }
  55%  { transform: perspective(160px) rotateX(88deg); filter: brightness(.7); }
  100% { transform: perspective(160px) rotateX(0); }
}
@media (prefers-reduced-motion: reduce) { .dep:hover .flap { animation: none; } }

.leg__time {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-xl);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ink-2);
  white-space: nowrap;
}
/* Arrives the next day: an overnight coach's 07:00 is tomorrow's. */
.leg__nextday {
  font-size: 0.45em;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--caution);
  margin-left: 2px;
  vertical-align: super;
}
.leg__place {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 8px;
}
:lang(bn) .leg__place { letter-spacing: normal; }
.leg__end { text-align: right; }
.leg__end .leg__place { text-align: right; }

/* The road between the two times: the route's colour from a hollow origin
   dot to a filled destination, a small bus on it, the journey time below. */
.leg__span { display: flex; flex-direction: column; align-items: stretch; gap: 6px; min-width: 0; }
.leg__track {
  position: relative;
  height: 2px;
  margin: 0 5px;
  border-radius: 2px;
  background: repeating-linear-gradient(90deg, var(--dep-line) 0 8px, transparent 8px 13px);
  opacity: .85;
}
.leg__track::before,
.leg__track::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 10px; height: 10px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-sizing: border-box;
}
.leg__track::before { left: 0; background: var(--surface); border: 2px solid var(--dep-line); }
.leg__track::after { left: 100%; background: var(--dep-line); }
.leg__bus {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--dep-line);
  color: var(--dep-on-line);
  box-shadow: 0 0 0 4px var(--surface);
  transition: left 700ms var(--ease);
}
.leg__bus .ico { width: 15px; height: 15px; }
.dep:hover .leg__bus { left: 64%; }
@media (prefers-reduced-motion: reduce) {
  .leg__bus { transition: none; }
  .dep:hover .leg__bus { left: 50%; }
}
.leg__span-label {
  align-self: center;
  margin-top: 12px;
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

.dep__meta {
  display: flex;
  align-items: center;
  gap: var(--s-2) var(--s-4);
  flex-wrap: wrap;
  font-size: var(--t-xs);
  color: var(--ink-3);
  padding-top: var(--s-3);
  border-top: 1px dashed var(--rule);
}
.dep__meta-item { display: inline-flex; align-items: center; gap: 6px; }
.dep__coach { color: var(--ink-2); font-weight: 600; }

/* Amenities: a quiet row of glyphs on small tiles; the label is on the
   tooltip and in an sr-only span, so this never becomes icon-only for a
   screen reader. */
.amenities { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); }
.amenities > span {
  display: grid;
  place-items: center;
  width: 24px; height: 24px;
  border-radius: var(--r-sm);
  background: var(--surface-sunken);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.amenities .ico { width: 15px; height: 15px; }

.rating { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); }
.rating .ico { width: 13px; height: 13px; color: var(--caution); }
.rating__score { font-family: var(--font-mono); font-weight: 600; font-size: var(--t-xs); }
.rating__count { color: var(--ink-3); font-size: var(--t-2xs); }

/* ---- the stub: in the route's colour, torn along a perforation -------- */
.dep__side {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  text-align: center;
  background:
    radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--dep-line) 16%, transparent), transparent 70%),
    color-mix(in srgb, var(--dep-line) 6%, var(--surface));
  border-left: 2px dashed color-mix(in srgb, var(--dep-line) 40%, var(--rule-strong));
}
/* Notches: true cut-outs in the board's own ground colour. */
.dep__side::before,
.dep__side::after {
  content: "";
  position: absolute;
  left: -1px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--dep-ground);
  box-shadow: inset 0 0 0 1px var(--rule);
  transform: translateX(-50%);
}
.dep__side::before { top: -12px; }
.dep__side::after { bottom: -12px; }
.dep__side .badge { align-self: center; }
.fare { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.fare__amount {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 48;
  font-variant-numeric: lining-nums;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ink);
}
.fare__unit {
  font-size: var(--t-2xs);
  color: var(--ink-3);
  font-family: var(--font-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.fare--sm .fare__amount { font-size: var(--t-md); }
.dep__side .btn--primary { width: 100%; justify-content: center; }
.dep__side .avail { justify-content: center; font-size: var(--t-xs); }

@media (max-width: 720px) {
  /* Phones: the date block folds into a tag, and the stub tears off the
     bottom — a horizontal perforation, notches at its two ends, fare and
     button side by side, seats left beneath. */
  .dep { grid-template-columns: minmax(0, 1fr); }
  .dep__day { display: none; }
  .dep__date { display: inline-block; }
  .dep { border-top: 4px solid var(--dep-line); }
  .dep__main { padding: var(--s-4) var(--s-4) var(--s-3); }
  .dep__side {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--s-2) var(--s-4);
    padding: var(--s-3) var(--s-4);
    border-left: 0;
    border-top: 2px dashed color-mix(in srgb, var(--dep-line) 40%, var(--rule-strong));
    text-align: left;
  }
  .dep__side::before,
  .dep__side::after { top: -1px; bottom: auto; transform: translateY(-50%); }
  .dep__side::before { left: -12px; }
  .dep__side::after { left: auto; right: -12px; }
  .dep__side .btn--primary { width: auto; justify-self: end; }
  .dep__side .badge { justify-self: end; }
  .dep__side .avail { grid-column: 1 / -1; justify-content: flex-start; }
  .fare { align-items: flex-start; }
  .fare__amount { font-size: 26px; }
  .leg { gap: var(--s-3); }
  .flap { width: 24px; height: 34px; font-size: 20px; }
  .flaps__sep { font-size: 18px; }
  .leg__time { font-size: var(--t-lg); }
}

/* ---- section headings between grouped departures --------------------- */
.group-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: color-mix(in srgb, var(--brand-2) 5%, var(--surface-sunken));
  border-bottom: 1px solid var(--rule);
}
/* The section's name, not another piece of meta — it is the only thing
   telling a passenger which part of the day they have scrolled into, so
   it is set at full ink rather than the --ink-3 every other label uses.

   The colour accent is a FILL, not the text. --brand-2 is tenant-supplied
   (base.html injects it from Tenant.secondary_color), so its contrast
   against any ground is unknowable at authoring time — setting 11px type
   in it measured 3.84:1 on Green Line's blue in dark mode, under the 4.5
   this label needs as text. A bar carries the same colour with no such
   floor to clear, which is why tokens.css scopes --brand-2 to fills,
   rings and selected states rather than to type. */
.group-head > .u-label:first-child {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink);
}
.group-head > .u-label:first-child::before {
  content: "";
  width: 3px;
  height: 0.95em;
  border-radius: 2px;
  background: var(--brand-2);
}
/* The count trails the rule rather than sitting beside the label, so the
   two read as heading-then-tally instead of two equal labels. */
.group-head > .u-label:last-child {
  order: 3;
  padding: 2px var(--s-2);
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--rule);
  color: var(--ink-2);
}
.group-head::after { content: ""; order: 2; flex: 1; border-top: 1px solid var(--rule-strong); }

/* ---- date strip ------------------------------------------------------ */
.datestrip { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-5); }
.datestrip__scroll {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  scrollbar-width: none;
  padding: 2px;
  scroll-snap-type: x proximity;
}
.datestrip__scroll::-webkit-scrollbar { display: none; }
.datestrip__day {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 60px;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--surface);
  text-decoration: none;
  color: var(--ink-2);
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.datestrip__day:hover { border-color: var(--ink-3); text-decoration: none; }
.datestrip__dow { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-3); }
.datestrip__date { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--t-md); font-weight: 600; line-height: 1.1; }
.datestrip__day--on {
  background: var(--brand-2);
  border-color: var(--brand-2);
  color: var(--brand-2-ink);
  box-shadow: 0 6px 16px -7px color-mix(in srgb, var(--brand-2) 80%, transparent);
}
/* The day-of-week sits quieter than the date it labels, but only just: at
   78% this measured 4.0:1 on a tenant brand of #2A66C9, under the 4.5 a
   9.5px label needs. 90% keeps the two-step hierarchy and clears it. */
.datestrip__day--on .datestrip__dow { color: color-mix(in srgb, var(--brand-2-ink) 90%, transparent); }
.datestrip__arrow {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule);
  background: var(--surface);
  color: var(--ink-2);
  display: grid; place-items: center;
  text-decoration: none;
}
.datestrip__arrow:hover { color: var(--brand-2); border-color: var(--brand-2); }

/* ---- checkout: two-column with sticky summary ------------------------ */
.checkout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 336px;
  gap: var(--s-7);
  align-items: start;
}
@media (max-width: 960px) { .checkout { grid-template-columns: minmax(0, 1fr); } }

.panel {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.panel + .panel { margin-top: var(--s-5); }
.panel__head {
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.panel__body { padding: var(--s-5); }

.summary { position: sticky; top: 78px; }
@media (max-width: 960px) { .summary { position: static; } }

/* ---- money breakdown ------------------------------------------------- */
/* The one place the fare arithmetic becomes visible, so it mirrors
   apps.bookings.services.quote_booking line for line: subtotal, discount,
   fee, total. Tabular figures keep the right edge of the column straight. */
.money { display: flex; flex-direction: column; gap: var(--s-3); }
.money__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); font-size: var(--t-sm); }
.money__label { color: var(--ink-2); display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.money__value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap; }
.money__row--credit .money__label,
.money__row--credit .money__value { color: var(--positive); }
.money__row--total {
  border-top: 1px solid var(--rule-strong);
  padding-top: var(--s-3);
  margin-top: var(--s-1);
  align-items: baseline;
}
.money__row--total .money__label { font-weight: 600; color: var(--ink); font-size: var(--t-base); }
.money__row--total .money__value { font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.03em; }

/* ---- seat map -------------------------------------------------------- */
/* A real bus floor plan: an aisle gap, a driver marker, and rows that read
   front-to-back. The aisle is a grid gap rather than a drawn divider —
   whitespace is what actually communicates "you walk down here". */
.deck {
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-lg) var(--r-lg) var(--r-md) var(--r-md);
  padding: var(--s-5) var(--s-4) var(--s-4);
  background: var(--surface-sunken);
  position: relative;
  max-width: 320px;
}
.deck__driver {
  position: absolute;
  top: calc(-1 * var(--s-3));
  right: var(--s-4);
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-pill);
  padding: 3px var(--s-3);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.deck__rows { display: flex; flex-direction: column; gap: var(--s-2); }
.deck__row { display: grid; grid-template-columns: repeat(2, 40px) var(--s-6) repeat(2, 40px); gap: var(--s-2); justify-content: center; }

.seat {
  width: 40px;
  height: 40px;
  border-radius: 9px 9px 6px 6px;
  border: 1.5px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 500;
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.seat:hover:not(:disabled) { border-color: var(--brand-2); color: var(--brand-2); }
.seat--taken {
  background: repeating-linear-gradient(
    -45deg, var(--surface-sunken), var(--surface-sunken) 3px, var(--rule) 3px, var(--rule) 5px
  );
  border-color: var(--rule);
  color: var(--ink-3);
  cursor: not-allowed;
}
.seat--sel { background: var(--brand-2); border-color: var(--brand-2); color: var(--brand-2-ink); font-weight: 600; }
.seat--gap { visibility: hidden; }

.seat-legend { display: flex; flex-wrap: wrap; gap: var(--s-4); margin-bottom: var(--s-4); }
.seat-legend__item { display: inline-flex; align-items: center; gap: 7px; font-size: var(--t-xs); color: var(--ink-2); }
.seat-legend__swatch { width: 15px; height: 15px; border-radius: 5px; border: 1.5px solid var(--rule-strong); background: var(--surface); }
.seat-legend__swatch--taken { background: repeating-linear-gradient(-45deg, var(--surface-sunken), var(--surface-sunken) 3px, var(--rule) 3px, var(--rule) 5px); border-color: var(--rule); }
.seat-legend__swatch--sel { background: var(--brand-2); border-color: var(--brand-2); }

/* Selected seats, listed with a remove control. */
.seat-list { display: flex; flex-direction: column; gap: var(--s-2); }
.seat-list__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--rule);
}
.seat-list__item:last-child { border-bottom: 0; }
.seat-list__tag {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  font-weight: 600;
  padding: 5px 9px;
  border-radius: var(--r-sm);
  background: var(--brand-2-wash);
  color: var(--brand-2);
}
.seat-list__drop {
  margin-left: auto;
  width: 28px; height: 28px;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-3);
  display: grid; place-items: center;
  cursor: pointer;
}
.seat-list__drop:hover { color: var(--critical); border-color: var(--critical); }

/* ---- stepper --------------------------------------------------------- */
.steps { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-6); }
.step { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--t-xs); color: var(--ink-3); white-space: nowrap; }
.step__dot {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 1.5px solid var(--rule-strong);
  display: grid; place-items: center;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
}
.step--done { color: var(--positive); }
.step--done .step__dot { background: var(--positive); border-color: var(--positive); color: #fff; }
.step--on { color: var(--ink); font-weight: 600; }
.step--on .step__dot { background: var(--brand-2); border-color: var(--brand-2); color: var(--brand-2-ink); }
.steps__link { flex: 1 1 14px; min-width: 10px; border-top: 1px solid var(--rule-strong); }
@media (max-width: 640px) {
  .step__text { display: none; }
  .step--on .step__text { display: inline; }
}

/* ---- ticket ---------------------------------------------------------- */
/* A boarding pass: two panes divided by a perforation. The notches are
   drawn with radial-gradients on the divider so the shape survives any
   background, including a print stylesheet. */
.ticket {
  display: grid;
  /* 160px, not less: the stub carries "Or read this out" as one line, which
     needs 129px at --track-label. Tightening the tracking to fit a narrower
     column instead would drop it under the ~0.1em floor tokens.css sets for
     uppercase mono, where it stops reading as a word. */
  grid-template-columns: minmax(0, 1fr) 160px;
  /* A ticket should read as a stub, not as a table. Left to fill the
     860px column this sat 820px wide with a ~510px value column carrying
     "Chattogram" — mostly empty, which is what made it look oversized
     rather than designed. Capping the width is also what makes the saved
     PNG a card you can read on a phone instead of a banner.

     660px rather than the original 560px because the extra width now buys
     a second label/value pair per row (see .ticket .dl below) instead of a
     wider empty column — the fields here are short (a name, a ticket
     number, a terminal), so pairing them halves the ticket's height. Wider
     AND shorter lands closer to the proportions of a real boarding pass
     than the tall narrow card it was.

     Now the full column, like the panels above and below it: a narrower
     ticket between full-width cards looked misaligned, and the capped value
     columns wrapped the ticket and bus numbers onto two lines each, which
     made the ticket taller, not shorter. */
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.ticket__body { padding: var(--s-4); min-width: 0; }
/* Space from the live-status panel above (its data <script> may sit
   between the two). */
.panel + .ticket, .panel + script + .ticket { margin-top: var(--s-5); }
/* Tighter than the .dl default: these rows are short identifiers read one
   at a time, not prose, so the looser rhythm the panels use only added
   height. Scoped to the ticket so the checkout panels keep theirs. */
.ticket .dl { gap: var(--s-2) var(--s-4); }
/* Two label/value pairs per row wherever the stub sits beside the body.
   Every value on a ticket is short — a name, a ticket number, a terminal,
   a time — so one pair per row left most of the column empty and made the
   card twice as tall as it needed to be. dt/dd already alternate in source
   order, so a four-track grid pairs them with no markup change, and the
   fields still read in the order they matter: who and what, when and where
   you get on, where you get off and what it cost.

   760px, not the 640px the stub switches at: the pairing is only an
   improvement once the ticket can actually reach its 700px cap, which needs
   the 700px plus .site-main's 20px gutters. Engaging it any earlier squeezes
   the value columns until "Tue 1 Sep · 09:30" wraps and orphans the time,
   which is taller AND uglier than the single-pair rows it replaced. Between
   the two widths the ticket keeps the stub beside a one-pair body. */
@media (min-width: 760px) {
  .ticket .dl {
    grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr);
    column-gap: var(--s-4);
  }
}
.ticket__stub {
  padding: var(--s-4) var(--s-3);
  border-left: 2px dashed var(--rule-strong);
  background: var(--surface-sunken);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  text-align: center;
}
/* 112px still exports at 224px on the 2x PNG and prints around 30mm, well
   above what a scanner needs — the stub gets shorter without the code
   getting harder to read. */
.ticket__qr { width: 112px; height: 112px; background: #fff; padding: 5px; border-radius: var(--r-sm); }
.ticket__code {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-md);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--ink);
}
@media (max-width: 640px) {
  .ticket { grid-template-columns: minmax(0, 1fr); }
  .ticket__stub { border-left: 0; border-top: 2px dashed var(--rule-strong); }
}

/* ---- definition rows ------------------------------------------------- */
.dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-3) var(--s-5); align-items: baseline; }
.dl dt { color: var(--ink-3); font-family: var(--font-mono); font-size: var(--t-2xs); letter-spacing: var(--track-label); text-transform: uppercase; }
.dl dd { margin: 0; color: var(--ink); min-width: 0; }
/* JetBrains Mono renders visibly larger than Familjen Grotesk at the same
   nominal size — measured on this pair, its x-height is 0.5625em against
   0.5em and its cap-height 0.7344em against 0.6563em, so a 15.5px mono value
   sits 12-20% taller than the 15.5px sans value directly above it. That only
   shows where the two meet in one column, which is exactly what a .dl is: a
   ticket number or a timestamp reads as bigger than the passenger name.

   font-size-adjust matches x-heights instead of nominal sizes, which is what
   the eye is comparing. 0.5 is not arbitrary: it is the body face own ex
   ratio, so the mono is asked to meet the sans rather than both meeting some
   third value. Matching cap-height instead would land within 0.1px of the
   same result. Unsupported browsers ignore it and get todays rendering.
   Scoped to .dl on purpose — a table column that is entirely mono has
   nothing to disagree with and should keep its full size. */
.dl dd.u-num, .dl dd .u-num { font-size-adjust: 0.5; }

/* ---- stop timeline --------------------------------------------------- */
.stops { list-style: none; margin: 0; padding: 0; }
.stops__item {
  display: grid;
  grid-template-columns: 62px 18px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: start;
  padding-bottom: var(--s-4);
}
.stops__item:last-child { padding-bottom: 0; }
.stops__time { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--t-xs); color: var(--ink-2); padding-top: 1px; }
.stops__rail { position: relative; display: flex; justify-content: center; padding-top: 4px; }
.stops__rail::before {
  content: "";
  position: absolute;
  top: 12px; bottom: -20px;
  width: 1px;
  background: var(--rule-strong);
}
.stops__item:last-child .stops__rail::before { display: none; }
.stops__node { width: 9px; height: 9px; border-radius: 50%; background: var(--surface); border: 2px solid var(--rule-strong); position: relative; z-index: 1; }
.stops__item--on .stops__node { background: var(--brand-2); border-color: var(--brand-2); }
.stops__name { font-size: var(--t-sm); }
.stops__addr { font-size: var(--t-xs); color: var(--ink-3); }

/* ---- radio cards ----------------------------------------------------- */
.pick { display: flex; flex-direction: column; gap: var(--s-2); }
.pick__opt {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.pick__opt:hover { border-color: var(--ink-3); }
.pick__opt:has(input:checked) { border-color: var(--brand-2); background: var(--brand-2-wash); }
.pick__opt input {
  appearance: none;
  width: 17px; height: 17px;
  margin-top: 2px;
  flex-shrink: 0;
  border: 1.5px solid var(--rule-strong);
  border-radius: 50%;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.pick__opt input:checked { border-color: var(--brand-2); border-width: 5px; }
/* Several can be ticked (seats to cancel): a square box with a tick, not a
   round "pick one" dot. */
.pick__opt input[type="checkbox"] { border-radius: 5px; }
.pick__opt input[type="checkbox"]:checked {
  border-width: 1.5px; background: var(--brand-2)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")
    center / 13px no-repeat;
}

/* A stop this trip has no fare rule to, given the boarding point chosen —
   left visible but plainly unselectable, so the route still reads as the
   whole journey it is while only the legs the operator has actually priced
   can be bought. See trip_detail.html's syncDroppingOptions(). */
.pick__opt--off {
  opacity: 0.45;
  cursor: not-allowed;
  border-style: dashed;
}
.pick__opt--off:hover { border-color: var(--rule); }
.pick__opt--off input { cursor: not-allowed; }
.pick__label { font-size: var(--t-sm); font-weight: 500; }
.pick__meta { font-size: var(--t-xs); color: var(--ink-3); }

/* ---- promo ----------------------------------------------------------- */
.promo { display: flex; gap: var(--s-2); }
.promo .input { font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; }
.promo__applied {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border: 1px dashed color-mix(in srgb, var(--positive) 45%, transparent);
  border-radius: var(--r-md);
  background: var(--positive-wash);
  color: var(--positive);
  font-size: var(--t-sm);
}
.promo__code { font-family: var(--font-mono); font-weight: 600; letter-spacing: 0.06em; }
.promo__drop { margin-left: auto; background: none; border: 0; color: inherit; cursor: pointer; display: grid; place-items: center; padding: 4px; }

/* ---- rating widget --------------------------------------------------- */
.stars { display: inline-flex; flex-direction: row-reverse; justify-content: flex-end; gap: 3px; }
.stars input { position: absolute; opacity: 0; pointer-events: none; }
.stars label { cursor: pointer; color: var(--rule-strong); padding: 3px; transition: color var(--dur-fast) var(--ease); }
.stars label .ico { width: 26px; height: 26px; }
/* Reverse-order flex + sibling selector: hovering or checking a star also
   lights every star before it, which is the only behaviour anyone expects
   from a star rating and is otherwise a scripting problem. */
.stars input:checked ~ label,
.stars label:hover,
.stars label:hover ~ label { color: var(--caution); }
.stars input:focus-visible + label { outline: 2px solid var(--brand-2); outline-offset: 2px; border-radius: var(--r-sm); }

/* ---- notes / callouts ------------------------------------------------ */
.note {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  font-size: var(--t-sm);
  background: var(--surface-sunken);
  color: var(--ink-2);
  border: 1px solid var(--rule);
}
.note--info { background: var(--info-wash); border-color: color-mix(in srgb, var(--info) 25%, transparent); color: var(--info); }
.note--caution { background: var(--caution-wash); border-color: color-mix(in srgb, var(--caution) 25%, transparent); color: var(--caution); }
.note--critical { background: var(--critical-wash); border-color: color-mix(in srgb, var(--critical) 25%, transparent); color: var(--critical); }
.note .ico { margin-top: 1px; }

/* ---- policy list ----------------------------------------------------- */
.policy { display: flex; flex-direction: column; gap: var(--s-2); }
.policy__row { display: flex; align-items: center; gap: var(--s-3); font-size: var(--t-sm); }
.policy__row .ico { color: var(--ink-3); }
.policy__val { margin-left: auto; font-weight: 600; font-size: var(--t-xs); }

/* ---- Bengali script adjustments ---------------------------------------
   The rest of the Latin-tracking fixes live in tokens.css (--track-label
   and the heading rules, shared by both surfaces). These four are hardcoded
   per-component rather than routed through that token, and all four can
   carry translated or tenant-entered Bengali text (a badge word, a route or
   terminal name, the brand mark, the "Direct"/duration label on the
   journey connector), so they get the same reset here. */
:lang(bn) .site-brand,
:lang(bn) .badge,
:lang(bn) .dep__route-name,
:lang(bn) .leg__span-label {
  letter-spacing: normal;
}

/* ---- print ----------------------------------------------------------- */
@media print {
  .site-header,
  .site-footer,
  .messages,
  .btn,
  .no-print { display: none !important; }
  body { background: #fff; }
  .site-main { padding: 0; max-width: none; }
  .ticket, .panel { border-color: #999; box-shadow: none; break-inside: avoid; }
  /* Paper is not a viewport. A4's printable width is around 6.5in — under
     the 700px the card is capped to on screen, and under the 760px the
     paired layout needs — and whether a print media query is measured
     against the sheet or the printable box varies by browser. Rather than
     depend on that, print always gets the single-pair card at whatever
     width the page box allows: the layout that was proven on paper before
     the screen one widened, and one that cannot overflow the sheet. */
  .ticket { max-width: 100%; }
  .ticket .dl { grid-template-columns: auto minmax(0, 1fr); }
}

/* ---- dashboard-language additions -------------------------------------
   The same indicator-light + bar vocabulary the staff dashboard uses,
   applied to what a passenger acts on: what their search came to, and how
   full each bus is. Colour never carries meaning alone — every light sits
   beside its words and number. */
.lamp { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }

.search-summary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1px;
  margin: 0; background: var(--rule); border-bottom: 1px solid var(--rule);
}
.search-summary__item { margin: 0; padding: var(--s-3) var(--s-4); background: var(--surface); }
.search-summary dt {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: var(--t-2xs); font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-3);
}
.search-summary__item:nth-child(1) dt { color: var(--positive); }
.search-summary__item:nth-child(2) dt { color: var(--info); }
.search-summary__item:nth-child(3) dt { color: var(--brand-2); }
.search-summary dd {
  margin: 2px 0 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--t-lg); font-weight: 600; color: var(--ink);
}
.search-summary dd small { font-size: var(--t-2xs); font-weight: 500; color: var(--ink-3); }

.avail { display: inline-flex; align-items: center; gap: 6px; }
.avail__bar { width: 54px; height: 5px; border-radius: 3px; background: var(--surface-sunken); overflow: hidden; }
.avail__bar > span { display: block; height: 100%; border-radius: inherit; background: currentColor; }
.avail--plenty { color: var(--positive); }
.avail--filling { color: var(--info); }
.avail--few { color: var(--caution); }
.avail--full { color: var(--critical); }
.avail .u-num { color: var(--ink-2); }
.avail--few .u-num, .avail--full .u-num { color: inherit; font-weight: 600; }
.avail__note { font-size: var(--t-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track-label); }

/* "Your journey" on the trip page: the route as a line diagram. The chosen
   boarding/dropping stops get a filled node and a label; the stretch the
   passenger rides is drawn in the route's colour at full strength, the rest
   faded. */
.journey { list-style: none; margin: 0; padding: 0; }
.journey__stop {
  display: grid; grid-template-columns: 18px 52px 1fr auto; align-items: center; gap: var(--s-3);
  min-height: 44px;
}
.journey__rail { position: relative; align-self: stretch; }
.journey__rail::before {
  content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 3px; transform: translateX(-50%);
  background: color-mix(in srgb, var(--line, var(--brand-2)) 30%, transparent); border-radius: 2px;
}
.journey__stop.is-first .journey__rail::before { top: 50%; }
.journey__stop.is-last .journey__rail::before { bottom: 50%; }
.journey__stop.is-ride .journey__rail::before { background: var(--line, var(--brand-2)); }
.journey__stop.is-off .journey__rail::before { background: linear-gradient(var(--line, var(--brand-2)) 50%, color-mix(in srgb, var(--line, var(--brand-2)) 30%, transparent) 50%); }
.journey__node {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 11px; height: 11px; border-radius: 50%; box-sizing: border-box;
  background: var(--surface); border: 3px solid color-mix(in srgb, var(--line, var(--brand-2)) 55%, transparent);
}
.journey__stop.is-on .journey__node, .journey__stop.is-off .journey__node {
  width: 16px; height: 16px; background: var(--line, var(--brand-2)); border-color: var(--surface);
  box-shadow: 0 0 0 3px var(--line, var(--brand-2));
}
.journey__time { font-size: var(--t-sm); color: var(--ink-3); }
.journey__name { font-weight: 500; color: var(--ink-2); }
.journey__stop.is-on .journey__name, .journey__stop.is-off .journey__name,
.journey__stop.is-ride .journey__name { color: var(--ink); }
.journey__stop.is-on .journey__time, .journey__stop.is-off .journey__time { color: var(--ink); font-weight: 600; }
.journey__you, .journey__tag {
  font-size: var(--t-2xs); font-weight: 600; letter-spacing: var(--track-label); text-transform: uppercase;
  padding: 2px 8px; border-radius: var(--r-pill);
}
.journey__you { display: none; background: var(--line, var(--brand-2)); color: #fff; }
.journey__stop.is-on .journey__you--on, .journey__stop.is-off .journey__you--off { display: inline-block; }
.journey__tag { color: var(--ink-3); border: 1px dashed var(--rule-strong); }

/* Ticket page: when the bus goes. */
.leaves { display: inline-flex; align-items: center; gap: 8px; margin: var(--s-2) 0 0; font-weight: 600; font-size: var(--t-sm); }
.leaves--soon { color: var(--caution); }
.leaves--later { color: var(--positive); }
.leaves--gone { color: var(--ink-3); }
.leaves--soon .lamp { box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 22%, transparent); }

/* ---- ticket page: before you go ------------------------------------- */
.extras { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s-3); }
.extra {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
}
.extra--link { transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.extra--link:hover { text-decoration: none; border-color: var(--brand-2); box-shadow: var(--shadow-2); }
.extra .ico-tile--lg { width: 42px; height: 42px; flex: none; }
.extra .ico-tile--lg .ico { width: 21px; height: 21px; }
.extra__text { display: grid; gap: 3px; min-width: 0; }
.extra__text strong { color: var(--ink); }
.extra__text > span { font-size: var(--t-xs); color: var(--ink-3); }
.extra__links { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; font-size: var(--t-sm) !important; font-weight: 600; }
.stops__dir { display: inline-flex; align-items: center; gap: 4px; margin-top: 4px; font-size: var(--t-xs); font-weight: 600; }
.remember { margin-top: var(--s-4); padding: 0; }
.remember[hidden] { display: none; }

/* ---- colourful icons ---------------------------------------------------
   Each kind of thing has its own colour, everywhere it appears: seats
   violet, the passenger teal, the route orange, places red, tickets blue,
   money and phones green, dates indigo, ratings gold — and each amenity its
   own (AC sky, WiFi violet, charging amber…). One map, keyed on the icon
   drawn, so every page picks it up without template changes. Applied to
   icon tiles, field and label icons, filter options and amenity tiles —
   never to buttons or links, which keep their own colour. Dark theme takes
   a lighter mix of the same colour. */
:root {
  --tone-blue: #1c7ed6;
  --tone-violet: #7048e8;
  --tone-teal: #0c8599;
  --tone-green: #2b8a3e;
  --tone-orange: #e8590c;
  --tone-red: #e03131;
  --tone-pink: #c2255c;
  --tone-amber: #e67700;
  --tone-indigo: #4263eb;
  --tone-cyan: #1098ad;
  --tone-grape: #9c36b5;
  --tone-gold: #f08c00;
  --tone-slate: #5c6b7a;
}
svg.ico:has(> use[href="#icon-seat"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-seat"]) { --tone: var(--tone-violet); }
svg.ico:has(> use[href="#icon-user"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-user"]) { --tone: var(--tone-teal); }
svg.ico:has(> use[href="#icon-users"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-users"]) { --tone: var(--tone-teal); }
svg.ico:has(> use[href="#icon-route"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-route"]) { --tone: var(--tone-orange); }
svg.ico:has(> use[href="#icon-pin"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-pin"]) { --tone: var(--tone-red); }
svg.ico:has(> use[href="#icon-flag"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-flag"]) { --tone: var(--tone-pink); }
svg.ico:has(> use[href="#icon-ticket"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-ticket"]) { --tone: var(--tone-blue); }
svg.ico:has(> use[href="#icon-tag"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-tag"]) { --tone: var(--tone-amber); }
svg.ico:has(> use[href="#icon-info"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-info"]) { --tone: var(--tone-cyan); }
svg.ico:has(> use[href="#icon-money"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-money"]) { --tone: var(--tone-green); }
svg.ico:has(> use[href="#icon-star"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-star"]) { --tone: var(--tone-gold); }
svg.ico:has(> use[href="#icon-calendar"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-calendar"]) { --tone: var(--tone-indigo); }
svg.ico:has(> use[href="#icon-clock"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-clock"]) { --tone: var(--tone-cyan); }
svg.ico:has(> use[href="#icon-card"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-card"]) { --tone: var(--tone-grape); }
svg.ico:has(> use[href="#icon-list"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-list"]) { --tone: var(--tone-slate); }
svg.ico:has(> use[href="#icon-filter"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-filter"]) { --tone: var(--tone-grape); }
svg.ico:has(> use[href="#icon-phone"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-phone"]) { --tone: var(--tone-green); }
svg.ico:has(> use[href="#icon-mail"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-mail"]) { --tone: var(--tone-orange); }
svg.ico:has(> use[href="#icon-refresh"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-refresh"]) { --tone: var(--tone-teal); }
svg.ico:has(> use[href="#icon-bus"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-bus"]) { --tone: var(--tone-orange); }
svg.ico:has(> use[href="#icon-check"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-check"]) { --tone: var(--tone-green); }
svg.ico:has(> use[href="#icon-edit"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-edit"]) { --tone: var(--tone-amber); }
svg.ico:has(> use[href="#icon-lock"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-lock"]) { --tone: var(--tone-grape); }
svg.ico:has(> use[href="#icon-sunrise"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-sunrise"]) { --tone: var(--tone-orange); }
svg.ico:has(> use[href="#icon-sun"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-sun"]) { --tone: var(--tone-gold); }
svg.ico:has(> use[href="#icon-sunset"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-sunset"]) { --tone: var(--tone-pink); }
svg.ico:has(> use[href="#icon-moon"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-moon"]) { --tone: var(--tone-indigo); }
svg.ico:has(> use[href="#icon-search"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-search"]) { --tone: var(--tone-blue); }
svg.ico:has(> use[href="#icon-home"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-home"]) { --tone: var(--tone-blue); }
svg.ico:has(> use[href="#icon-shield"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-shield"]) { --tone: var(--tone-green); }
svg.ico:has(> use[href="#icon-wrench"]), :is(.ico-tile, .amenities > span):has(use[href="#icon-wrench"]) { --tone: var(--tone-slate); }
svg.ico:has(> use[href="#amenity-ac"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-ac"]) { --tone: var(--tone-blue); }
svg.ico:has(> use[href="#amenity-wifi"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-wifi"]) { --tone: var(--tone-violet); }
svg.ico:has(> use[href="#amenity-usb"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-usb"]) { --tone: var(--tone-amber); }
svg.ico:has(> use[href="#amenity-blanket"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-blanket"]) { --tone: var(--tone-pink); }
svg.ico:has(> use[href="#amenity-water"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-water"]) { --tone: var(--tone-cyan); }
svg.ico:has(> use[href="#amenity-meals"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-meals"]) { --tone: var(--tone-orange); }
svg.ico:has(> use[href="#amenity-toilet"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-toilet"]) { --tone: var(--tone-teal); }
svg.ico:has(> use[href="#amenity-entertainment"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-entertainment"]) { --tone: var(--tone-grape); }
svg.ico:has(> use[href="#amenity-light"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-light"]) { --tone: var(--tone-gold); }
svg.ico:has(> use[href="#amenity-gps"]), :is(.ico-tile, .amenities > span):has(use[href="#amenity-gps"]) { --tone: var(--tone-green); }

.ico-tile,
.amenities > span {
  background: color-mix(in srgb, var(--tone, var(--brand-2)) 13%, var(--surface));
  color: light-dark(var(--tone, var(--brand-2)), color-mix(in oklab, var(--tone, var(--brand-2)) 62%, white));
}
.amenities > span:hover {
  background: color-mix(in srgb, var(--tone, var(--brand-2)) 22%, var(--surface));
  color: light-dark(var(--tone, var(--brand-2)), color-mix(in oklab, var(--tone, var(--brand-2)) 62%, white));
}
:root[data-theme="dark"] .ico-tile, :root[data-theme="dark"] .amenities > span {
  background: color-mix(in srgb, var(--tone, var(--brand-2)) 24%, var(--surface));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ico-tile, :root:not([data-theme="light"]) .amenities > span {
    background: color-mix(in srgb, var(--tone, var(--brand-2)) 24%, var(--surface));
  }
}
.ico--label,
.field-ico__i,
.check .ico,
.dep__coach .ico,
.site-footer__item .ico,
.stops__dir .ico {
  color: light-dark(var(--tone, currentColor), color-mix(in oklab, var(--tone, currentColor) 62%, white));
}
.check:has(input:checked) .ico { color: light-dark(var(--tone, var(--brand-2)), color-mix(in oklab, var(--tone, var(--brand-2)) 62%, white)); }
/* Filter group titles draw their icon as a small tile. */
.rail__group-title .ico--label {
  background: color-mix(in srgb, var(--tone, var(--brand-2)) 13%, var(--surface));
  color: light-dark(var(--tone, var(--brand-2)), color-mix(in oklab, var(--tone, var(--brand-2)) 62%, white));
}
/* On the company band (dark in both themes), a light mix of each colour. */
.opband__comfort .ico { color: color-mix(in oklab, var(--tone, #ffffff) 45%, white); }
/* WhatsApp's own green (its icon is drawn inline, outside the icon map). */
.ico-tile.extra__wa { --tone: #1f9d55; }

/* ---- company pages: help, terms, privacy (storefront/page.html) ------ */
.page-tabs { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }
.page-tabs a {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong); background: var(--surface);
  color: var(--ink-2); font-size: var(--t-sm); font-weight: 600; text-decoration: none;
}
.page-tabs a:hover { border-color: var(--brand-2); color: var(--ink); text-decoration: none; }
.page-tabs a[aria-current="page"] { background: var(--brand-2-wash); border-color: var(--brand-2); color: var(--ink); }
.contacts { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s-3); }
.contact {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-4); border: 1px solid var(--rule); border-radius: var(--r-md);
  background: var(--surface); color: inherit; text-decoration: none;
}
.contact > span:last-child { display: grid; gap: 2px; font-size: var(--t-sm); color: var(--ink-2); min-width: 0; }
.contact strong { color: var(--ink); font-size: var(--t-base); }
.contact .ico-tile--lg { width: 42px; height: 42px; flex: none; }
.contact .ico-tile--lg .ico { width: 21px; height: 21px; }
a.contact--main:hover { border-color: var(--brand-2); box-shadow: var(--shadow-2); text-decoration: none; }
.contact--main .u-num { font-size: var(--t-lg); font-weight: 700; color: var(--ink); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  cursor: pointer; list-style: none; padding: var(--s-4) 0;
  font-weight: 600; display: flex; justify-content: space-between; gap: var(--s-3);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font-family: var(--font-mono); color: var(--ink-3); font-size: var(--t-lg); line-height: 1; }
.faq details[open] summary::after { content: "–"; }
.faq details > :not(summary) { margin: 0 0 var(--s-4); color: var(--ink-2); }
.prose h3 { font-size: var(--t-md); margin: var(--s-5) 0 var(--s-2); }
.prose h3:first-child { margin-top: 0; }
.prose h4 { font-size: var(--t-base); margin: var(--s-4) 0 var(--s-2); }
.prose p, .prose ul { color: var(--ink-2); margin: 0 0 var(--s-3); max-width: 70ch; }
.prose ul { padding-left: 1.2em; }
.site-footer__links { display: inline-flex; flex-wrap: wrap; gap: var(--s-3); }
.agree { margin: var(--s-3) 0 0; font-size: var(--t-xs); color: var(--ink-3); text-align: center; }

/* ---- ticket page: your trip right now (storefront/_trip_live.html) --- */
.live { border-color: color-mix(in srgb, var(--brand-2) 35%, var(--rule)); }
.live__badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 99px;
  background: var(--positive-wash); color: var(--positive); font-size: var(--t-2xs); font-weight: 700;
  letter-spacing: var(--track-label); text-transform: uppercase;
}
.live__badge[hidden] { display: none; }
.live__badge .lamp { animation: live-pulse 1.6s ease-in-out infinite; }
@keyframes live-pulse { 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .live__badge .lamp { animation: none; } }
.live-steps { list-style: none; margin: 0 0 var(--s-4); padding: 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.live-steps li {
  position: relative; padding-top: 14px; font-size: var(--t-xs); font-weight: 600; color: var(--ink-3); text-align: center;
}
.live-steps li::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 6px; border-radius: 99px; background: var(--surface-sunken);
}
.live-steps li.is-done::before { background: var(--positive); }
.live-steps li.is-done { color: var(--ink-2); }
.live-steps li.is-now::before { background: linear-gradient(90deg, var(--positive), var(--brand-2)); }
.live-steps li.is-now { color: var(--ink); }
.live-steps [hidden] { display: none; }
.live__line { font-size: var(--t-md); font-weight: 600; color: var(--ink); margin: 0 0 var(--s-4); }
.live--cancelled .live__line { color: var(--critical); }
.live--arrived .live__line { color: var(--positive); }
.live__facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--s-3); }
.live__fact { display: grid; gap: 3px; padding: var(--s-3) var(--s-4); border-radius: var(--r-md); background: var(--surface-sunken); }
.live__fact strong { color: var(--ink); }
.live__fact .u-num { font-family: var(--font-mono); font-size: var(--t-lg); font-weight: 700; color: var(--ink); }
.live__fact s { font-size: .65em; color: var(--ink-3); font-weight: 500; }
.live__fact--eta { background: color-mix(in srgb, var(--brand-2) 10%, var(--surface)); }
.live__fact--eta[hidden] { display: none; }
.live__bay { justify-self: start; padding: 2px 8px; border-radius: var(--r-sm); background: var(--ink); color: var(--paper); font-family: var(--font-mono); font-size: var(--t-xs); font-weight: 700; }
.live__map { height: 260px; margin-top: var(--s-4); border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--rule); }
.live__map[hidden], #live-bus-note[hidden] { display: none; }


/* ---- flash messages (every storefront page) ------------------------- */
.flash-stack { display: grid; gap: var(--s-3); margin-bottom: var(--s-5); }
.note--positive { background: var(--positive-wash); border-color: color-mix(in srgb, var(--positive) 25%, transparent); color: var(--positive); }

/* ---- passenger account: sign-in and "My trips" (account_views) ------ */
.acct-code { font-size: var(--t-2xl); letter-spacing: 0.4em; text-align: center; }
.acct-alt { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-3); margin-top: var(--s-4); }

.acct-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4); margin-bottom: var(--s-6); }
.acct-head__who { display: flex; align-items: center; gap: var(--s-4); min-width: 0; }
.acct-head h1 { margin: 0 0 2px; }
.acct-head__meta { margin: 0; color: var(--ink-3); font-size: var(--t-sm); display: flex; flex-wrap: wrap; gap: 0 6px; }
.acct-head__actions { display: flex; gap: var(--s-2); align-items: center; }
.acct-avatar {
  width: 56px; height: 56px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand-2); color: var(--brand-2-ink);
  font-family: var(--font-display); font-size: var(--t-xl); font-weight: 600;
}

.acct-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s-6); align-items: start; }
.acct-side { display: grid; gap: var(--s-4); }
.acct-side .panel__head h2 { font-size: var(--t-base); display: flex; align-items: center; gap: 8px; margin: 0; }
@media (max-width: 960px) { .acct-grid { grid-template-columns: minmax(0, 1fr); } }

.acct-section { margin-bottom: var(--s-7); }
.acct-section h2 { font-size: var(--t-lg); display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-3); }
.acct-count {
  font-family: var(--font-mono); font-size: var(--t-xs); font-weight: 600;
  min-width: 24px; height: 22px; padding: 0 7px; border-radius: var(--r-pill);
  display: inline-grid; place-items: center; background: var(--surface-sunken); color: var(--ink-2);
}

/* An upcoming trip as a ticket: date block, journey, stub with a punched edge. */
.acct-ticket {
  display: grid; grid-template-columns: 76px minmax(0, 1fr) auto; align-items: stretch;
  margin-bottom: var(--s-3); border: 1px solid var(--rule); border-radius: var(--r-lg);
  background: var(--surface); color: inherit; text-decoration: none; overflow: hidden;
  box-shadow: var(--shadow-1); transition: box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.acct-ticket:hover { text-decoration: none; box-shadow: var(--shadow-2); transform: translateY(-1px); }
.acct-ticket__date {
  display: grid; place-content: center; text-align: center; gap: 1px; padding: var(--s-3);
  background: var(--brand); color: #fff;
}
.acct-ticket__day { font-size: var(--t-2xl); font-weight: 700; line-height: 1; }
.acct-ticket__mon { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--track-label); font-weight: 600; }
.acct-ticket__dow { font-size: var(--t-2xs); opacity: 0.8; }
.acct-ticket__body { padding: var(--s-4); display: grid; gap: var(--s-2); align-content: center; min-width: 0; }
.acct-ticket__route { font-family: var(--font-display); font-size: var(--t-lg); font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.acct-ticket__facts { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); color: var(--ink-2); font-size: var(--t-sm); }
.acct-ticket__facts > span { display: inline-flex; align-items: center; gap: 5px; }
.acct-ticket__stub {
  position: relative; display: grid; align-content: center; justify-items: end; gap: 4px;
  padding: var(--s-4) var(--s-5); border-left: 2px dashed var(--rule); background: var(--surface-sunken);
  font-size: var(--t-sm);
}
.acct-ticket__stub::before, .acct-ticket__stub::after {
  content: ""; position: absolute; left: -9px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--paper); border: 1px solid var(--rule);
}
.acct-ticket__stub::before { top: -9px; }
.acct-ticket__stub::after { bottom: -9px; }
@media (max-width: 560px) {
  .acct-ticket { grid-template-columns: 64px minmax(0, 1fr); }
  .acct-ticket__stub { grid-column: 1 / -1; border-left: 0; border-top: 2px dashed var(--rule); justify-items: start;
                       grid-template-columns: auto auto 1fr; align-items: center; gap: var(--s-2); padding: var(--s-3) var(--s-4); }
  .acct-ticket__stub::before, .acct-ticket__stub::after { display: none; }
  .acct-ticket__stub .acct-pill { justify-self: end; }
}

.acct-pill { display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: var(--r-pill); font-size: var(--t-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.acct-pill--ok { background: var(--positive-wash); color: var(--positive); }
.acct-pill--go { background: var(--info-wash); color: var(--info); }
.acct-pill--warn { background: var(--caution-wash); color: var(--caution); }

.acct-empty { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-5); border: 1px dashed var(--rule-strong); border-radius: var(--r-lg); color: var(--ink-3); }
.acct-empty p { margin: 0; }

.acct-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--rule); border-radius: var(--r-lg); background: var(--surface); overflow: hidden; }
.acct-list li + li { border-top: 1px solid var(--rule); }
.acct-list a { display: grid; grid-template-columns: 110px minmax(0, 1fr) auto; gap: var(--s-3); align-items: center; padding: var(--s-3) var(--s-4); color: inherit; text-decoration: none; }
.acct-list a:hover { background: var(--surface-hover); text-decoration: none; }
.acct-list__when { color: var(--ink-3); font-size: var(--t-sm); }
.acct-list__what { font-weight: 600; min-width: 0; }
.acct-list__sub { display: block; font-weight: 400; color: var(--ink-3); font-size: var(--t-xs); }
.acct-list__end { display: inline-flex; align-items: center; gap: 4px; color: var(--brand); font-size: var(--t-sm); font-weight: 600; }
.acct-list--muted .acct-list__what { color: var(--ink-2); }
@media (max-width: 560px) { .acct-list a { grid-template-columns: minmax(0, 1fr) auto; } .acct-list__when { grid-column: 1 / -1; } }

.acct-person, .acct-notice { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) 0; }
.acct-person + .acct-person, .acct-notice + .acct-notice { border-top: 1px solid var(--rule); }
.acct-person__init { width: 32px; height: 32px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--info-wash); color: var(--info); font-weight: 700; font-size: var(--t-sm); }
.acct-person__who { min-width: 0; font-weight: 600; font-size: var(--t-sm); }
.acct-notice { justify-content: space-between; font-size: var(--t-sm); }
.acct-notice__what { font-weight: 600; min-width: 0; }
.acct-notice__when { color: var(--ink-3); font-size: var(--t-xs); white-space: nowrap; }
.acct-notice.is-failed .acct-notice__what { color: var(--critical); }
