@import url('/static/fonts.css');

/* ===========================================================================
   Διοδιόμετρο, visual identity

   Deep motorway green on a warm off-white. Green because it is what the
   overhead signs on a Greek motorway are, and because the sibling site
   (Τιμόμετρο) owns mustard, the two should read as a family without being
   the same thing. Commissioner at 800 is the other half of that family tie;
   it is self-hosted, in Greek and Latin subsets, so no CDN sees a visitor.

   Green is the brand, so it is *never* used to mean "cheap" in the same view
   as a saving. Money that you save is stated in words and in the amount; the
   only semantic colours here are the ferry-alternative box (which is an
   opportunity, not a status) and the error red.

   --boom is the one colour that is not a brand decision. A toll barrier is
   red-and-white everywhere in Greece, so the barrier in the logo is
   red-and-white, and it never sits directly on the green: red on green is the
   worst pair there is for the commonest colour blindness.
   =========================================================================== */

:root {
  --bg: #F4F7F3;
  --surface: #FFFFFF;
  --surface-2: #FAFCF9;
  --ink: #12211A;
  --muted: #5C7065;
  --line: #DCE6DD;

  --brand: #0F6B45;          /* dark motorway green, AA on the off-white */
  --brand-strong: #0A4E32;
  --brand-tint: #E4F1E8;
  --brand-ink: #FFFFFF;

  --accent: #B7791F;         /* the one warm note: savings, ferry box */
  --accent-tint: #FDF3E0;
  --accent-ink: #4A2F05;

  --toll: #0F6B45;
  --fuel: #2E6B8F;
  --ferry: #B7791F;

  --dear: #A5321C;
  --dear-bg: #FBEAE5;
  --warn: #8A6003;         /* arrives, but eats the reserve */
  --warn-bg: #FDF6E3;

  --logo-ink: #12211A;
  --logo-bg: #F6F2E7;      /* the dial face: warm, so the red has somewhere to sit */
  --boom: #DC4A26;         /* toll-barrier red. Never placed on --brand */
  --road: #3D4B44;

  --radius: 13px;
  --shadow: 0 1px 2px rgba(15, 50, 35, .05), 0 8px 22px rgba(15, 50, 35, .07);
  --font: 'Commissioner', system-ui, -apple-system, 'Segoe UI', Roboto,
          'Helvetica Neue', sans-serif;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

body {
  color-scheme: light only;
  margin: 0;
  /* A column, so the one flexible child (the calculator) can absorb the space
     the fixed ones do not use. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 400 16px/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand-strong); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { letter-spacing: -.021em; }

.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.skip {
  position: absolute; left: -999px; top: 0; z-index: 100;
  background: var(--brand); color: #fff; padding: 10px 16px;
}
.skip:focus { left: 0; }

.topbar {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 12px 22px; background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 900;
  transition: background-color .2s ease, border-color .2s ease;
}
.brand { display: flex; align-items: center; gap: 9px; color: var(--ink); }
.brand:hover { text-decoration: none; }
.logo-mark { width: 34px; height: 34px; flex-shrink: 0; }
/* 24, not 22, because the viewBox grew to make room for the boom above the
   letters. The wordmark is sized by height, so the extra headroom would
   otherwise be paid for by shrinking the type; this keeps the letters the
   size they were and gives the accent the space it needs. */
.wordmark { height: 24px; width: auto; flex-shrink: 0; display: block; }
.brand-text { font-weight: 800; font-size: 20px; letter-spacing: -.03em; }
.brand-text span { color: var(--brand); }

.topnav-wrap {
  position: relative;
  display: flex;
  align-items: center;
  margin-left: auto;
  min-width: 0;
  max-width: 100%;
}
.topnav {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 2px 0;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
}
.topnav::-webkit-scrollbar { display: none; }
.topnav a {
  font-weight: 600; font-size: 14.5px; color: var(--ink);
  padding: 6px 11px; border-radius: 8px; transition: background .15s ease, color .15s ease;
  flex-shrink: 0;
}
.topnav a:hover { color: var(--brand-strong); background: var(--brand-tint); text-decoration: none; }
.topnav a[aria-current="page"] {
  color: var(--brand-strong); background: var(--brand-tint); font-weight: 700;
}
.lang {
  border: 1px solid var(--line); border-radius: 8px; padding: 4px 10px;
  font-size: 13px; color: var(--muted); font-weight: 600;
  background: var(--surface);
  transition: all .15s ease;
  flex-shrink: 0;
}
.lang:hover { border-color: var(--brand); color: var(--brand-strong); background: var(--brand-tint); text-decoration: none; }

/* Topnav Scroll Indicators & Arrows */
.topnav-arrow {
  display: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.96);
  border: 1px solid var(--line);
  color: var(--ink);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.14);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  transition: transform .15s ease, background-color .15s ease, color .15s ease, border-color .15s ease;
}
.topnav-arrow:hover {
  background: var(--brand);
  color: #FFFFFF;
  border-color: var(--brand);
  transform: translateY(-50%) scale(1.1);
}
.topnav-arrow.prev {
  left: -2px;
}
.topnav-arrow.next {
  right: -2px;
}

.topnav-wrap.has-overflow.can-scroll-left .topnav-arrow.prev {
  display: flex;
}
.topnav-wrap.has-overflow.can-scroll-right .topnav-arrow.next {
  display: flex;
}

/* Subtle edge gradients when scrollable */
.topnav-wrap.has-overflow.can-scroll-right::after {
  content: '';
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 32px;
  background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.92));
  pointer-events: none;
  border-radius: 0 8px 8px 0;
  z-index: 3;
}
.topnav-wrap.has-overflow.can-scroll-left::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 32px;
  background: linear-gradient(to left, transparent, rgba(255, 255, 255, 0.92));
  pointer-events: none;
  border-radius: 8px 0 0 8px;
  z-index: 3;
}

/* ------------------------------------------------------ disclaimer strip */
.disclaimer {
  background: var(--brand-tint); border-bottom: 1px solid var(--line);
  color: #123A28; font-size: 13px; line-height: 1.45;
}
.disclaimer div {
  max-width: 1500px; margin: 0 auto; padding: 7px 20px;
  display: flex; gap: 9px; align-items: baseline;
}
.disclaimer a { color: inherit; text-decoration: underline; }

/* The only child of <body> that grows. Everything else (topbar, disclaimer,
   footer) is its natural height. */
#main { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

/* Because #main is a flex container, everything it holds is a flex item, and a
   flex item's automatic minimum size is its *content's* minimum, not zero. So
   a page whose widest thing cannot shrink refuses to shrink itself: the toll
   table needs 733 px, `.wide` therefore claimed 773, and /prices scrolled
   sideways on every phone. The `overflow-x: auto` on the table's own wrapper
   never got a chance, because the wrapper had been handed all the room it
   asked for.
   min-width: 0 is what makes a flex item obey its container, and then the
   wrapper scrolls the table instead of the page scrolling the wrapper. */
#main > * { min-width: 0; }

/* =========================================================== the app grid */
/* Phone order is the DOM order: controls, then map. Desktop lifts the map to
   the right column and pins it, so the numbers scroll against a map that
   stays put. */
.app {
  display: grid; grid-template-columns: 1fr;
  max-width: 1500px; margin: 0 auto; gap: 0;
  /* Explicit, because as a flex item the `margin: 0 auto` that centres this
     also cancels the default cross-axis stretch, and the grid collapsed to
     zero width: the map column was 0px wide and the map simply was not there. */
  width: 100%;
}
.panel { padding: 22px 20px 60px; min-width: 0; }
.map-wrap { position: relative; height: 62vh; min-height: 340px; }
#map { position: absolute; inset: 0; background: #DDE6E0; }

@media (min-width: 900px) {
  /* The calculator fills whatever is left after the chrome, so the footer sits
     on the fold instead of 140px below it.
     
     This used to be `height: calc(100vh - 96px)`, a guess at the topbar plus
     the disclaimer strip that ignored the footer completely and broke again
     every time either changed height. Letting flex measure it is exact and
     stays exact. */
  .app { grid-template-columns: minmax(400px, 40vw) 1fr; }

  /* The home page is one screen: the calculator takes whatever the topbar, the
     disclaimer strip and the footer leave, so the footer lands on the fold
     rather than 140px below it, and the controls scroll inside their own
     column.

     Scoped to the home page on purpose. A route page carries an article under
     the same calculator and has to scroll like any other document; this used
     to be `height: calc(100vh - 96px)` on `.app` everywhere, a guess at two of
     the three fixed bars that ignored the footer and went stale whenever any
     of them changed. */
  body[data-fullscreen] { height: 100vh; overflow: hidden; }
  body[data-fullscreen] #main { flex: 1 1 auto; min-height: 0; }
  body[data-fullscreen] .app { flex: 1 1 auto; min-height: 0; }
  .panel { overflow-y: auto; padding: 26px 28px 60px; }
  .map-wrap { height: auto; min-height: 0; }
}
@media (min-width: 1400px) {
  .app { grid-template-columns: 560px 1fr; }
}

.map-hint {
  position: absolute; left: 10px; bottom: 10px; z-index: 500;
  margin: 0; padding: 6px 11px; border-radius: 8px;
  background: rgba(255,255,255,.92); border: 1px solid var(--line);
  font-size: 12.5px; color: var(--muted); max-width: min(70%, 380px);
}

/* ------------------------------------------------------------------ hero */
.hero h1 { font-size: 30px; line-height: 1.15; margin: 0 0 10px; font-weight: 800; }
.hero h1 em { font-style: normal; color: var(--brand); }
.lede { font-size: 15.5px; color: var(--muted); margin: 0 0 20px; }

/* ------------------------------------------------------------------ form */
.trip { display: block; }
.stops { display: flex; flex-direction: column; position: relative; }
.stop { display: flex; align-items: center; gap: 9px; position: relative;
        padding: 4px 0; }

/* The rail down the left: a lettered badge per row, joined by a line, so the
   list reads as a direction of travel rather than as three similar boxes. */
.rail {
  position: relative; flex-shrink: 0; width: 26px; height: 26px;
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 11.5px; font-weight: 800; color: #fff; background: var(--muted);
}
.stop.from .rail { background: var(--brand); }
.stop.to .rail { background: var(--dear); }
/* The stops are one journey, so the rail draws it: a line from each stop down
   to the next with an arrowhead pointing the way, through the intermediate
   stops as well as the two ends. It used to be a 12 px stub in the hairline
   grey, which read as a divider between two rows rather than as a route
   running through them. The 31 px it now spans is the real gap between the
   badges, less the room the arrowhead needs. */
.stop:not(:last-child) .rail::after {
  content: ""; position: absolute; top: 100%; left: 50%; width: 2px;
  height: 23px; margin-left: -1px; background: var(--brand); opacity: .5;
}
.stop:not(:last-child) .rail::before {
  content: ""; position: absolute; top: calc(100% + 21px); left: 50%;
  margin-left: -4.5px; width: 0; height: 0;
  border-left: 4.5px solid transparent;
  border-right: 4.5px solid transparent;
  border-top: 6px solid var(--brand);
  opacity: .5;
}
.row-tools { display: flex; gap: 3px; flex-shrink: 0; }
.icon.tiny {
  width: 28px; height: 28px; font-size: 13px; border-radius: 8px;
  border-color: transparent; background: transparent; color: var(--muted);
}
.icon.tiny:hover { background: var(--brand-tint); color: var(--brand-strong); }
.icon.tiny.danger:hover { background: var(--dear-bg); color: var(--dear); }

/* The reorder grip. Dots rather than arrows, because a stop moves to wherever
   you put it, not one place at a time. */
.grip {
  border: 0; padding: 0 6px; cursor: grab;
  color: var(--muted); font-size: 16px; line-height: 1; letter-spacing: -3px;
  touch-action: none;          /* or the browser scrolls instead of dragging */
  align-self: stretch;
  /* Visible at rest, not on hover. A handle you have to find by hovering is
     a handle nobody on a phone will ever find, and hover is exactly the
     input this control does not have. */
  background: var(--surface-2); border-radius: 8px;
}
.grip:hover { color: var(--brand-strong); background: var(--brand-tint); }
.grip:active { cursor: grabbing; }
.stop.dragging {
  background: var(--brand-tint); border-radius: 10px;
  box-shadow: 0 4px 14px rgba(15, 50, 35, .13);
}
.stop.dragging .grip { color: var(--brand); }
.stop input {
  flex: 1; min-width: 0; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: 15px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.stop input:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(15, 107, 69, .14);
}
.dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
.dot.from { background: var(--brand); box-shadow: 0 0 0 2px rgba(15, 107, 69, .2); }
.dot.to { background: var(--dear); box-shadow: 0 0 0 2px rgba(165, 50, 28, .2); }
.dot.via { background: var(--muted); }

.icon {
  width: 38px; height: 38px; flex-shrink: 0;
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  color: var(--muted); font-size: 16px; cursor: pointer; line-height: 1;
  transition: all .15s ease;
}
.icon:hover { border-color: var(--brand); color: var(--brand); }

/* "My location" and "swap" are actions on the pair of boxes, not fields of
   their own, so they lose the input-shaped outline and read as buttons. */
.stop-tools { display: flex; gap: 7px; margin: 8px 0 12px;
              align-items: center; flex-wrap: wrap; }
.ghost-btn {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--line); background: var(--surface); padding: 6px 11px; border-radius: 8px;
  font: inherit; font-size: 13px; font-weight: 600;
  color: var(--brand-strong); cursor: pointer;
  box-shadow: 0 1px 2px rgba(15, 50, 35, .03);
  transition: all .15s ease;
}
.ghost-btn:hover {
  background: var(--brand-tint); border-color: var(--brand);
  transform: translateY(-1px); box-shadow: 0 2px 6px rgba(15, 50, 35, .08);
}
.ghost-btn:active { transform: translateY(0); }
.ghost-btn span.g { font-size: 15px; line-height: 1; }

/* Clearing throws work away, so it is not the same green as adding a stop or
   swapping the ends. Soft, not alarming: it sits in a row of ordinary
   controls and is not a delete button. */
#clear { color: var(--dear); }
#clear:hover { background: var(--dear-bg); border-color: var(--dear); }

.drag-hint { font-size: 12.5px; color: var(--muted); margin-left: 4px; }

/* Popular routes: one sideways row under the boxes they fill in, rather than
   a block of chips that pushed the settings off the screen. */
.chips.scroller {
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  padding: 3px 2px 8px; margin: 0 -2px; scroll-snap-type: x proximity;
  mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
}
.chips.scroller::-webkit-scrollbar { display: none; }
.chips.scroller .chip { flex: 0 0 auto; scroll-snap-align: start; }

.stop-actions { margin: 8px 0 16px; }
.link {
  background: none; border: 0; padding: 0; font: inherit; font-size: 14px;
  color: var(--brand-strong); cursor: pointer; text-decoration: none;
}
.link:hover { text-decoration: underline; }

.field { margin-bottom: 13px; min-width: 0; flex: 1; }
.field > label {
  display: block; font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 5px;
}
select, .unit-input input {
  width: 100%; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
select:focus, .unit-input input:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(15, 107, 69, .14);
}
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row .field { flex: 1 1 150px; }

.field.check { display: flex; flex-direction: column; gap: 7px; justify-content: center; }
.field.check label {
  display: flex; align-items: center; gap: 7px; font-size: 14.5px;
  text-transform: none; letter-spacing: 0; color: var(--ink); font-weight: 500;
  margin: 0; cursor: pointer;
}
.field.check input { accent-color: var(--brand); width: 17px; height: 17px; }
.field.check label.off { color: var(--muted); cursor: default; }

.hint {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; border-radius: 50%; background: var(--line);
  color: var(--muted); font-size: 11px; font-weight: 700; cursor: help;
}

.unit-input { position: relative; }
.unit-input .unit {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  font-size: 12.5px; color: var(--muted); pointer-events: none;
}
.unit-input input { padding-right: 78px; }

.more { margin: 4px 0 18px; }
.more summary {
  cursor: pointer; font-size: 14px; color: var(--brand-strong); font-weight: 600;
  padding: 6px 0; list-style: none;
}
.more summary::-webkit-details-marker { display: none; }
.more summary::before { content: "▸ "; }
.more[open] summary::before { content: "▾ "; }

.btn {
  display: inline-block; padding: 10px 18px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font: inherit; font-weight: 700; cursor: pointer; font-size: 15px;
  transition: all .15s ease;
}
.btn:hover { border-color: var(--brand); text-decoration: none; }
.btn.primary {
  background: var(--brand); border-color: var(--brand); color: var(--brand-ink);
  box-shadow: 0 2px 6px rgba(15, 107, 69, .2);
}
.btn.primary:hover {
  background: var(--brand-strong); border-color: var(--brand-strong);
  box-shadow: 0 4px 12px rgba(15, 107, 69, .3);
  transform: translateY(-1px);
}
.btn.primary:active { transform: translateY(0); }
.btn.big { width: 100%; padding: 14px; font-size: 16.5px; }
.btn:disabled { opacity: .6; cursor: default; }
.btn.small { padding: 5px 11px; font-size: 13px; }

.error {
  margin: 12px 0 0; padding: 11px 14px; border-radius: 10px;
  background: var(--dear-bg); color: var(--dear); font-size: 14.5px;
}

/* -------------------------------------------------------------- results */
.result { margin-top: 14px; }
.totals {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow);
}
.total-main { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.total-main .label {
  font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em;
}
.total-main strong { font-size: 38px; font-weight: 800; letter-spacing: -.03em; line-height: 1; }
.per-person { font-size: 14px; color: var(--muted); }

.split { display: flex; flex-wrap: wrap; gap: 9px; margin: 16px 0 0; padding: 0; }
.split > div {
  flex: 1 1 96px; padding: 10px 13px; border-radius: 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-left-width: 4px; position: relative; overflow: hidden;
  transition: transform .15s ease, box-shadow .15s ease;
}
.split > div:hover {
  transform: translateY(-1px);
  box-shadow: 0 3px 10px rgba(15, 50, 35, .06);
}
/* Faint, so it reads as a marker for the eye and never competes with the
   number, which is the only thing in the box anybody is here for. */
.split .ico {
  position: absolute; top: 6px; right: 8px; font-size: 17px;
  line-height: 1; opacity: .35; pointer-events: none;
}
.split.minor .ico { font-size: 15px; opacity: .3; }
.split dd { padding-right: 4px; }
.split dt {
  font-size: 11px; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; font-weight: 700;
}
.split dd { margin: 2px 0 0; font-size: 18px; font-weight: 800; }
.split .tolls { border-left-color: var(--toll); background: linear-gradient(to right, #F2F8F4, var(--surface-2) 45%); }
.split .fuel { border-left-color: var(--fuel); background: linear-gradient(to right, #F0F6F9, var(--surface-2) 45%); }
.split .ferry { border-left-color: var(--ferry); background: linear-gradient(to right, #FDF9F0, var(--surface-2) 45%); }
.split.minor > div { border-left-color: var(--line); }
.split.minor dd { font-size: 15.5px; font-weight: 700; }

.share-row { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 15px; }
#stamp { margin: 9px 0 0; font-size: 11.5px; }

/* ----------------------------------------------------------- the islands */
/* Blue rather than the ferry amber: the amber box is an *opportunity* (there
   is a cheaper way across), and this one is a fact (you cannot drive there).
   Using the same colour for both would make an unavoidable boat look like a
   suggestion. */
.island {
  margin-top: 16px; padding: 16px 17px; border-radius: var(--radius);
  background: #EAF1F6; border: 1px solid #C6DAE7;
}
.island h3 { margin: 0 0 4px; font-size: 16px; color: #24506E; }
.island .lede { font-size: 13.5px; margin: 0 0 12px; color: #3C6584; }
.island-legs { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 8px 12px; }
.island-legs dt {
  width: 22px; height: 22px; border-radius: 50%; background: #24506E;
  color: #fff; font-size: 12px; font-weight: 800; text-align: center;
  line-height: 22px;
}
.island-legs dd { margin: 0; font-size: 14.5px; color: var(--ink); }
.island-legs dd b { font-weight: 800; }
.island-legs dd .sub { display: block; font-size: 12.5px; color: #3C6584; }
.island .tiny { margin: 10px 0 0; color: #3C6584; }

/* Link to the page a fare was read from, the same treatment as timometro's.
   Deliberately quiet: it sits in a column of numbers people scan, and it is
   there for the reader who wants to check one, not for everyone reading past
   it. Toll prices are the one thing here that must never be taken on trust,
   and a price you cannot check is a price you have to. */
.src-link {
  font-size: .78em; text-decoration: none; color: var(--muted);
  vertical-align: super; margin-left: 2px;
}
.src-link:hover, .src-link:focus-visible { color: var(--brand-strong); }

/* The last line on the page. Deliberately the quietest thing on it: it is a
   caveat, not a warning, and a site that shouts its own disclaimer reads as
   though it does not trust its numbers. */
.fine-print {
  margin: 18px 0 0; font-size: 11.5px; line-height: 1.45;
  color: var(--muted); opacity: .72; max-width: 62ch;
}

/* The «a boat is cheaper» box. Same warm treatment as the Ρίο alternative,
   because it is the same kind of thing: an offer, not a status. */
/* «Report a problem». Crisp vector warning triangle with smooth rounded corners and cutout exclamation mark. */
.warn-ico {
  display: inline-block;
  width: 15px;
  height: 15px;
  vertical-align: -2.5px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cmask id='m'%3E%3Crect width='24' height='24' fill='%23fff'/%3E%3Cline x1='12' y1='8' x2='12' y2='13.5' stroke='%23000' stroke-width='2.4' stroke-linecap='round'/%3E%3Ccircle cx='12' cy='17.2' r='1.4' fill='%23000'/%3E%3C/mask%3E%3Cpath d='M12 2.5a2 2 0 0 0-1.74 1l-8.5 15A2 2 0 0 0 3.5 21.5h17a2 2 0 0 0 1.74-3l-8.5-15A2 2 0 0 0 12 2.5z' fill='%23000' mask='url(%23m)'/%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cmask id='m'%3E%3Crect width='24' height='24' fill='%23fff'/%3E%3Cline x1='12' y1='8' x2='12' y2='13.5' stroke='%23000' stroke-width='2.4' stroke-linecap='round'/%3E%3Ccircle cx='12' cy='17.2' r='1.4' fill='%23000'/%3E%3C/mask%3E%3Cpath d='M12 2.5a2 2 0 0 0-1.74 1l-8.5 15A2 2 0 0 0 3.5 21.5h17a2 2 0 0 0 1.74-3l-8.5-15A2 2 0 0 0 12 2.5z' fill='%23000' mask='url(%23m)'/%3E%3C/svg%3E") no-repeat center / contain;
}
.btn.report {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #92400E;
  border-color: #FDE68A;
  background: #FEF3C7;
  font-weight: 600;
  transition: all .15s ease;
}
.btn.report:hover {
  border-color: #F59E0B;
  background: #FDE68A;
  color: #78350F;
  box-shadow: 0 2px 6px rgba(245, 158, 11, 0.18);
  transform: translateY(-1px);
}

/* The per-row version: quiet until you look for it. */
.warn-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  color: var(--muted);
  opacity: 0.55;
  border: 1px solid transparent;
  background: transparent;
  transition: all .14s ease;
}
.warn-btn:hover, .warn-btn:focus-visible {
  color: #B45309;
  background: #FEF3C7;
  border-color: #FDE68A;
  opacity: 1;
  transform: scale(1.1);
  box-shadow: 0 1px 4px rgba(245, 158, 11, 0.16);
  text-decoration: none;
}
.name-cell .warn-btn { width: 24px; height: 24px; vertical-align: middle; }
.card h3 .warn-btn { float: right; margin-left: 8px; }

/* Kept trips. A short list, so it is a comparison rather than a history. */
.saved {
  margin-top: 14px; padding: 11px 13px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line);
}
.saved h3 { margin: 0; font-size: 14px; }
.saved-list { list-style: none; margin: 8px 0 0; padding: 0; }
.saved-item {
  display: flex; align-items: center; gap: 12px;
  border-top: 1px solid var(--line);
}
/* The whole row is the control: clicking it puts that trip back on screen.
   Still an <a>, so ctrl-click and the middle button open it in a tab like any
   other link. */
.saved-open {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 10px;
  padding: 8px 10px; border-radius: 8px;
  /* Only the left is pulled out, so the highlight lines up with the card's
     own edge. Pulling the right out as well ran it into the ✕, which then had
     nowhere to sit that did not look like part of the button. */
  margin-left: -6px;
  color: inherit; text-decoration: none; cursor: pointer;
  transition: background .12s ease;
}
.saved-open:hover, .saved-open:focus-visible {
  background: var(--brand-tint); text-decoration: none;
}
.saved-drop { flex-shrink: 0; }
.saved-item:first-child { border-top: 0; }
/* The cheapest is marked rather than sorted to the top: the order you saved
   them in is the order you were thinking about them. */
.saved-item.best .saved-total { color: var(--brand); }
.saved-where { flex: 1; min-width: 0; font-size: 14px; }
.saved-where b { font-weight: 700; }
.saved-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.saved-meta { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }

/* What tells two saves of the same road apart. The toll badge carries the same
   green/grey the result card does, so the pair reads the same wherever it
   appears; the rest are neutral, because they are facts about the trip rather
   than the choice being compared. */
.s-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
  padding: 1px 6px; border-radius: 5px; white-space: nowrap;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--line);
}
.s-badge.tolled {
  background: #CBE4D5; color: var(--brand-strong);
  border-color: rgba(15, 107, 69, .35);
}
.s-badge.free {
  background: #E8ECE9; color: var(--muted);
  border-color: rgba(92, 112, 101, .30);
}
.s-badge.ferry {
  background: #D9E8F5; color: #1B4D7E;
  border-color: rgba(27, 77, 126, .35);
}
.saved-total {
  font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.saved-drop {
  color: var(--muted); flex-shrink: 0;
  width: 24px; height: 24px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
}
.saved-drop:hover { color: var(--dear); background: var(--dear-bg); }

/* An offer with an action behind it, so it is a button and looks pressable:
   it lifts on hover and carries its own call to action. */
.ferry-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  text-align: left;
  cursor: pointer;
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--accent-tint);
  border: 1px dashed #D6B97B;
  font: inherit;
  color: inherit;
  box-sizing: border-box;
  transition: box-shadow .12s ease, border-color .12s ease;
}
.ferry-option:hover, .ferry-option:focus-visible {
  border-color: var(--accent);
  border-style: solid;
  box-shadow: 0 2px 10px rgba(183, 121, 31, .22);
}
.ferry-option h3 { margin: 0; font-size: 14px; color: var(--accent-ink); }
.ferry-cta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 12.5px;
  font-weight: 800;
  color: var(--accent-ink);
  transition: color .15s ease;
}
.ferry-cta .ferry-cta-txt {
  text-decoration: none;
}
.ferry-cta .cta-arrow {
  display: inline-block;
  text-decoration: none;
  transition: transform .15s ease;
}
.ferry-option:hover .ferry-cta,
.ferry-option:focus-visible .ferry-cta {
  color: var(--ink);
}
.ferry-option:hover .ferry-cta .ferry-cta-txt,
.ferry-option:focus-visible .ferry-cta .ferry-cta-txt {
  text-decoration: underline;
}
.ferry-option:hover .ferry-cta .cta-arrow,
.ferry-option:focus-visible .ferry-cta .cta-arrow {
  text-decoration: none;
  transform: translateX(3px);
}
.ferry-option-action-col {
  flex: 0 0 78px;
  width: 78px;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-align: center;
  margin-left: auto;
}
.ferry-cta-box {
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: #FFFDF8;
  border: 1px solid #D6B97B;
  color: var(--accent-ink);
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.ferry-option:hover .ferry-cta-box,
.ferry-option:focus-visible .ferry-cta-box {
  background: #FFF4DC;
  border-color: var(--accent);
  color: var(--ink);
  box-shadow: 0 1px 4px rgba(183, 121, 31, .25);
}
.ferry-cta-box .mode-arrow {
  font-size: 14px;
  font-weight: 700;
  transition: transform .15s ease;
}
.ferry-option:hover .ferry-cta-box .mode-arrow,
.ferry-option:focus-visible .ferry-cta-box .mode-arrow {
  transform: scale(1.25);
}
.ferry-option-sub {
  width: 100%;
  font-size: 10px;
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: .01em;
  color: var(--accent-ink);
  text-align: center;
  white-space: normal;
  transition: color .15s ease;
}
.ferry-option:hover .ferry-option-sub,
.ferry-option:focus-visible .ferry-option-sub {
  color: var(--ink);
}

/* Said whenever the answer puts somebody on a boat. */
.ferry-warning {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; cursor: pointer;
  margin: 12px 0 0; padding: 10px 14px; border-radius: var(--radius);
  background: var(--warn-bg); border: 1px dashed #D6B97B;
  font: inherit; color: var(--warn);
  box-sizing: border-box;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.ferry-warning[hidden] {
  display: none !important;
}
.ferry-warning:hover, .ferry-warning:focus-visible {
  border-style: solid; border-color: var(--accent); background: #FFF9ED;
  box-shadow: 0 2px 10px rgba(183, 121, 31, .20);
}
.ferry-warning-text {
  flex: 1 1 auto; font-size: 12.5px; line-height: 1.45; color: var(--warn);
  display: flex; align-items: flex-start; gap: 8px; margin: 0;
}
.ferry-warning-icon {
  font-size: 14px; flex-shrink: 0; line-height: 1.35;
}
.ferry-warning-action-col {
  flex: 0 0 78px;
  width: 78px;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-align: center;
  margin-left: auto;
}
.ferry-warning-cta {
  flex: 0 0 34px; width: 34px; height: 34px;
  box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; background: #FFFDF8; border: 1px solid #D6B97B;
  color: var(--accent-ink);
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.ferry-warning:hover .ferry-warning-cta,
.ferry-warning:focus-visible .ferry-warning-cta {
  background: #FFF4DC; border-color: var(--accent); color: var(--ink);
  box-shadow: 0 1px 4px rgba(183, 121, 31, .25);
}
.ferry-warning-cta .mode-arrow {
  font-size: 14px; font-weight: 700; transition: transform .15s ease;
}
.ferry-warning:hover .ferry-warning-cta .mode-arrow,
.ferry-warning:focus-visible .ferry-warning-cta .mode-arrow {
  transform: scale(1.25);
}
.ferry-warning-sub {
  width: 100%;
  font-size: 10px; font-weight: 500; line-height: 1.18; letter-spacing: .01em;
  color: var(--accent-ink); text-align: center; white-space: normal;
  transition: color .15s ease;
}
.ferry-warning:hover .ferry-warning-sub,
.ferry-warning:focus-visible .ferry-warning-sub {
  color: var(--ink);
}

/* Ferry fares on the map wear the ferry gold, so a crossing never reads as a
   toll at a glance. */
.toll-label.ferry-label span { color: var(--accent-ink); }

/* The fare table inside a crossing's popup. */
.pop-fares { border-collapse: collapse; margin: 6px 0 4px; width: 100%; }
.pop-fares td { padding: 1px 0; font-size: 12.5px; }
.pop-fares td.n { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.pop-note { font-size: 12px; color: var(--muted); margin-top: 3px; line-height: 1.4; }
.pop-note a { color: var(--brand-strong); }

/* A numbered barrier on the route: a white disc with a coloured ring and a
   coloured number, the same as the exported card. The number is the row in the
   list below, so the map and the table can be read against each other.

   Two things had to be got right and only one of them was obvious.

   `box-sizing`, because Leaflet anchors the icon at half of `iconSize`: without
   border-box the 2px ring pushed the real box out to 19px while the anchor
   stayed at 7.5, so the disc sat off-centre on the route line.

   And the selector has to out-rank `.leaflet-marker-icon`, which sets
   `display: block`. Leaflet's stylesheet is pulled in by the calculator's own
   head block, which lands *after* this file, so at equal specificity it won:
   the flex centring here was simply dead and the digit sat against the left
   edge of the disc, 2px in on one side and 9px on the other. Measuring the
   glyph box is what found it; it is invisible in the rules themselves. */
.leaflet-marker-icon.toll-pin {
  box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  background: #fff; color: var(--toll); border: 2px solid var(--toll);
  border-radius: 999px; font: 800 9px/1 var(--font);
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 2px rgba(15, 50, 35, .28);
}
.leaflet-marker-icon.toll-pin.ferry { color: var(--ferry); border-color: var(--ferry); }
.leaflet-marker-icon.toll-pin b { font-weight: 800; display: block; line-height: 1; }

/* ------------------------------------------------------------- the range */
.range {
  margin-top: 16px; padding: 15px 17px; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface);
  border-left: 4px solid var(--brand);
}
.range.short { border-left-color: var(--dear); background: var(--dear-bg); }
.range.warn { border-left-color: var(--warn); background: var(--warn-bg); }
.range h3 {
  margin: 0 0 4px; font-size: 12px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted);
}
.range-head { margin: 0 0 3px; font-size: 15.5px; font-weight: 700; }
.range.short .range-head { color: var(--dear); }
.range.warn .range-head { color: var(--warn); }
/* The actionable line: how much more to put in. */
.range-add { margin: 2px 0 0; font-size: 13.5px; font-weight: 600; }
.range.warn .range-add { color: var(--warn); }
.range.short .range-add { color: var(--dear); }
.range .tiny { margin: 0; color: var(--muted); }

/* Tank on the left, what the drive burns marked on it. The bar is the tank,
   the fill is what is in it, and the tick is where the trip ends, if the tick
   is past the fill you are walking. */
.gauge {
  position: relative; height: 12px; margin-top: 11px; border-radius: 999px;
  background: var(--line); overflow: hidden;
}
.gauge span {
  position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px;
  background: var(--brand);
}
.range.short .gauge span { background: var(--dear); }
.range.warn .gauge span { background: var(--warn); }
.gauge b {
  position: absolute; top: -3px; bottom: -3px; width: 3px;
  background: var(--ink); border-radius: 2px;
}

.check-line {
  display: flex; align-items: center; gap: 8px; font-size: 14.5px;
  margin: 10px 0 12px; cursor: pointer; font-weight: 600; flex-wrap: wrap;
}
.check-line .lighter { font-weight: 400; font-size: 13.5px; }
.check-line input { accent-color: var(--brand); width: 17px; height: 17px; }

.unit-input .unit { pointer-events: none; }

/* One line per control. Label, a short slider, the percentage you steer with,
   and the absolute amount beside it in grey. Everything is live in both
   directions, so there is no unit to switch and nothing to discover, which
   was the whole problem with the version this replaces.

   Flex rather than a fixed grid: the panel is 400 px wide in the app's left
   column and full width on a wide phone, and a rigid five-column grid
   collapsed a column to zero at the narrow end. Here the slider simply gives
   up its width first, and only below 360 px does it step out entirely. */
.lvl {
  display: flex; align-items: center; gap: 7px; margin-bottom: 8px;
  flex-wrap: nowrap;
}
.lvl > label {
  flex: 0 0 auto; max-width: 46%;
  font-size: 11.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .03em; line-height: 1.2;
}
.mini-slider {
  flex: 1 1 40px; min-width: 34px; margin: 0;
  -webkit-appearance: none; appearance: none;
  background: transparent;
  height: 18px;
  cursor: pointer;
}
.mini-slider::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--track-fill, #E2E8F0);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  border: 1px solid rgba(0, 0, 0, 0.08);
}
.mini-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  height: 16px;
  width: 16px;
  border-radius: 50%;
  background: var(--brand);
  margin-top: -6px;
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
  transition: transform .1s ease;
}
.mini-slider::-webkit-slider-thumb:hover {
  transform: scale(1.15);
}
.mini-slider::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--track-fill, #E2E8F0);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  border: 1px solid rgba(0, 0, 0, 0.08);
}
.mini-slider::-moz-range-thumb {
  height: 14px;
  width: 14px;
  border-radius: 50%;
  background: var(--brand);
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
  transition: transform .1s ease;
}
.mini-slider::-moz-range-thumb:hover {
  transform: scale(1.15);
}
.mini-slider:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 3px rgba(15, 107, 69, 0.35), 0 1px 3px rgba(0, 0, 0, 0.28);
}
.mini-slider:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 3px rgba(15, 107, 69, 0.35), 0 1px 3px rgba(0, 0, 0, 0.28);
}
.pct-box {
  flex: 0 0 46px; padding: 5px 6px; text-align: right;
  border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
  color: var(--ink); font: inherit; font-size: 13.5px; font-weight: 700;
}
.pct-sign { flex: 0 0 auto; font-size: 12.5px; color: var(--muted); }
.abs-side, .tank-only {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 3px;
}
.abs-side input, .tank-only input {
  width: 52px; padding: 5px 6px; text-align: right;
  border: 1px solid var(--line); border-radius: 8px;
  font: inherit; font-size: 13px;
  background: var(--surface-2); color: var(--muted);
}
.tank-only input { background: var(--surface); color: var(--ink); font-weight: 600; }
.abs-side i, .tank-only i { font-style: normal; font-size: 11.5px; color: var(--muted); }
.lvl .hint { vertical-align: 1px; }

@media (max-width: 360px) {
  .mini-slider { display: none; }
}

#gas-note { margin-top: 4px; }
#gas-note.warn {
  color: var(--dear); background: var(--dear-bg); padding: 9px 12px;
  border-radius: 9px; font-weight: 600;
}

.rh { font-size: 16px; margin: 26px 0 10px; font-weight: 700; }

/* --------------------------------------------- the ferry alternative box */
/* This is the one thing on the site no competitor shows, so it gets the one
   warm colour and sits above the breakdown rather than inside it. */
.alt {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  padding: 11px 12px;
  border-radius: var(--radius);
  background: var(--accent-tint);
  border: 1px dashed #D6B97B;
  box-shadow: 0 1px 3px rgba(183, 121, 31, 0.08);
}

.alt-thumb {
  flex: 0 0 58px;
  width: 58px;
  height: 58px;
  aspect-ratio: 1 / 1;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  border: 1px solid rgba(183, 121, 31, 0.25);
  background: #E8ECE9;
}

.alt-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.alt-body {
  flex: 1 1 auto;
  min-width: 0;
}

.alt-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 5px;
}

.alt-title-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
}

.alt h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent-ink);
}

.alt-mins {
  font-size: 11px;
  font-weight: 600;
  color: #785A1D;
  background: rgba(255, 255, 255, 0.7);
  padding: 1px 6px;
  border-radius: 6px;
}

.alt-saving {
  font-size: 13px;
  font-weight: 800;
  color: #0F6B45;
  background: #E1F2E8;
  border: 1px solid #B7DEC9;
  padding: 2px 7px;
  border-radius: 6px;
  white-space: nowrap;
}

.alt-compare {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: #4A3A17;
  flex-wrap: wrap;
}

.alt-opt {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid #EBD9B4;
  border-radius: 6px;
  padding: 2px 7px;
  font-size: 12px;
}

.alt-opt.win {
  border-color: #A3D4BA;
  background: #F0F8F4;
  color: #0F6B45;
  font-weight: 600;
}

.alt-opt b {
  font-size: 13px;
  font-weight: 700;
}

.alt-arrow {
  color: #8C7030;
  font-size: 13px;
  font-weight: 700;
}

.alt-note {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.35;
  color: #6A5324;
}

/* It states the toll-free answer, so it is the control that fetches it. The
   dashes stay: this is an offer, not a result, until you press it. */
.compare-free {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px dashed var(--line);
  font: inherit;
  font-size: 13px;
  text-align: left;
  color: inherit;
  cursor: pointer;
  box-sizing: border-box;
  transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.compare-free-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
}

.compare-free strong { flex-shrink: 0; }

.compare-free-action-col {
  flex: 0 0 78px;
  width: 78px;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-align: center;
  margin-left: auto;
}

.compare-free-cta {
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--muted);
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}

.compare-free-cta .mode-arrow {
  font-size: 14px;
  font-weight: 700;
  transition: transform .15s ease;
}

.compare-free-sub {
  width: 100%;
  font-size: 10px;
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: .01em;
  color: var(--muted);
  text-align: center;
  white-space: normal;
  transition: color .15s ease;
}

/* Green means tolls are in play, grey means they are not, and the rule holds
   wherever the pair appears. The switch shows the route you are *not* on, so
   it wears that route's colour: pressing the grey one takes the barriers out
   of the answer, pressing the green one puts them back. */
.compare-free.to-free {
  border-color: var(--line);
}
.compare-free.to-free strong {
  color: var(--muted);
}
.compare-free.to-free:hover,
.compare-free.to-free:focus-visible {
  background: var(--surface-2);
  border-color: var(--muted);
  border-style: solid;
  box-shadow: 0 2px 8px rgba(92, 112, 101, .15);
}
.compare-free.to-free:hover .compare-free-cta,
.compare-free.to-free:focus-visible .compare-free-cta {
  background: #E8ECE9;
  border-color: var(--muted);
  color: var(--ink);
  box-shadow: 0 1px 4px rgba(92, 112, 101, .20);
}
.compare-free.to-free:hover .compare-free-cta .mode-arrow,
.compare-free.to-free:focus-visible .compare-free-cta .mode-arrow {
  transform: scale(1.25);
}
.compare-free.to-free:hover .compare-free-sub,
.compare-free.to-free:focus-visible .compare-free-sub {
  color: var(--ink);
}

.compare-free.to-tolled {
  border-color: rgba(15, 107, 69, .35);
}
.compare-free.to-tolled strong {
  color: var(--brand-strong);
}
.compare-free.to-tolled .compare-free-cta {
  border-color: rgba(15, 107, 69, .35);
  color: var(--brand-strong);
  background: #F0F7F2;
}
.compare-free.to-tolled .compare-free-sub {
  color: var(--brand-strong);
}
.compare-free.to-tolled:hover,
.compare-free.to-tolled:focus-visible {
  background: var(--brand-tint);
  border-color: var(--brand);
  border-style: solid;
  box-shadow: 0 2px 8px rgba(15, 107, 69, .15);
}
.compare-free.to-tolled:hover .compare-free-cta,
.compare-free.to-tolled:focus-visible .compare-free-cta {
  background: #D7EADF;
  border-color: var(--brand-strong);
  color: var(--brand-strong);
  box-shadow: 0 1px 4px rgba(15, 107, 69, .20);
}
.compare-free.to-tolled:hover .compare-free-cta .mode-arrow,
.compare-free.to-tolled:focus-visible .compare-free-cta .mode-arrow {
  transform: scale(1.25);
}
.compare-free.to-tolled:hover .compare-free-sub,
.compare-free.to-tolled:focus-visible .compare-free-sub {
  color: var(--brand-strong);
}

/* And the answer itself carries the same signal: you can tell which of the two
   you are looking at without reading the tolls row.
   The whole card, not a gradient fading out by 62px, which is what this was
   first and it was invisible: against a white panel a tint that has already
   ended by the second row is not a signal, it is a rounding error. The inner
   boxes stay near-white, so they lift off whichever ground is behind them. */
/* Stronger than --brand-tint, which is sized for a chip on white and
   disappears when it has to colour a whole card. The total is near-black at
   38px, so there is plenty of room to go greener before contrast is a
   question. */
.totals.mode-tolled {
  background: #CBE4D5;
  border-color: rgba(15, 107, 69, .42);
}
.totals.mode-free {
  background: #E8ECE9;
  border-color: rgba(92, 112, 101, .30);
}
/* The stamp and the mode tag share the card's last line, so naming the answer
   costs no height. */
.stamp-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.stamp-row #stamp { margin: 0; }
.mode-tag {
  flex-shrink: 0; font-size: 11.5px; font-weight: 700;
  letter-spacing: .03em; white-space: nowrap;
  background: none; border: none; padding: 4px 9px;
  border-radius: 6px; font-family: inherit;
  display: inline-flex; align-items: center; gap: 5px;
}
.mode-tag:empty { display: none; }
.mode-tag.clickable {
  cursor: pointer;
  transition: all .14s ease;
}
.mode-arrow {
  font-size: 12px;
  font-weight: 700;
  opacity: 0.75;
  display: inline-block;
  transition: transform .14s ease, opacity .14s ease;
}
.mode-tag.clickable:hover .mode-arrow {
  opacity: 1;
  transform: scale(1.2);
}
.totals.mode-tolled .mode-tag {
  color: var(--brand-strong);
  background: var(--brand-tint);
  border: 1px solid rgba(15, 107, 69, 0.22);
}
.totals.mode-tolled .mode-tag.clickable:hover {
  background: rgba(15, 107, 69, 0.18);
  border-color: var(--brand);
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(15, 107, 69, 0.12);
}
.totals.mode-free .mode-tag {
  color: var(--ink);
  background: rgba(0, 0, 0, 0.06);
  border: 1px solid rgba(0, 0, 0, 0.14);
}
.totals.mode-free .mode-tag.clickable:hover {
  background: rgba(0, 0, 0, 0.10);
  border-color: rgba(0, 0, 0, 0.25);
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}
.mode-tag:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* The label above the total picks up the mode too, so the two states differ in
   more than one place and neither depends on colour alone. */
.totals.mode-tolled .total-main .label { color: var(--brand-strong); }
.totals.mode-free .total-main .label { color: var(--muted); }


/* The report control, on the total's own line rather than pinned to the top
   of the box. Absolutely positioned at the corner it floated a little above
   the price and read as unaligned with everything around it, so it rides in
   the flex row instead and centres on the figure it is about. */
.total-main .totals-report { margin-left: auto; align-self: center; }

/* --------------------------------------------------------- the toll list */
.legs { list-style: none; margin: 0; padding: 0; position: relative; }
.legs::before {
  content: ""; position: absolute; left: 21px; top: 16px; bottom: 16px;
  width: 2px; background: var(--line); z-index: 0;
}
.legs li {
  display: flex; align-items: baseline; gap: 12px; padding: 10px 14px;
  border: 1px solid var(--line); border-radius: 12px; margin-bottom: 8px;
  background: var(--surface); position: relative; z-index: 1;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.legs li:hover {
  border-color: #B4CBBF; box-shadow: 0 2px 8px rgba(15, 50, 35, .05);
}
.legs .no {
  flex: none; width: 22px; height: 22px; border-radius: 999px;
  background: #fff; color: var(--toll); border: 2px solid var(--toll);
  font: 800 11px/18px var(--font);
  text-align: center; font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 3px rgba(15, 50, 35, .1);
}
.legs .no.ferry { color: var(--ferry); border-color: var(--ferry); }
.legs .at { font-size: 12px; color: var(--muted); min-width: 58px; font-variant-numeric: tabular-nums; }
.legs .nm { flex: 1; min-width: 0; font-weight: 600; font-size: 14.5px; }
.legs .op { display: block; font-weight: 400; font-size: 12px; color: var(--muted); margin-top: 1px; }
.legs .amt { font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; font-size: 15.5px; }
.legs li.ferry { border-left: 4px solid var(--ferry); }
.legs li.toll { border-left: 4px solid var(--toll); }
.tag {
  display: inline-block; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .05em; padding: 2px 7px; border-radius: 999px;
  background: var(--brand-tint); color: var(--brand-strong); font-weight: 700;
  vertical-align: 1px;
}
.tag.approx { background: #FBF0D2; color: #7A5A10; }

.tiny { font-size: 12.5px; }
.muted { color: var(--muted); }

.directions { margin-top: 20px; }
.directions summary { cursor: pointer; font-size: 14px; color: var(--brand-strong); font-weight: 600; }
.steps { margin: 12px 0 0; padding: 0; list-style: none; font-size: 14px; }
.steps li {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 7px 0; border-bottom: 1px solid var(--line);
}
.steps li:last-child { border-bottom: 0; }
.steps b { color: var(--ink); font-weight: 700; }
.steps .road-name { font-weight: 400; color: var(--muted); }
.steps .step-km {
  color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ------------------------------------------------------------ autocomplete */
.ac-results {
  position: absolute; z-index: 950; left: 20px; right: 47px; top: 100%;
  margin-top: 4px; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow); overflow: hidden;
}
.ac-results button {
  display: block; width: 100%; text-align: left; padding: 9px 13px;
  border: 0; background: none; font: inherit; font-size: 14px; cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.ac-results button:last-child { border-bottom: 0; }
.ac-results button:hover, .ac-results button.on { background: var(--brand-tint); }
.ac-results .sub { display: block; font-size: 12px; color: var(--muted); }
.ac-note { padding: 9px 13px; font-size: 13px; color: var(--muted); }

/* ---------------------------------------------------------------- chips */
/* Sits directly under the buttons it fills in. The heading is screen-reader
   only, so there is no title bar adding height between the two. */
.popular { margin: 0 0 16px; }
.popular h2 {
  margin: 0 0 8px; font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted);
}
.chips { display: flex; flex-wrap: wrap; gap: 7px; }
.chip {
  background: var(--surface); border: 1px solid var(--line); border-radius: 999px;
  padding: 6px 13px; font: inherit; font-size: 13.5px; color: var(--ink); cursor: pointer;
}
.chip:hover { border-color: var(--brand); color: var(--brand-strong); text-decoration: none; }

/* ------------------------------------------------------- content pages */
.page { max-width: 820px; margin: 0 auto; padding: 30px 20px 70px; }
.page h1 { font-size: 32px; margin: 0 0 14px; font-weight: 800; }
.page h2 { font-size: 20px; margin: 30px 0 10px; }
.page p, .page li { font-size: 16px; }
.page .lede { font-size: 17.5px; color: var(--muted); }
.page code {
  background: var(--brand-tint); padding: 1px 5px; border-radius: 5px;
  font-size: 13.5px;
}
.notice {
  padding: 12px 15px; border-radius: 10px; background: var(--dear-bg);
  color: var(--dear);
}
/* `width: 100%` for the same reason it is on `.app`: these are flex items of
   #main, and the `margin: 0 auto` that centres them cancels the cross-axis
   stretch that would otherwise size them to the viewport. Without it the box
   falls back to fitting its content, which on /prices is a 1200 px table, and
   the whole page scrolled sideways on a phone. */
.wide, .page { width: 100%; }
.wide { max-width: 1200px; margin: 0 auto; padding: 30px 20px 70px; }

/* Route index, grouped by origin. Columns that reflow rather than a table:
   a real <table> with a column per origin cannot wrap on a phone without
   sideways scrolling, and this is a list of links, not tabular data. */
.route-groups {
  display: grid; gap: 14px; margin: 22px 0 8px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.route-group {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px;
}
.route-group h2 {
  margin: 0 0 8px; font-size: 15px; color: var(--brand-strong);
  text-transform: uppercase; letter-spacing: .04em;
}
.route-group ul { margin: 0; padding: 0; list-style: none; }
.route-group li { padding: 3px 0; }
.route-group a { font-size: 15px; }

/* -------------------------------------------------- per-route landing pages */
.route-page .lede { font-size: 18px; color: var(--ink); max-width: 70ch; }
.route-page .btn.primary { margin: 6px 0 10px; }
.crumbs {
  font-size: 13px; color: var(--muted); margin: 0 0 14px;
  display: flex; gap: 7px; flex-wrap: wrap;
}
.faq { margin: 0; }
.faq dt {
  font-weight: 700; margin: 18px 0 5px; font-size: 16.5px;
}
.faq dd { margin: 0; color: var(--muted); max-width: 72ch; }

.table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.table th, .table td {
  padding: 8px 11px; border-bottom: 1px solid var(--line); text-align: left;
  vertical-align: middle;
}
.table th {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); font-weight: 700; background: var(--bg);
  /* Not sticky. A sticky header inside a horizontally scrolling wrapper docks
     against the page, not the wrapper, so it parked itself on top of the first
     data row. The tables are grouped per operator and short enough not to need
     it. */
}
.table th.sortable {
  cursor: pointer;
  user-select: none;
  transition: color .12s ease, background-color .12s ease;
}
.table th.sortable:hover {
  color: var(--ink);
  background: var(--surface);
}
.sort-icon {
  display: inline-block;
  margin-left: 4px;
  font-size: 10px;
  opacity: 0.55;
  vertical-align: middle;
}
th.sortable[aria-sort="ascending"] .sort-icon,
th.sortable[aria-sort="descending"] .sort-icon {
  opacity: 1;
  color: #0284C7;
}

/* Numbers right-aligned and so are their headers, so a price sits under the
   category it belongs to instead of drifting left of it. */
.table td.n, .table th.n { text-align: right; font-variant-numeric: tabular-nums;
  white-space: nowrap; vertical-align: middle; }
.table td.n { padding-right: 18px; }
.table th.n { padding-right: 18px; }

/* Centered columns for values and headers */
.table td.c, .table th.c {
  text-align: center;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  vertical-align: middle;
}
.table td.c { padding: 10px 14px; }
.table th.c { padding: 8px 14px; }

.table th.report-col, .table td.report-cell {
  width: 32px; min-width: 32px; text-align: center; padding: 6px 6px 6px 2px;
  vertical-align: middle;
}
.table td.report-cell .warn-btn {
  width: 24px; height: 24px; vertical-align: middle;
}
.table tbody tr:hover { background: var(--surface); }
.scroll-x { overflow-x: auto; }
/* Full headings everywhere but the phone, where the media query swaps them. */
.lbl-short { display: none; }
.lbl-long { display: inline; }
.op-block { margin-bottom: 42px; }
.op-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 16px;
}
.op-header-info {
  flex: 1;
  min-width: 240px;
}
.op-block h2 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0;
}
.op-block h2 span { font-size: 13.5px; font-weight: 600; color: var(--muted); }
.op-meta-pills {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.pill-chip {
  font-size: 12px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--brand-tint);
  color: var(--brand-strong);
  border: 1px solid rgba(15, 107, 69, 0.15);
}
.pill-chip.subtle {
  background: var(--surface);
  color: var(--muted);
  border-color: var(--line);
  font-weight: 500;
}
/* The one that is a link, so it does not read as another count. */
.pill-chip.src {
  background: transparent;
  border-style: dashed;
  text-decoration: none;
}
.pill-chip.src:hover {
  background: var(--brand-tint);
  border-style: solid;
}
.op-map-preview-box {
  flex-shrink: 0;
  width: 240px;
}
.op-map-link {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 2 / 1;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #E8F4F8;
  transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.op-map-link:hover {
  transform: translateY(-2px);
  border-color: #0284C7;
  box-shadow: 0 4px 14px rgba(2, 132, 199, .22);
}
.op-map-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.op-map-badge {
  position: absolute;
  bottom: 5px;
  right: 5px;
  font-size: 9.5px;
  font-weight: 600;
  color: #0A3858;
  background: rgba(255, 255, 255, .68);
  border: 1px solid rgba(255, 255, 255, .5);
  padding: 1px 5px;
  border-radius: 4px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
  transition: all .15s ease;
}
.op-map-link:hover .op-map-badge {
  background: #0284C7;
  border-color: #0284C7;
  color: #FFFFFF;
}

@media (max-width: 640px) {
  .op-header-row {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .op-map-preview-box {
    width: 100%;
  }
  .op-map-link {
    width: 100%;
    aspect-ratio: 2 / 1;
    height: auto;
  }
}
.flat-fare {
  margin: 0 0 8px; padding: 12px 15px; border-radius: 10px;
  background: var(--brand-tint); font-size: 15px;
}
.flat-fare strong { font-size: 22px; font-weight: 800; color: var(--brand-strong); }
.flat-fare .muted { display: block; font-size: 13px; margin-top: 4px; }

.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow);
}
.card h3 {
  margin: 0 0 10px;
  font-size: 16px;
  line-height: 1.3;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}
.card dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; font-size: 14px; }
.card dt { color: var(--muted); }
.card dd { margin: 0; font-weight: 600; text-align: right; }

/* Ferry table: full-width catalog table matching toll prices layout */
.ferry-table {
  margin-top: 18px;
}
.ferry-name-cell {
  min-width: 320px;
}
.ferry-cell-row {
  display: flex;
  align-items: center;
  gap: 16px;
}
.ferry-thumb-link {
  position: relative;
  display: block;
  width: 105px;
  min-width: 105px;
  height: 105px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #E8F4F8;
  flex-shrink: 0;
  transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.ferry-thumb-link:hover {
  transform: scale(1.03);
  border-color: #0284C7;
  box-shadow: 0 4px 14px rgba(2, 132, 199, .24);
}
.ferry-thumb-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ferry-thumb-link .ferry-map-btn {
  position: absolute;
  bottom: 5px;
  right: 5px;
  font-size: 9.5px;
  font-weight: 600;
  color: #0A3858;
  background: rgba(255, 255, 255, .62);
  border: 1px solid rgba(255, 255, 255, .5);
  padding: 1px 5px;
  border-radius: 4px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
  transition: all .15s ease;
}
.ferry-thumb-link:hover .ferry-map-btn {
  background: #0284C7;
  border-color: #0284C7;
  color: #FFFFFF;
  box-shadow: 0 2px 6px rgba(2, 132, 199, .35);
}
.ferry-cell-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.d-block {
  display: block;
}

/* Mobile sort bar */
.mobile-sort-bar {
  display: none;
  align-items: center;
  gap: 8px;
  margin: 12px 0 16px;
}
.mobile-sort-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.mobile-sort-chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 2px 0;
}
.mobile-sort-chips::-webkit-scrollbar { display: none; }
.mobile-sort-chips .chip {
  cursor: pointer;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  transition: all .12s ease;
}
.mobile-sort-chips .chip.active {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}

.ferry-duration-tag {
  display: none;
}

@media (max-width: 680px) {
  .wide {
    padding: 16px 12px 60px;
  }
  
  .mobile-sort-bar {
    display: flex;
  }

  /* Op Jump Bar */
  .op-jump-bar {
    margin: 10px 0 18px;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 2px 0;
  }
  .op-jump-bar::-webkit-scrollbar { display: none; }
  .op-jump-bar .chip {
    white-space: nowrap;
    flex-shrink: 0;
    font-size: 13px;
  }

  /* Ferry table reflow into clean mobile cards */
  .ferry-table thead {
    display: none;
  }
  .ferry-table,
  .ferry-table tbody {
    display: block;
    width: 100%;
  }
  .ferry-table tbody tr {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 12px 14px;
    margin-bottom: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,.03);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 6px;
  }
  .ferry-table td.ferry-name-cell {
    width: 100%;
    min-width: 0;
    padding: 0;
    border: none;
    margin-bottom: 4px;
  }
  .ferry-cell-row {
    display: flex;
    gap: 12px;
    align-items: center;
  }
  .ferry-thumb-link {
    width: 76px;
    min-width: 76px;
    height: 76px;
  }
  .ferry-cell-info {
    flex: 1;
    min-width: 0;
    padding-right: 28px;
  }
  .ferry-cell-info strong {
    font-size: 15px;
    line-height: 1.3;
  }
  .ferry-duration-tag {
    display: inline-block;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--brand-strong);
    background: var(--brand-tint);
    padding: 1px 6px;
    border-radius: 4px;
    margin-left: 6px;
    vertical-align: middle;
  }
  
  /* 3-column prices strip on mobile, perfectly aligned */
  .ferry-table td.price-cell {
    flex: 1 1 calc(33.333% - 6px);
    min-width: 0;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 7px 4px 6px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center !important;
    font-size: 13.5px;
    font-weight: 700;
    box-sizing: border-box;
  }
  .ferry-table td.price-cell::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 10.5px;
    font-weight: 600;
    margin-bottom: 2px;
    text-transform: uppercase;
    letter-spacing: .02em;
    display: block;
    text-align: center;
  }
  
  .ferry-table td.duration-cell {
    display: none;
  }
  
  .ferry-table td.report-cell {
    position: absolute;
    top: 10px;
    right: 10px;
    width: auto;
    min-width: 0;
    padding: 0;
    border: none;
  }

  /* The toll table stays a table on a phone, and gets dense.
     Sideways scrolling was the original bug: the header scrolled away with the
     columns, so «1,40 €» could be a motorbike or a car with nothing left on
     screen to say which, and two of the four fares were unreachable. Reflowing
     each row into a card fixed that and cost far too much height, a screenful
     for three barriers out of a hundred and fifty.
     So: drop the road, which the operator heading above already lists; shrink
     the fares to fixed narrow columns; keep the header on screen while you
     scroll past it. All four prices, no sideways scroll, four rows a screen. */
  /* The wrapper's `overflow-x: auto` has to go, and not only because the
     dense table no longer needs it. A scroll container on one axis becomes one
     on both, and `position: sticky` then sticks to *that* box rather than to
     the viewport: the header parked itself four rows down the table and sat on
     top of them. */
  .op-block .scroll-x { overflow-x: visible; }
  .toll-table { font-size: 12px; table-layout: fixed; width: 100%; }
  .toll-table th, .toll-table td { padding: 7px 3px; }
  .toll-table thead th {
    position: sticky;
    /* Under the site's own sticky header rather than behind it. */
    top: var(--topbar-h, 117px);
    z-index: 2;
    font-size: 9.5px;
    padding: 6px 3px;
    background: var(--bg);
    box-shadow: inset 0 -1px 0 var(--line);
  }
  .toll-table .lbl-long { display: none; }
  .toll-table .lbl-short { display: inline; }
  .toll-table td.name-cell, .toll-table th:first-child {
    width: auto;
    padding-left: 2px;
    line-height: 1.25;
    font-weight: 600;
    overflow-wrap: anywhere;
  }
  .toll-table td.n, .toll-table th.n { width: 50px; padding-right: 4px; }
  .toll-table td.n { font-weight: 700; }
  /* The road repeats the operator heading on every one of its rows. */
  .toll-table td.road-cell, .toll-table th:nth-child(2) { display: none; }
  .toll-table td.report-cell, .toll-table th.report-col { width: 18px; padding: 0; }
  /* The source arrow costs a whole column's width beside a price. It stays on
     the operator's own heading, where one link covers the whole table. */
  .toll-table td .src-link { display: none; }
  .toll-table .tag { font-size: 9.5px; padding: 0 4px; margin-left: 3px; }
}

/* One line. It was 147px, a third of the fold on a laptop, for links nobody
   visits the site to click. The estimate caveat that made up half of that now
   sits at the end of the content, next to the numbers it is about. */
footer {
  border-top: 1px solid var(--line); background: var(--surface);
  padding: 6px 20px; text-align: center;
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: center; gap: 2px 12px;
  font-size: 11px; line-height: 1.45;
}
footer nav { display: flex; gap: 11px; flex-wrap: wrap; }
footer nav a { font-size: 11px; font-weight: 600; color: var(--muted); }
footer nav a:hover { color: var(--brand-strong); }
footer .foot-meta { color: var(--muted); opacity: .8; }

/* ------------------------------------------- floating result shortcut */
/* Follows you down the panel with the running total on it, and takes you to
   the breakdown. Grey and inert until there is a route to price, so it never
   promises a number it does not have. */
/* Two positioning schemes, because the two layouts scroll differently.
   On a phone the *page* scrolls, so `fixed` is the only thing that keeps the
   pill on screen: sticky would leave it parked at its natural position far
   down the document until you had almost reached the answer anyway.
   On desktop the *panel* scrolls inside itself, so sticky pins the pill to the
   bottom of that column, which is exactly the scope wanted, and it can never
   stray over the map. */
.result-peek {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 60;
  display: flex; align-items: center; gap: 12px; justify-content: space-between;
  padding: 11px 18px; border-radius: 14px; cursor: pointer; text-align: left;
  border: 1px solid var(--brand); background: var(--brand); color: #fff;
  font: inherit; box-shadow: 0 6px 22px rgba(15, 50, 35, .3);
  transition: opacity .15s ease;
}
@media (min-width: 900px) {
  .result-peek {
    position: fixed; left: 28px; right: auto; bottom: 20px;
    width: max-content; max-width: min(calc(40vw - 56px), 480px);
    margin: 0;
  }
}
@media (min-width: 1400px) {
  .result-peek {
    max-width: 504px;
  }
}
/* Once the totals are on screen the shortcut has nothing left to shortcut. */
.result-peek.past {
  opacity: 0; pointer-events: none; transform: translateY(8px);
}
.result-peek.waiting {
  background: var(--surface); color: var(--muted); border-color: var(--line);
  box-shadow: 0 4px 16px rgba(15, 50, 35, .14); cursor: default;
}
.peek-main {
  display: flex; align-items: baseline; gap: 7px; min-width: 0;
}
.peek-price {
  font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}
.result-peek.waiting .peek-price { font-size: 14px; font-weight: 700; }
/* The breakdown beside the total. It is the part that gives way when the
   screen is narrow: it truncates rather than wrapping, so the pill keeps its
   one-line height no matter what is in it. */
.peek-split {
  font-size: 11.5px; opacity: .82; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.peek-split:empty { display: none; }
.peek-cta { font-size: 11.5px; opacity: .9; flex: 0 0 auto; }
.result-peek:not(.waiting) .peek-cta::after { content: " ↓"; }

/* Below this the words in the call to action are what the breakdown needs, so
   the arrow speaks for itself and the numbers get the room. */
@media (max-width: 430px) {
  .result-peek:not(.waiting) .peek-cta { font-size: 0; }
  .result-peek:not(.waiting) .peek-cta::after { font-size: 15px; }
}

/* Waiting, it says one short thing and does not need the full width. */
@media (max-width: 899px) {
  .result-peek.waiting { left: auto; justify-content: flex-start; }
}

/* ------------------------------------------------------------------ ads */
.ad-slot {
  display: none !important;
  margin: 26px 0; min-height: 92px; border: 0;
  background: transparent; font-size: 12px; color: var(--muted);
}
/* The map menu, from a right click or a long press.
   Leaflet's popup chrome is built for text, so the padding and the tail are
   taken off and the menu supplies its own. */
.map-menu-pop .leaflet-popup-content-wrapper {
  padding: 0; border-radius: 12px; overflow: hidden;
  box-shadow: 0 10px 30px rgba(15, 50, 35, .22);
}
.map-menu-pop .leaflet-popup-content { margin: 0; width: auto !important; }
.map-menu-pop .leaflet-popup-tip { box-shadow: none; }

.map-menu { min-width: 194px; padding: 5px; background: var(--surface); }
.mm-row {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 8px;
  background: none; font: inherit; font-size: 14px; color: var(--ink);
  text-align: left; cursor: pointer;
  transition: background .12s ease;
}
.mm-row:hover, .mm-row:focus-visible { background: var(--brand-tint); }
.mm-row.danger:hover, .mm-row.danger:focus-visible {
  background: var(--dear-bg); color: var(--dear);
}
/* The same badges as the stop rows, so the menu and the form read as one list. */
.mm-badge {
  flex-shrink: 0; width: 21px; height: 21px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 800; color: #fff; background: var(--muted);
}
.mm-badge.from { background: var(--brand); }
.mm-badge.to { background: var(--dear); }
.mm-badge.via { background: var(--muted); font-size: 12px; }
.mm-badge.clear { background: transparent; color: var(--muted); font-size: 13px; }
.mm-row.danger:hover .mm-badge.clear { color: var(--dear); }
.mm-sep { height: 1px; margin: 4px 6px; background: var(--line); }
.mm-hint {
  padding: 5px 11px 6px; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* A long press is the phone's version of a right click, so the targets are
   sized for a thumb rather than a cursor. */
@media (max-width: 600px) {
  .map-menu { min-width: 210px; }
  .mm-row { padding: 11px 12px; font-size: 15px; }
}

/* The map page's own slot. The map is full-bleed and the ad is not, so it
   gets the same gutters as the rest of the site's content. */
.map-ad { max-width: 1200px; margin: 0 auto; padding: 0 20px; width: 100%; }
.map-ad .ad-slot { margin: 18px 0 24px; }

/* Ezoic writes its own markup into the placeholder, so there is nothing of
   ours to frame. The reserved height stays: an ad arriving into zero height
   shoves the page down under whoever is reading it, which is the layout shift
   Core Web Vitals actually measures. 250 is the tallest of the common
   rectangles, so the space is right more often than it is wrong. */
.ad-slot.ez {
  display: block; border: 0; background: none; min-height: 250px;
}
@media (max-width: 600px) { .ad-slot.ez { min-height: 280px; } }
/* The live consent control on the privacy page: which of the two is in force,
   and both of them pressable. */
#consent-state { margin: 10px 0 18px; }
.cs-now {
  margin: 0 0 8px; font-size: 12px; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
.cs-saved { margin-left: 8px; color: var(--brand-strong); text-transform: none;
            letter-spacing: 0; }
.cs-opts { display: flex; gap: 8px; flex-wrap: wrap; }
.cs-opt {
  padding: 9px 15px; border-radius: 9px; cursor: pointer;
  font: inherit; font-size: 14px;
  background: var(--surface); color: var(--muted);
  border: 1px solid var(--line);
  transition: all .14s ease;
}
.cs-opt:hover { border-color: var(--brand); color: var(--brand-strong); }
.cs-opt.on {
  background: var(--brand-tint); color: var(--brand-strong);
  border-color: var(--brand); cursor: default;
}
.cs-tick { margin-right: 7px; }

/* A modal, not a strip along the bottom. A strip gets scrolled past and never
   answered, which leaves every visitor unasked and every ad slot empty. */
.consent-wrap {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(18, 33, 26, .55);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: consent-in .18s ease-out;
}
@keyframes consent-in { from { opacity: 0 } to { opacity: 1 } }
.consent {
  width: 100%; max-width: 460px;
  background: var(--surface); border-radius: var(--radius);
  box-shadow: 0 18px 50px rgba(15, 50, 35, .3);
  padding: 22px 24px 20px;
}
.consent-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}
.consent h2 { margin: 0; font-size: 18px; font-weight: 800; }
.consent-lang {
  flex-shrink: 0; font-size: 12.5px; font-weight: 700; color: var(--muted);
  border: 1px solid var(--line); border-radius: 6px; padding: 2px 8px;
  text-decoration: none;
}
.consent-lang:hover {
  color: var(--brand-strong); border-color: var(--brand); text-decoration: none;
}
.consent p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }
.consent p a { color: var(--brand-strong); }
.consent-intro { margin-bottom: 14px !important; color: var(--ink) !important; }

/* Two named groups rather than one paragraph. Nothing here is bold: the
   headings are set apart by case and colour, which is enough at this size and
   does not shout at somebody who only wants to press a button. */
.consent-cats { display: flex; flex-direction: column; gap: 12px; margin-bottom: 14px; }
.consent-cat {
  padding: 11px 13px; border-radius: 9px;
  background: var(--surface-2); border: 1px solid var(--line);
}
.consent-cat-h {
  display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px;
  font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink);
}
.consent-cat-tag {
  font-size: 10.5px; letter-spacing: .02em; text-transform: none;
  color: var(--muted);
}
.consent-cat p { font-size: 13px; }
.consent-foot {
  margin: 0 0 16px !important; font-size: 12px !important; opacity: .85;
}
.consent-btns { display: flex; flex-direction: column; gap: 8px; }
.consent-btns button {
  width: 100%; padding: 11px 16px; border-radius: 10px;
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
  border: 1px solid transparent; transition: all .14s ease;
}
/* Accepting is the primary action and looks like it. Declining is a real
   choice and a plain one, which is the line Google's own policy draws. */
.consent-btns .primary { background: var(--brand); color: #fff; }
.consent-btns .primary:hover { background: var(--brand-strong); }
.consent-btns .ghost {
  background: var(--surface); color: var(--muted); border-color: var(--line);
}
.consent-btns .ghost:hover { background: var(--surface-2); color: var(--ink); }
@media (min-width: 480px) {
  .consent-btns { flex-direction: row-reverse; }
  .consent-btns button { width: auto; flex: 1; }
}

/* --------------------------------------------------------------- the map */
/* Standard OSM tiles, untinted. A filtered pastel basemap matched the brand
   and was harder to read, road numbers and place names washed out, and on a
   map whose entire job is "which road is that", legibility wins. */
.leaflet-container { font: inherit; background: #E7EEE8; }

/* Toll prices, printed beside their dot, with no click required. A halo
   instead of a box: 139 little white rectangles over a map is a rash, but text
   outlined against the tiles stays readable and nearly disappears. */
.toll-label span {
  font: 700 10.5px/1 var(--font);
  color: #0A4E32; white-space: nowrap;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff, 0 0 2px #fff;
  opacity: .85;
}
.toll-label.on-route span {
  font-size: 11.5px; font-weight: 800; color: #0A4E32; opacity: 1;
}
/* ----------------------------------------------- standalone map (fullpage) */
.map-fullpage {
  position: relative;
  width: 100%;
  flex: 1 1 auto;
  min-height: calc(100vh - 90px);
  display: flex;
  overflow: hidden;
}
.map-fullpage .fullscreen-map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}
.map-hud {
  position: absolute;
  top: 18px;
  left: 18px;
  z-index: 500;
  width: 320px;
  max-width: calc(100vw - 36px);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  box-shadow: 0 6px 24px rgba(15, 50, 35, 0.12);
}
.map-hud-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
}
.map-hud h1 {
  margin: 0;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.hud-badge {
  font-size: 11px;
  font-weight: 700;
  color: var(--brand-strong);
  background: var(--brand-tint);
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.map-hud-lede {
  margin: 0 0 12px;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.4;
}
.map-hud-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  font-weight: 600;
}
.map-hud-footer a { color: var(--brand-strong); }

@media (max-width: 600px) {
  .map-fullpage {
    min-height: calc(100vh - 100px);
  }
  /* Docked to the bottom instead of floating over the top.
     Full width at the top it took a quarter of a phone screen, covered the
     part of the country you had just scrolled to, and parked itself on top of
     Leaflet's own zoom buttons and layer switch. At the bottom it is in reach
     of a thumb and the map keeps the corners its controls live in. */
  .map-hud {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    border-radius: 14px 14px 0 0;
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -2px 14px rgba(0, 0, 0, .08);
  }
  .map-hud-header { margin-bottom: 8px; }
  .map-hud h1 { font-size: 16px; }
  .map-hud-lede { display: none; }
  .map-hud .field { margin-bottom: 0 !important; }
  /* The options name the categories themselves, so the field label is a line
     of screen the map can have back. Kept for screen readers. */
  .map-hud .field > label {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
  }
  .map-hud-footer { margin-top: 10px; padding-top: 9px; font-size: 12.5px; }
  /* Leaflet's attribution and zoom sit in the bottom corners, which the panel
     now covers. Lifted clear rather than hidden: the OpenStreetMap credit is a
     licence condition, not decoration. `--hud-h` is measured in tollmap.js,
     with a sensible value here in case the script never runs. */
  .map-fullpage { --hud-h: 118px; }
  .map-fullpage .leaflet-bottom { bottom: var(--hud-h); }
  .map-fullpage .leaflet-control-attribution { font-size: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
