/* ===== RailAlertBD design tokens — Material Design 3 =====
   Colors extracted directly from the real logo (frequency-analyzed from
   its 580 shapes): a dark bottle-green family, a muted sage secondary,
   and a maroon-red tertiary — not an invented palette. */

:root {
  --md-primary: #38604C;
  --md-on-primary: #FFFFFF;
  --md-primary-container: #BFD0C7;
  --md-on-primary-container: #0B2318;

  --md-secondary: #4C6358;
  --md-on-secondary: #FFFFFF;
  --md-secondary-container: #D3E4DA;
  --md-on-secondary-container: #0E1F16;

  --md-tertiary: #863238;
  --md-on-tertiary: #FFFFFF;
  --md-tertiary-container: #FFDAD9;
  --md-on-tertiary-container: #410007;

  --md-error: #BA1A1A;
  --md-on-error: #FFFFFF;
  --md-error-container: #FFDAD6;
  --md-on-error-container: #410002;

  --md-background: #F7FAF7;
  --md-on-background: #181D1A;
  --md-surface: #F7FAF7;
  --md-on-surface: #181D1A;
  --md-surface-variant: #DDE5DE;
  --md-on-surface-variant: #414942;
  --md-outline: #717972;
  --md-outline-variant: #C0C9C1;

  --md-corner-small: 8px;
  --md-corner-medium: 12px;
  --md-corner-large: 16px;
  --md-corner-full: 9999px;

  --md-elevation-1: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.08);
  --md-elevation-2: 0 4px 12px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.08);

  --md-font: 'Plus Jakarta Sans', system-ui, sans-serif;
  --md-font-display: 'Fraunces', Georgia, serif;
  --md-motion: 200ms cubic-bezier(0.2, 0, 0, 1);
}

[data-theme="dark"] {
  --md-primary: #9DD0B6;
  --md-on-primary: #05391F;
  --md-primary-container: #1E4B37;
  --md-on-primary-container: #BBEFCE;

  --md-secondary: #B2CCBE;
  --md-on-secondary: #1E352A;
  --md-secondary-container: #364B40;
  --md-on-secondary-container: #CFE9DA;

  --md-tertiary: #FFB3AE;
  --md-on-tertiary: #5D131A;
  --md-tertiary-container: #7D2930;
  --md-on-tertiary-container: #FFDAD9;

  --md-error: #FFB4AB;
  --md-on-error: #690005;
  --md-error-container: #93000A;
  --md-on-error-container: #FFDAD6;

  --md-background: #10140F;
  --md-on-background: #DEE4DD;
  --md-surface: #10140F;
  --md-on-surface: #DEE4DD;
  --md-surface-variant: #414942;
  --md-on-surface-variant: #C0C9C1;
  --md-outline: #8B938C;
  --md-outline-variant: #414942;

  --md-elevation-1: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
  --md-elevation-2: 0 4px 12px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--md-font);
  background: var(--md-background);
  color: var(--md-on-background);
  transition: background-color var(--md-motion), color var(--md-motion);
}

a { color: inherit; }

/* Bengali script: neither Plus Jakarta Sans nor Fraunces cover it, so both
   fall back to Noto Sans Bengali specifically when the page is in Bangla.
   Bengali also reads better with a taller line-height and without forcing
   the heavier weights Latin headlines use, so those get relaxed too. */
html[lang="bn"] body {
  font-family: 'Noto Sans Bengali', 'Plus Jakarta Sans', sans-serif;
  line-height: 1.7;
}
html[lang="bn"] .display-small,
html[lang="bn"] .headline-large,
html[lang="bn"] .headline-medium,
html[lang="bn"] .headline-small {
  font-family: 'Noto Sans Bengali', sans-serif;
  font-weight: 500;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* Type scale */
.display-small    { font-family: var(--md-font-display); font-size: 2.75rem; line-height: 3.25rem; font-weight: 500; margin: 0; letter-spacing: -0.5px; }
.headline-large   { font-family: var(--md-font-display); font-size: 2.25rem; line-height: 2.75rem; font-weight: 500; margin: 0; }
.headline-medium  { font-family: var(--md-font-display); font-size: 1.875rem; line-height: 2.25rem; font-weight: 500; margin: 0; }
.headline-small   { font-family: var(--md-font-display); font-size: 1.5rem;  line-height: 2rem;    font-weight: 500; margin: 0; }
.title-large      { font-size: 1.375rem; line-height: 1.75rem; font-weight: 400; margin: 0; }
.title-medium     { font-size: 1rem;    line-height: 1.5rem;  font-weight: 500; letter-spacing: 0.15px; margin: 0; }
.body-large       { font-size: 1.0625rem; line-height: 1.625rem; font-weight: 400; letter-spacing: 0.15px; }
.body-medium      { font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; letter-spacing: 0.25px; }
.label-large      { font-size: 0.875rem; line-height: 1.25rem; font-weight: 500; letter-spacing: 0.1px; }

/* Self-hosted subset (~265KB) containing only the ~40 icons this site
   actually uses, instead of requesting Google's full variable-axis family
   on every visit. font-display: block means the browser reserves space
   and waits briefly rather than ever painting the raw fallback text
   ("menu", "search"...) — and because this file is tiny, same-origin, and
   preloaded in base.html's <head>, that wait is imperceptible in practice.
   No JS readiness-gating needed for this anymore. */
@font-face {
  font-family: 'Material Symbols Outlined';
  src: url('fonts/material-symbols-subset.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-weight: 400;
  font-style: normal;
  vertical-align: middle;
  line-height: 1;
}

/* Top app bar */
.top-app-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  height: 64px;
  background: var(--md-surface);
  border-bottom: 1px solid var(--md-outline-variant);
  position: sticky;
  top: 0;
  z-index: 10;
}
.brand-group { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.brand-group img { height: 32px; width: 32px; }
.brand-group span { font-family: var(--md-font-display); font-size: 1.375rem; font-weight: 600; color: var(--md-on-surface); }

.nav-right { display: flex; align-items: center; gap: 4px; position: relative; }

.nav-links { display: flex; gap: 4px; align-items: center; }
.nav-links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--md-on-surface-variant);
  text-decoration: none;
  padding: 8px 14px;
  border-radius: var(--md-corner-full);
  font-size: 0.875rem;
  font-weight: 500;
  transition: background-color var(--md-motion), color var(--md-motion);
}
.nav-links a:hover { background: var(--md-surface-variant); color: var(--md-on-surface); }
.nav-links a.nav-cta { background: var(--md-primary); color: var(--md-on-primary); }
.nav-links a.nav-cta:hover { filter: brightness(1.1); }

/* Dims the page behind the open mobile menu and doubles as a
   tap-outside-to-close target. z-index: 9 keeps it just below
   .top-app-bar's own stacking context (z-index: 10), so it can
   never cover the bar or the toggle button — only ordinary
   page content underneath. */
.nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 9;
}
.nav-backdrop[hidden] {
  display: none;
}

/* Stops the page behind the drawer from scrolling while it's open. */
body.nav-open {
  overflow: hidden;
}

button.nav-toggle { display: none; }

@media (max-width: 860px) {
  button.nav-toggle {
    display: flex;
    /* .nav-links.open has z-index: 30, but as a descendant of .top-app-bar it's
       scoped *inside* that element's own stacking context (position: sticky +
       z-index: 10 makes .top-app-bar one). The toggle button lived in that same
       context with no z-index of its own, so the open panel painted directly
       over the button meant to close it. A higher z-index *within that same
       context* is enough to fix it — no need to touch the panel's z-index. */
    position: relative;
    z-index: 31;
  }

  /* Anchored dropdown, not a forced-height full-screen takeover: height comes
     entirely from content (2 links vs 6 look different), capped by max-height
     with scroll as a safety net for very short viewports. */
  .nav-links {
    position: fixed;
    top: 64px;
    left: 0;
    right: 0;
    max-height: calc(100vh - 64px);
    overflow-y: auto;
    background: var(--md-surface);
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 12px 12px 16px;
    border-bottom: 1px solid var(--md-outline-variant);
    border-radius: 0 0 var(--md-corner-large) var(--md-corner-large);
    box-shadow: var(--md-elevation-2);
    transform: translateY(-12px);
    opacity: 0;
    pointer-events: none;
    transition: transform 220ms cubic-bezier(0.2, 0, 0, 1), opacity 180ms ease;
    z-index: 30;
  }

  /* Glass surface where supported; the solid var(--md-surface) above is the
     fallback everywhere else, so this is a pure progressive enhancement. */
  @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .nav-links {
      background: color-mix(in srgb, var(--md-surface) 86%, transparent);
      -webkit-backdrop-filter: blur(20px) saturate(160%);
      backdrop-filter: blur(20px) saturate(160%);
    }
  }

  .nav-links.open {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }

  .nav-links a {
    justify-content: flex-start;
    width: 100%;
    max-width: none;
    font-size: 1rem;
    padding: 13px 16px;
    border-radius: var(--md-corner-medium);
  }
  .nav-links a.nav-cta {
    order: -1;
    justify-content: center;
    margin-bottom: 4px;
  }
}

/* Footer */
.site-footer {
  border-top: 1px solid var(--md-outline-variant);
  margin-top: 32px;
  padding: 48px 24px 32px;
  background: var(--md-surface-variant);
}
.footer-inner {
  max-width: 1000px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 32px;
}
.footer-inner > div:not(.footer-brand) { text-align: center; }
.footer-inner h4 { font-size: 0.875rem; font-weight: 500; margin: 0 0 12px; color: var(--md-on-surface); }
.footer-inner a {
  display: block;
  color: var(--md-on-surface-variant);
  text-decoration: none;
  font-size: 0.875rem;
  padding: 4px 0;
  transition: color var(--md-motion);
}
.footer-inner a:hover { color: var(--md-primary); }
.footer-social { display: flex; gap: 8px; margin-top: 4px; }
.footer-bottom {
  max-width: 1000px;
  margin: 32px auto 0;
  padding-top: 24px;
  border-top: 1px solid var(--md-outline-variant);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 0.8125rem;
  color: var(--md-on-surface-variant);
}
@media (max-width: 700px) {
  .footer-inner { grid-template-columns: repeat(3, 1fr); }
  .footer-inner .footer-brand {
    grid-column: 1 / -1;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 8px;
  }
  .footer-inner .footer-brand .brand-group { justify-content: center; }
  .footer-inner .footer-brand .footer-social { justify-content: center; }
}

@media (max-width: 780px) {
  .display-small { font-size: 2rem; line-height: 2.5rem; }
  .headline-medium { font-size: 1.5rem; line-height: 2rem; }
  main > section[style*="grid-template-columns: 1fr 1fr"] {
    grid-template-columns: 1fr !important;
  }
}

/* Rail-track divider: a persistent, quiet bit of motion between content and
   footer. Animates via animation-duration, so it's automatically stilled by
   the prefers-reduced-motion rule above — no extra handling needed. */
.rail-divider {
  position: relative;
  height: 40px;
  overflow: hidden;
  background: var(--md-surface-variant);
  border-top: 1px solid var(--md-outline-variant);
  border-bottom: 1px solid var(--md-outline-variant);
}
.rail-track {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.rail-sleeper { fill: var(--md-outline-variant); }
.rail-line { stroke: var(--md-outline); stroke-width: 2; }

.rail-train {
  position: absolute;
  top: 50%;
  left: -80px;
  width: 64px;
  height: 34px;
  transform: translateY(-50%);
  animation: rail-train-move 16s linear infinite;
}
.rail-train svg { width: 100%; height: 100%; display: block; }
.rail-train-body { fill: var(--md-primary); }
.rail-train-window { fill: var(--md-primary-container); }
.rail-train-wheel { fill: var(--md-on-surface-variant); }

@keyframes rail-train-move {
  from { left: -80px; }
  to   { left: 100%; }
}

/* Homepage "how it works" story strip: a seat leaves the train, gets
   noticed by the watching eye, and becomes a ticket that continues on to
   the mailbox. Purely decorative (aria-hidden) — the heading right below
   spells the same story out in words.
   The seat-to-ticket "transformation" is a standard CSS trick: two
   separate icons share the exact same travel keyframes, with a crossfade
   timed to happen only once both are sitting at the eye's position, so it
   reads as one object changing form rather than two objects overlapping.
   Everything here runs on animation-duration, so it's automatically
   stilled by the prefers-reduced-motion rule near the top of this file —
   under reduced motion this settles on the three static landmarks with no
   traveling icon, rather than any bespoke handling.
   .story-band exists purely so .story-strip can span the true page width
   (100vw + left:50% + -50vw margin, same trick as .rail-divider) even
   though it's nested inside <main>'s max-width — no background of its own
   anymore, just a width-escape hatch so train/mailbox can sit at the real
   page edges.
   --story-item-half/--story-seat-rest/--story-ticket-end are redefined in
   the mobile media query below rather than left as shared pixel values —
   they're derived from each icon's actual size at that breakpoint, so
   seat/ticket alignment on the train/eye/mailbox stays correct at both
   sizes instead of only working at the size they happened to be tuned for. */
.story-band {
  position: relative;
  width: 100vw;
  left: 50%;
  margin-left: -50vw;
  overflow: hidden;
}
.story-strip {
  position: relative;
  height: 56px;
  --story-item-half: 20px;
  --story-seat-rest: 39px;
  --story-ticket-end: 64px;
}
.story-train, .story-mailbox {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
.story-eye {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
/* All four landmarks now share the item's own 40px scale (mobile: 28px)
   instead of being noticeably larger than the seat/ticket traveling
   between them. */
.story-train { left: 24px; width: 70px; }
.story-eye { width: 40px; }
.story-mailbox { right: 24px; width: 40px; }
.story-train svg, .story-eye svg, .story-mailbox svg { width: 100%; height: auto; display: block; }

/* Outlined, not filled — reads as a simple line-art train. */
.story-train-body { fill: none; stroke: var(--md-primary); stroke-width: 2; }
.story-train-window { fill: none; stroke: var(--md-primary-container); stroke-width: 2; }
.story-train-wheel { fill: none; stroke: var(--md-on-surface-variant); stroke-width: 2; }
.story-train svg { transform-origin: center; animation: story-train-release 8s ease-in-out infinite; }

.story-eye-outline { fill: none; stroke: var(--md-on-surface-variant); stroke-width: 2; }
.story-eye-pupil { fill: var(--md-primary); }
.story-eye svg { transform-origin: center; animation: story-eye-pulse 8s ease-in-out infinite; }

.story-mailbox-shape { fill: none; stroke: var(--md-on-surface-variant); stroke-width: 2; }
.story-mailbox-flap { fill: none; stroke: var(--md-on-surface-variant); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.story-item {
  position: absolute;
  top: 50%;
  width: 40px;
  height: 40px;
}
.story-item svg { width: 100%; height: 100%; display: block; }

/* Green seat, maroon ticket — matches the tertiary color already used for
   confirmation_number elsewhere on this page, so the color shift itself
   reinforces "this became a booking." */
.story-seat-shape { fill: var(--md-primary); }
.story-ticket-shape { fill: var(--md-tertiary); }
.story-ticket-perf { stroke: var(--md-tertiary-container); stroke-width: 2; stroke-dasharray: 2 2; }
.story-ticket-notch { fill: var(--md-surface); }

.story-seat { animation: story-seat-travel 8s ease-in-out infinite; }
.story-ticket { animation: story-ticket-travel 8s ease-in-out infinite; }
.story-mailbox svg { transform-origin: center; animation: story-mailbox-bounce 8s ease-in-out infinite; }

/* --story-seat-rest is set to exactly match the train's own left inset
   (they're the same width now, so equal left edges means equal centers —
   the seat's center lands exactly on the train's center, not just
   "somewhere near it"). */
@keyframes story-seat-travel {
  0%   { left: var(--story-seat-rest); opacity: 0; transform: translateY(-50%) scale(0.6); }
  4%   { left: var(--story-seat-rest); opacity: 1; transform: translateY(-50%) scale(1); }
  40%  { left: calc(50% - var(--story-item-half)); opacity: 1; transform: translateY(-50%) scale(1); }
  46%  { left: calc(50% - var(--story-item-half)); opacity: 1; transform: translateY(-50%) scale(0.85); }
  50%  { left: calc(50% - var(--story-item-half)); opacity: 0; transform: translateY(-50%) scale(0.5); }
  100% { left: var(--story-seat-rest); opacity: 0; transform: translateY(-50%) scale(0.6); }
}

/* --story-ticket-end is derived the same way from the mailbox's own right
   inset and width, so the ticket's center lands exactly on the mailbox's
   center on arrival. */
@keyframes story-ticket-travel {
  0%   { left: calc(50% - var(--story-item-half)); opacity: 0; transform: translateY(-50%) scale(0.5); }
  50%  { left: calc(50% - var(--story-item-half)); opacity: 0; transform: translateY(-50%) scale(0.5); }
  55%  { left: calc(50% - var(--story-item-half)); opacity: 1; transform: translateY(-50%) scale(1.25); }
  60%  { left: calc(50% - var(--story-item-half)); opacity: 1; transform: translateY(-50%) scale(1); }
  90%  { left: calc(100% - var(--story-ticket-end)); opacity: 1; transform: translateY(-50%) scale(1); }
  94%  { left: calc(100% - var(--story-ticket-end)); opacity: 0; transform: translateY(-50%) scale(0.7); }
  100% { left: calc(100% - var(--story-ticket-end)); opacity: 0; transform: translateY(-50%) scale(0.7); }
}

/* A small "release" pop timed to exactly when the seat fades in (0-4%),
   so the train visibly reacts at the moment it's supposed to be the
   source of the seat, the same way the eye and mailbox react at theirs. */
@keyframes story-train-release {
  0%, 8%, 96%, 100% { transform: scale(1); }
  2% { transform: scale(1.08); }
}

/* A quick, one-time pulse right at the crossfade — not a sustained state
   like the camera version had, since an eye doesn't "hold" anything. */
@keyframes story-eye-pulse {
  0%, 40%, 65%, 100% { transform: scale(1); }
  48%, 55% { transform: scale(1.15); }
}

@keyframes story-mailbox-bounce {
  0%, 86%, 98%, 100% { transform: translateY(0); }
  92% { transform: translateY(-4px); }
}

@media (max-width: 480px) {
  .story-strip {
    height: 40px;
    /* Recomputed for the 28px icons below, not inherited from desktop:
       --story-seat-rest matches .story-train's left (8px); --story-ticket-end
       matches .story-mailbox's right + width (8px + 28px = 36px). */
    --story-item-half: 14px;
    --story-seat-rest: 17px;
    --story-ticket-end: 36px;
  }
  .story-train { left: 8px; width: 46px; }
  .story-eye { width: 28px; }
  .story-mailbox { right: 8px; width: 28px; }
  .story-item { width: 28px; height: 28px; }
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 28px;
  border-radius: var(--md-corner-full);
  font-family: var(--md-font);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.1px;
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: transform var(--md-motion), box-shadow var(--md-motion), filter var(--md-motion);
}
.btn-filled { background: var(--md-primary); color: var(--md-on-primary); box-shadow: var(--md-elevation-1); }
.btn-filled:hover { filter: brightness(1.08); transform: translateY(-1px); box-shadow: var(--md-elevation-2); }
.btn .material-symbols-outlined { font-size: 20px; }
.btn-outlined { background: transparent; color: var(--md-primary); border: 1px solid var(--md-outline); }
.btn-outlined:hover { background: var(--md-primary-container); }
.btn-text { background: transparent; color: var(--md-primary); padding: 0 12px; height: auto; }
.btn-large { height: 56px; padding: 0 36px; font-size: 1rem; }

/* Cards */
.card {
  background: var(--md-surface);
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-corner-medium);
  padding: 24px;
  transition: box-shadow var(--md-motion), transform var(--md-motion);
}

/* Forms */
label { font-size: 0.875rem; color: var(--md-on-surface-variant); display: block; margin-bottom: 4px; }
input, select {
  font-family: var(--md-font);
  font-size: 1rem;
  padding: 12px 16px;
  border-radius: var(--md-corner-small);
  border: 1px solid var(--md-outline);
  background: var(--md-surface);
  color: var(--md-on-surface);
  width: 100%;
  max-width: 400px;
  transition: border-color var(--md-motion), outline-color var(--md-motion);
}
input:focus, select:focus { outline: 2px solid var(--md-primary); outline-offset: -1px; }

/* Icon button */
.icon-btn {
  width: 40px; height: 40px;
  border-radius: var(--md-corner-full);
  border: none;
  background: transparent;
  color: var(--md-on-surface-variant);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  text-decoration: none;
  font-size: 24px;
  transition: background-color var(--md-motion), transform var(--md-motion);
}
.icon-btn:hover { background: var(--md-surface-variant); }
@media (hover: hover) {
  .icon-btn:hover { transform: rotate(-12deg); }
}
@media (hover: none) {
  .icon-btn:active { background: var(--md-surface-variant); }
}

/* Tables */
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--md-outline-variant); font-size: 0.875rem; }
th { color: var(--md-on-surface-variant); font-weight: 500; }

/* Scroll-reveal (JS adds .is-visible when a .reveal element enters view) */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 500ms cubic-bezier(0.2, 0, 0, 1), transform 500ms cubic-bezier(0.2, 0, 0, 1);
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }
