/* Buraq design tokens — the single palette/scale/rhythm both HTML surfaces
   are built from. Loaded after type.css and before the surface's own
   stylesheet (dashboard/app.css, storefront/app.css), each of which is
   responsible only for its own components, never for redefining a value
   here.

   ── The design language ────────────────────────────────────────────────
   "Departure board." A printed timetable, not a dashboard chrome kit: a
   warm paper ground, hairline rules doing the work that boxes and drop
   shadows usually do, a high-contrast serif for headings, and monospaced
   tabular figures for every time, fare and code so columns of numbers line
   up the way they do on a real departures display.

   Three rules keep it coherent, and breaking them is what would make this
   look like every other admin template:

   1. HIERARCHY COMES FROM TYPE AND SPACE, NOT FROM BOXES. A list of
      departures is ruled rows, not a stack of floating cards. Elevation is
      reserved for things that genuinely float above the page (sticky
      summary, dropdown, modal) — see --shadow-*, of which there are only
      three, all shallow.

   2. COLOR IS FUNCTIONAL. The tenant's own --brand/--brand-2 marks what a
      visitor can operate, --line-* is wayfinding, and the semantic trio is
      state. Nothing is coloured decoratively, which is what leaves room for
      a tenant's palette to actually read as theirs (spec section 13).

   3. NUMBERS ARE MONOSPACED AND TABULAR. Fares, times, seat counts, ticket
      and booking numbers. `--font-mono` + `font-variant-numeric: tabular-
      nums` — a fare that shifts width as the digits change looks broken in
      a column, and this is a product made almost entirely of such columns.

   Light is the source of truth; each themed token carries its dark value
   beside it as light-dark(light, dark) rather than being re-declared in a
   second block, so a component written once is correct in both. See the
   "dark" note near the bottom for how a scheme is chosen. */

:root {
  /* Opting into both schemes is what makes light-dark() below resolve,
     and it is also what themes the things CSS doesn't reach: native form
     controls, scrollbars, the caret. [data-theme] overrides it further
     down. */
  color-scheme: light dark;

  /* ---- ground & surfaces ---------------------------------------------
     Warm, slightly yellow paper rather than a neutral grey — it reads as
     printed stock, and it flatters the tenant brand colours these sit
     under far better than a cool grey does. */
  --paper: light-dark(#F7F4EE, #14161A);          /* the page itself */
  --surface: light-dark(#FFFFFF, #1C1F25);        /* raised content: panels, rows, inputs */
  --surface-sunken: light-dark(#EFEAE0, #171A1F); /* recessed: table headers, disabled, wells */
  --surface-hover: light-dark(#F2EEE5, #232730);

  /* ---- ink ------------------------------------------------------------
     Three weights, not five. --ink for anything a visitor reads to make a
     decision, --ink-2 for supporting copy, --ink-3 for labels and meta.

     --ink-3 is the floor, and it is a real one: it clears 4.5:1 against all
     three grounds, the worst being --surface-sunken at 4.52:1. It carries
     every uppercase mono label on both surfaces, which is text and has to be
     readable as text — so nothing dimmer than this exists to reach for. (An
     earlier #767C89 only managed 3.5:1 on sunken.) */
  --ink: light-dark(#16181D, #EDE8DE);   /* 16.2:1 on paper */
  --ink-2: light-dark(#4C525E, #B0B5BF); /*  7.2:1 on paper */
  --ink-3: light-dark(#656A76, #858B97); /*  4.9:1 on paper, 4.5:1 on sunken */

  /* ---- rules ----------------------------------------------------------
     The main structural device. --rule is the default hairline between
     rows; --rule-strong closes a section or separates a total from what it
     totals. Deliberately low-contrast: a rule should organise the page
     without being read as content. */
  --rule: light-dark(#E4DED1, #2C313A);
  --rule-strong: light-dark(#CDC5B2, #414753);

  /* ---- tenant brand ---------------------------------------------------
     Overridden per-tenant from Tenant.primary_color/secondary_color in each
     surface's base.html. --brand carries structure (headers, filled
     surfaces a tenant wants to own); --brand-2 carries action (buttons,
     focus rings, selected states, links). Keeping the two roles apart is
     what stops a tenant with an aggressive palette from turning every
     control on the page the same colour as its background.
     These values are fallbacks for a tenant that has set neither. */
  --brand: light-dark(#1B2430, #0F1216);
  --brand-2: light-dark(#1F5E8C, #6BA8D8);
  --brand-2-ink: light-dark(#FFFFFF, #10161C);    /* text on a --brand-2 fill */
  --brand-2-wash: light-dark(#EAF1F7, rgb(107 168 216 / 0.14));   /* tint for selected/active backgrounds */

  /* ---- state ----------------------------------------------------------
     Each pairs a foreground that passes on --surface with a wash to sit on.
     Never used alone to carry meaning — every status also carries a word or
     an icon, since a colour-only status is unreadable to a colourblind
     dispatcher and invisible on a thermal ticket print. */
  --positive: light-dark(#1B7A4B, #5DBE8B);
  --positive-wash: light-dark(#E4F2E9, rgb(93 190 139 / 0.14));
  --caution: light-dark(#8A5A0B, #D9A441);
  --caution-wash: light-dark(#FAF0DC, rgb(217 164 65 / 0.14));
  --critical: light-dark(#A63229, #E0796D);
  --critical-wash: light-dark(#FBEAE7, rgb(224 121 109 / 0.14));
  --info: light-dark(#1F5E8C, #6BA8D8);
  --info-wash: light-dark(#E9F1F7, rgb(107 168 216 / 0.14));

  /* ---- route line colours --------------------------------------------
     Wayfinding, not identity — an underground-map convention where each
     service keeps a fixed hue so a passenger can tell two departures apart
     at a glance. Assigned deterministically per route by
     apps.storefront.templatetags.storefront_extras.route_line, which is
     why they're a fixed set rather than anything a tenant configures: they
     must stay stable per route and must never collide with --brand-2, the
     only colour that means "you can click this". */
  --line-1: light-dark(#C2410C, #F08A4B);
  --line-2: light-dark(#0F766E, #3FB5A8);
  --line-3: light-dark(#5B45C7, #9B87F0);
  --line-4: light-dark(#BE185D, #EC6E9F);
  --line-5: light-dark(#15803D, #56BE7C);
  --line-6: light-dark(#1D4ED8, #6E97F0);

  /* ---- type -----------------------------------------------------------
     See type.css for why these three families and how they're hosted. */
  /* "Taka" leads ALL THREE stacks. Its unicode-range is the single
     codepoint U+09F3, so it can only ever supply the currency sign and can
     never affect a letter or digit — and putting it only on the mono stack
     meant a price inside a button or a heading fell back to whatever ৳ the
     operating system had, next to the properly-set one two lines above. */
  --font-display: "Taka", "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-body: "Taka", "Familjen Grotesk", "Segoe UI", system-ui, -apple-system, Helvetica, Arial, sans-serif;
  --font-mono: "Taka", "JetBrains Mono", "Cascadia Mono", Consolas, ui-monospace, "SF Mono", monospace;

  /* A modular-ish scale, hand-corrected at the small end so 13px and 14px
     both exist — UI meta needs that granularity more than a strict ratio
     needs to be preserved. */
  --t-2xs: 11px;
  --t-xs: 12px;
  --t-sm: 13px;
  --t-base: 15.5px;
  --t-md: 17px;
  --t-lg: 20px;
  --t-xl: 26px;
  --t-2xl: 33px;
  --t-3xl: 42px;
  --t-4xl: 54px;

  --lh-tight: 1.12;   /* display headings */
  --lh-snug: 1.3;     /* short UI strings, table cells */
  --lh-body: 1.55;    /* running prose */

  /* Uppercase mono labels are a signature of this design; this is their
     tracking. Below ~0.1em uppercase mono reads cramped, above ~0.16em it
     stops reading as a word. */
  --track-label: 0.13em;

  /* ---- space ----------------------------------------------------------
     4px base. Named by size, not by purpose, so a component can pick the
     step that fits rather than the step someone else named "card-gap". */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-7: 32px;
  --s-8: 40px;
  --s-9: 56px;
  --s-10: 72px;
  --s-11: 96px;

  /* ---- radius ---------------------------------------------------------
     Restrained on purpose. Content panels stay close to square so they
     read as sheets of a timetable; full rounding is reserved for things a
     visitor operates, which makes "round = interactive" a real signal
     rather than a decoration. */
  --r-sm: 5px;
  --r-md: 9px;
  --r-lg: 14px;
  --r-pill: 999px;

  /* ---- elevation ------------------------------------------------------
     Only three, all shallow, all warm-tinted rather than pure black so
     they sit on the paper ground instead of dirtying it. If something
     needs to stand out and isn't floating, it wants a rule or a wash —
     not a fourth shadow. */
  --shadow-1: 0 1px 2px light-dark(rgb(38 30 14 / 0.06), rgb(0 0 0 / 0.4));
  --shadow-2: 0 4px 14px -4px light-dark(rgb(38 30 14 / 0.14), rgb(0 0 0 / 0.5));
  --shadow-3: 0 18px 40px -12px light-dark(rgb(38 30 14 / 0.26), rgb(0 0 0 / 0.65));

  /* ---- motion ---------------------------------------------------------
     One duration for state, one for movement, one easing. A shared rhythm
     is most of what makes an interface feel considered rather than
     assembled; per-component timings are what make it feel assembled. */
  --dur-fast: 120ms;
  --dur: 200ms;
  --ease: cubic-bezier(0.2, 0.6, 0.3, 1);

  --z-sticky: 30;
  --z-dropdown: 50;
  --z-modal: 100;
}

/* ---- dark ------------------------------------------------------------
   There is no second palette below this line any more. Every themed token
   above is a light-dark(light, dark) pair, so each one has exactly one
   definition and the two schemes cannot drift apart — which they could
   when the dark values lived in a separate @media block that had to be
   kept in sync by hand.

   The same principle as before: the dark side REMAPS the token names, it
   does not invert them. Surfaces lift with warmth still in them (a pure-
   grey dark mode next to a warm light mode reads as two different
   products), state colours are desaturated and lightened so they stay
   legible on a dark ground instead of vibrating on it, and the --line-*
   ramp is lightened to clear 3:1 there.

   What resolves a light-dark() pair is the element's `color-scheme`, so
   these three lines are the whole theming mechanism:

     :root                     color-scheme: light dark  → follow the OS
     :root[data-theme="light"] color-scheme: light       → forced light
     :root[data-theme="dark"]  color-scheme: dark        → forced dark

   The attribute is set by the theme toggle in each surface's header and
   persisted in localStorage. With scripting off no attribute is ever set,
   so the OS preference still wins and the page is correct in both
   schemes — the toggle is an enhancement on top, not the mechanism. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

/* ---- base ------------------------------------------------------------ */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* `color-scheme` above already flips the scrollbar between the browser's
     light and dark defaults, but those defaults are neutral grey — next to
     a warm paper ground the gutter reads as a cold strip bolted to the
     page. These two tokens put it on the same palette as everything else,
     and because they are tokens it follows the theme toggle for free.

     scrollbar-color only, not ::-webkit-scrollbar: the pseudo-element
     opts a browser out of overlay scrollbars entirely, turning the thin
     bar that fades away on macOS into a permanent classic one. Recolouring
     is the ask; changing the scrollbar's behaviour is not. */
  scrollbar-color: var(--rule-strong) var(--paper);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Fraunces' optical-size axis, applied by role. A display serif set at one
   optical size across a 12px-to-54px range is the single fastest way to
   make a good typeface look wrong: too spindly small, too flat large. */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: -0.018em;
  color: var(--ink);
  margin: 0;
  font-variation-settings: "opsz" 72;
}
h1 { font-size: var(--t-2xl); font-variation-settings: "opsz" 110; }
h2 { font-size: var(--t-xl); font-variation-settings: "opsz" 60; }
h3 { font-size: var(--t-lg); font-variation-settings: "opsz" 36; letter-spacing: -0.012em; }
h4, h5, h6 { font-size: var(--t-md); font-variation-settings: "opsz" 20; letter-spacing: -0.006em; }

p { margin: 0 0 var(--s-4); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--brand-2);
  text-decoration-color: color-mix(in srgb, var(--brand-2) 35%, transparent);
  text-underline-offset: 0.18em;
}
a:hover { text-decoration-color: currentColor; }

/* Never removed, only styled — a keyboard user at a counter terminal needs
   to see where they are, and this is one of the few places where a visible
   ring genuinely beats a subtle one. */
:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* The UA's own `[hidden] { display: none }` is a bare attribute selector, so
   any component rule that sets `display: flex` on a class outranks it and the
   element stays visible. Every surface here toggles rows with `hidden`, so
   this needs to win outright. */
[hidden] { display: none !important; }

img, svg { max-width: 100%; }
svg { display: block; }

hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: var(--s-6) 0;
}

/* ---- shared primitives ----------------------------------------------- */

/* The uppercase mono label used for every field label, table header,
   eyebrow and meta string across both surfaces. */
.u-label {
  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);
}

/* Anything numeric. Tabular figures stop columns of fares and times from
   jittering as their digits change. */
.u-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}

.u-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Wide content (tables, seat maps) scrolls inside its own box so the page
   body never scrolls sideways on a phone. */
.u-scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---- Bengali script adjustments ---------------------------------------
   Two Latin-only habits in this system actively damage Bengali text rather
   than just looking odd on it, so both are neutralised wherever the page (or
   an ancestor) is marked `lang="bn"` — matching the storefront's dynamic
   `<html lang="{{ LANGUAGE_CODE }}">`, no per-element markup needed.

   1. --track-label is 0.13em of tracking meant to make Latin capitals in a
      mono face read as a deliberate label instead of shouting. Bengali has
      no case for it to apply to, and that much space between conjunct
      clusters breaks the eye's ability to read them as one glyph. Resetting
      the TOKEN fixes every consumer at once (.u-label, .eyebrow, .dl dt,
      .datestrip__dow, .leg__place — anywhere letter-spacing: var(--track-
      label) is used) rather than chasing each selector.

   2. The negative letter-spacing on headings (tightening Fraunces' Latin
      spacing at large sizes) pulls Bengali conjuncts into each other instead
      — a fix that only exists for a Latin optical-sizing reason Bengali
      doesn't share. */
:lang(bn) { --track-label: normal; }
:lang(bn) h1, :lang(bn) h2, :lang(bn) h3, :lang(bn) h4, :lang(bn) h5, :lang(bn) h6 {
  letter-spacing: normal;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
