/* Cycle from NY to CA — the journal page (on top of site.css).
   A gallery wall: muted print-like map, one moss line for the road, photographs as the hero.

   Readability rules applied at every screen size:
   - body text ≥ 17px, labels and numbers ≥ 14px (0.875rem); no text smaller except map attribution
   - text colours meet WCAG AA contrast on --paper (graphite 5.4:1, moss 6.2:1, ink 14:1)
   - every control is ≥ 44 × 44px on touch screens
   - photos are never cropped (object-fit: contain inside a frame shaped like the day's photos)

   Layouts: phone < 700px (stacked) · tablet 700–1099px (stacked, centred 680px column; map pinned on top when upright)
            desktop ≥ 1100px (map 50% | journal 40%, margins and gutter share the remaining 10%) */
:root {
  /* Colours, fonts, type scale, --margin and --tap come from site.css (loaded first). */
  --numeral: #a3a8a3;
  --gap: 0px;
  --mast: auto;
}

/* --- Journal intro --- */
.journal-intro {
  margin: 1.25rem 0 1rem;
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--graphite);
}

.journal-page .layout {
  padding-top: 1rem;
}

.unit-toggle,
.lang-toggle {
  display: flex;
  font-family: var(--display);
  font-size: var(--fs-data);
}

.unit-toggle button,
.lang-toggle button {
  min-width: var(--tap);
  min-height: var(--tap);
  border: 0;
  background: none;
  padding: 0 0.5rem;
  color: var(--graphite);
  cursor: pointer;
}

.unit-toggle button[aria-pressed='true'],
.lang-toggle button[aria-pressed='true'] {
  color: var(--ink);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--moss);
  text-decoration-thickness: 2px;
  text-underline-offset: 5px;
}

/* --- Page layout (phone first: map on top, journal below) --- */
.layout {
  display: block;
}

.map-frame {
  height: clamp(260px, 48svh, 560px);
  margin-bottom: 1.25rem;
  border: 1px solid var(--hairline);
  background: var(--paper-deep);
}

#map {
  width: 100%;
  height: 100%;
  /* Same grey as the filtered tiles, so tile edges never show during zoom animations. */
  background: #ececea;
}

.sidebar {
  min-height: 0;
  display: flex;
  flex-direction: column;
}




.day-list {
  padding-bottom: 3rem;
}

/* --- Map styling: a grey print with one moss line --- */
/* The grey filter sits on each tile, not on the layer: a filter on the layer that animates during zoom has to
   be re-applied to the whole map every frame, while a tile's filter is painted once with the tile.
   The 1px overlap stops sub-pixel hairlines between tiles when Leaflet shows them scaled on 2x/3x screens. */
.tiles-muted img.leaflet-tile {
  filter: grayscale(1) contrast(0.86) brightness(1.07);
  width: 257px !important;
  height: 257px !important;
}

.leaflet-container {
  font-family: var(--display);
  font-size: var(--fs-label);
}

.leaflet-control-zoom a,
.leaflet-control-layers {
  border-radius: 0 !important;
  border-color: var(--hairline) !important;
  color: var(--ink) !important;
}

.leaflet-bar {
  border: 1px solid var(--hairline) !important;
  box-shadow: none !important;
}

.leaflet-control-layers {
  box-shadow: none !important;
  border: 1px solid var(--hairline) !important;
  background: var(--paper) !important;
}

.leaflet-control-layers label {
  min-height: 32px;
  display: flex;
  align-items: center;
}

.leaflet-control-attribution {
  background: rgb(244 245 242 / 0.85) !important;
  font-size: 0.6875rem;
}


.route-tip {
  font-family: var(--display);
  font-size: var(--fs-label);
  border-radius: 0;
  border: 1px solid var(--hairline);
  box-shadow: none;
}

.pin {
  display: block;
  width: 10px;
  height: 10px;
  margin: 2px;
  border-radius: 50%;
  border: 2px solid var(--paper);
  background: var(--graphite);
  box-shadow: 0 0 0 1px rgb(31 38 34 / 0.25);
}

.pin--camp,
.pin--stay,
.pin--host {
  background: var(--ink);
}

.pin--bike_shop,
.pin--sight {
  background: var(--moss);
}


.pin--legend {
  display: inline-block;
  vertical-align: -1px;
  margin: 0 0.4rem 0 0.2rem;
}

.leaflet-popup-content-wrapper {
  border-radius: 0;
  box-shadow: 0 6px 24px rgb(31 38 34 / 0.12);
}

.leaflet-popup-content {
  font-size: var(--fs-data);
  line-height: 1.4;
}

.popup__type {
  font-size: var(--fs-label);
  color: var(--graphite);
}

.popup__name {
  font-family: var(--display);
  font-variation-settings: 'wdth' 85;
  font-weight: 650;
  font-size: 1.0625rem;
  margin: 2px 0;
}

.popup__comment {
  margin: 6px 0;
  font-family: var(--text);
  font-size: 1rem;
  line-height: 1.45;
}

.popup__cost {
  font-size: var(--fs-label);
}


/* --- Journal: one entry per day, numbered because it is a sequence --- */
.day {
  border-bottom: 1px solid var(--hairline);
}

.day__header {
  width: 100%;
  display: grid;
  grid-template-columns: 3.25rem 1fr;
  align-items: baseline;
  gap: 0.5rem;
  padding: 1rem 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}

.day__number {
  font-family: var(--display);
  font-variation-settings: 'wdth' 62;
  font-weight: 800;
  font-size: 2.5rem;
  line-height: 0.8;
  color: var(--numeral);
  font-variant-numeric: tabular-nums;
  transition: color 0.2s;
}

.day.is-open .day__number {
  color: var(--moss);
}

@media (hover: hover) {
  .day__header:hover .day__number {
    color: var(--moss);
  }
}

.day__heading {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.day__date {
  font-family: var(--display);
  font-size: var(--fs-label);
  color: var(--graphite);
}

.day__title {
  font-family: var(--display);
  font-variation-settings: 'wdth' 88;
  font-weight: 620;
  font-size: var(--fs-title);
  line-height: 1.2;
  overflow-wrap: anywhere;
}

.day__highlight {
  font-style: italic;
  font-size: 1rem;
  color: var(--graphite);
}

.day__body {
  display: none;
  padding: 0.25rem 0 2.5rem;
}

.day.is-open .day__body {
  display: block;
}

.day__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.5rem;
  margin: 1rem 0 1.25rem;
  font-family: var(--display);
  font-size: var(--fs-data);
  font-variant-numeric: tabular-nums;
}

/* The day's ride(s) on Strava, after the numbers they come from. The link is 44px tall to tap, but its
   negative margins keep the stats row the same height as before. */
.strava-links {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--graphite);
}

.strava-link {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  min-height: var(--tap);
  margin-block: -0.75rem;
  padding: 0 0.15rem;
  color: var(--moss);
  font-weight: 600;
  text-decoration: none;
}

.strava-link__arrow {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (hover: hover) {
  .strava-link:hover { text-decoration: underline; text-underline-offset: 3px; }
}

/* The open day's elevation profile, under its stats. The chart pans the page vertically on touch; a
   sideways drag moves the cursor (and the dot on the map). */
.profile { margin: -0.25rem 0 1.5rem; }

.profile__readout {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.25rem;
  min-height: 1.6em;
  margin: 0 0 0.35rem;
  font-family: var(--display);
  font-size: var(--fs-data);
  font-variant-numeric: tabular-nums;
}

.profile__muted { color: var(--graphite); }

.profile__chart {
  display: block;
  width: 100%;
  height: 140px;
  touch-action: pan-y;
  cursor: crosshair;
  outline: none;
}

.profile__chart:focus-visible { box-shadow: 0 0 0 2px var(--moss); }
.profile__area { fill: var(--moss-wash); }
.profile__line { fill: none; stroke: var(--moss); stroke-width: 2; stroke-linejoin: round; }
.profile__grid { stroke: var(--hairline); stroke-width: 1; }
.profile__label { font-family: var(--display); font-size: 12px; fill: var(--graphite); font-variant-numeric: tabular-nums; }
.profile__peak { fill: var(--moss); }
.profile__peak-label { font-family: var(--display); font-size: 12px; font-weight: 600; fill: var(--ink); }
.profile__cursor { stroke: var(--ink); stroke-width: 1; }
.profile__dot { fill: var(--paper); stroke: var(--ink); stroke-width: 2; }

.profile__hint {
  margin: 0.35rem 0 0;
  font-family: var(--display);
  font-size: var(--fs-label);
  color: var(--graphite);
}

.day__story p {
  margin: 0 0 1em;
  font-size: var(--fs-body);
  line-height: 1.7;
  max-width: 64ch;
  white-space: pre-line;
  overflow-wrap: break-word;
}

.day__weather {
  margin: 0 0 1rem;
  font-style: italic;
  font-size: 1rem;
  color: var(--graphite);
}

.day__more summary {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  font-family: var(--display);
  font-size: var(--fs-data);
  color: var(--moss);
  cursor: pointer;
  list-style: none;
}

.day__more summary::-webkit-details-marker {
  display: none;
}

.day__more summary::after {
  content: '+';
  margin-left: 0.4em;
}

.day__more[open] summary::after {
  content: '–';
}

.day-spend,
.day-extras {
  margin: 0.75rem 0 0;
  font-family: var(--display);
  font-size: var(--fs-label);
  line-height: 1.5;
  color: var(--graphite);
}

.place-list {
  list-style: none;
  margin: 0.25rem 0 0;
  padding: 0;
}

.place-list li + li {
  border-top: 1px solid var(--hairline);
}

.place-link {
  width: 100%;
  min-height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.25rem 0;
  border: 0;
  background: none;
  font-family: var(--display);
  font-size: var(--fs-data);
  text-align: left;
  cursor: pointer;
}

@media (hover: hover) {
  .place-link:hover span:first-child {
    color: var(--moss);
  }
}

.place-list__comment {
  margin: -0.25rem 0 0.75rem;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--graphite);
}

/* The slideshow (photos at their own proportions, crossfading every 8 s) lives in site.css: the About page uses it too. */

/* Chinese stories: a touch more line height and no italic (CJK fonts have none). */
.day__story:lang(zh-Hant) p {
  line-height: 1.85;
  letter-spacing: 0.02em;
  line-break: strict;
}

/* --- Instagram vlog: first slide of the carousel --- */
.reel-slide {
  position: absolute;
  inset: 0;
  display: block;
  color: var(--ink);
  text-decoration: none;
  -webkit-user-drag: none;
}

.reel-slide img {
  width: 100%;
  height: 100%;
  object-fit: contain; /* 9:16 cover inside the photos' frame: never cropped */
  display: block;
}

/* "Instagram ↗": where the slide goes, in the corner — not a play button, which would promise playback here. */
.reel-chip {
  position: absolute;
  left: 0.75rem;
  bottom: 0.75rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.7rem 0.45rem 0.55rem;
  border-radius: 999px;
  background: rgb(31 38 34 / 0.72);
  color: #fff;
  font-family: var(--display);
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background 0.15s;
}

.reel-chip svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.reel-chip__logo {
  width: 1.15rem;
  height: 1.15rem;
}

.reel-chip__dot {
  fill: currentColor;
  stroke: none;
}

.reel-chip__arrow {
  width: 0.85rem;
  height: 0.85rem;
  opacity: 0.85;
}

@media (hover: hover) {
  .reel-slide:hover .reel-chip {
    background: rgb(31 38 34 / 0.9);
  }
}

/* --- The numbers --- */
.numbers {
  padding-top: 1.25rem;
}

.numbers-section {
  margin-bottom: 2.5rem;
}

.numbers-section h2 {
  margin: 0 0 1rem;
  font-family: var(--display);
  font-variation-settings: 'wdth' 88;
  font-weight: 620;
  font-size: var(--fs-title);
}

.kpis {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem 1rem;
}

.kpi {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.kpi__value {
  font-family: var(--display);
  font-variation-settings: 'wdth' 62;
  font-weight: 760;
  font-size: clamp(2rem, 1.6rem + 1.2vw, 2.5rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.kpi__label {
  font-family: var(--display);
  font-size: var(--fs-label);
  color: var(--graphite);
}

.bar-row {
  display: grid;
  grid-template-columns: minmax(8rem, 10rem) 1fr auto;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  font-family: var(--display);
  font-size: var(--fs-label);
}

.bar-row__track {
  height: 6px;
  background: var(--paper-deep);
}

.bar-row__fill {
  display: block;
  height: 100%;
  background: var(--ink);
}

.bar-row__value {
  min-width: 3.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.numbers-note {
  margin: 0.75rem 0 0;
  font-style: italic;
  font-size: 1rem;
  color: var(--graphite);
}

.chart {
  width: 100%;
  height: auto;
}

.chart-area { fill: var(--moss-wash); }
.chart-line { fill: none; stroke: var(--moss); stroke-width: 1.6; }
.chart-tick { stroke: var(--hairline); stroke-dasharray: 2 3; }
/* SVG units: the 340-wide chart renders 340–430px wide, so 13 units ≥ 13–16px on screen. */
.chart-label { font-size: 13px; fill: var(--graphite); text-anchor: middle; font-family: var(--display); }
.chart-end { font-size: 14px; fill: var(--ink); text-anchor: end; font-weight: 600; font-family: var(--display); }

.prep-list {
  list-style: none;
  padding: 0;
  margin: 0;
  font-family: var(--display);
  font-size: var(--fs-data);
}

.prep-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--hairline);
}

/* --- Touch screens and phone/tablet widths: larger map controls --- */
@media (pointer: coarse), (max-width: 1099px) {
  .leaflet-bar a,
  .leaflet-touch .leaflet-bar a {
    width: var(--tap);
    height: var(--tap);
    line-height: var(--tap);
  }

  .leaflet-control-layers-toggle,
  .leaflet-touch .leaflet-control-layers-toggle {
    width: var(--tap);
    height: var(--tap);
  }
}

/* --- Tablets: still stacked, with a centred reading column --- */
@media (min-width: 700px) {
  :root {
    --margin: 32px;
  }

  .map-frame {
    height: clamp(320px, 50svh, 620px);
    margin-bottom: 2rem;
  }

  .sidebar {
    max-width: 680px;
    margin-inline: auto;
  }
}

/* --- Upright tablets: the map stays pinned at the top while the days scroll underneath it,
       so the route is always in view next to the day being read. (Sideways tablets aren't tall
       enough to give up that much height, so they keep the normal scrolling map.) --- */
@media (min-width: 700px) and (max-width: 1099px) and (orientation: portrait) {
  :root {
    --map-h: clamp(260px, 42svh, 480px);
  }

  .map-frame {
    position: sticky;
    top: env(safe-area-inset-top);
    z-index: 5;
    height: var(--map-h);
    /* A paper-coloured band under the map hides text sliding up beneath it. */
    box-shadow: 0 1.25rem 0 0 var(--paper);
  }

  /* Opening a day scrolls its heading to just below the pinned map, not underneath it. */
  .day {
    scroll-margin-top: calc(var(--map-h) + 1.5rem + env(safe-area-inset-top));
  }

  /* Photos fit in the space left under the pinned map — together with the day's heading (~5rem)
     and the photo counter (~2.5rem) — so a whole photo is always visible without scrolling. */
  .slideshow__frame {
    width: min(100%, calc((100svh - var(--map-h) - 10rem - env(safe-area-inset-top)) * var(--ratio, 0.8)));
  }
}

/* --- Desktop: map 50% | journal 40% --- */
@media (min-width: 1100px) {
  :root {
    --margin: 3vw;
    --gap: 4vw;
    --mast: 112px; /* 64px site bar + 48px project row */
  }

  /* The header is exactly --mast tall (64px bar + 48px project row, borders included),
     so the map/journal grid below fills the rest of the window without page scroll. */
  .journal-page .site-header {
    height: var(--mast);
  }

  .journal-page .site-header__bar {
    height: 64px;
  }

  .journal-page .site-header__project {
    height: 48px;
    min-height: 0;
    flex-wrap: nowrap;
  }

  .layout {
    display: grid;
    grid-template-columns: 50fr 40fr;
    column-gap: var(--gap);
    /* The 1rem top padding (.journal-page .layout) sits inside this height (border-box). */
    height: calc(100vh - var(--mast) - var(--margin));
    height: calc(100dvh - var(--mast) - var(--margin));
  }

  .map-frame {
    height: auto;
    min-height: 0;
    margin-bottom: 0;
  }

  .sidebar {
    max-width: none;
    margin-inline: 0;
  }

  .day-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--hairline) transparent;
    padding-right: 0.75rem;
  }

  .slideshow__frame {
    /* In the side column, also leave room for the day's heading above the photo. */
    width: min(100%, calc((100dvh - var(--mast) - 12rem) * var(--ratio, 0.8)));
  }
}

@media (prefers-reduced-motion: reduce) {
  .slide,
  .day__number,
  .slideshow__arrow {
    transition: none;
  }
}

/* --- Stats page --- */
.page--stats { max-width: 52rem; }
.favorites__list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--hairline); }
.favorite { padding: 1rem 0; border-bottom: 1px solid var(--hairline); }
.favorite__link { display: flex; flex-direction: column; min-height: var(--tap); text-decoration: none; color: var(--ink); }
.favorite__meta { font-family: var(--display); font-size: var(--fs-label); color: var(--graphite); }
.favorite__title { font-family: var(--display); font-weight: 600; font-size: var(--fs-title); }
.favorite__reason { margin: 0.35rem 0 0; }
.favorite__tags { display: flex; flex-wrap: wrap; gap: 0.25rem 0.75rem; margin: 0.35rem 0 0; font-family: var(--display); font-size: var(--fs-label); color: var(--moss); }

.day__favorite {
  margin-left: 0.5rem;
  color: var(--moss);
  font-weight: 600;
}

/* --- Toggles beside the data they change: EN/中文 + km/mi above the day list, km/mi beside Stats --- */
.list-tools,
.section-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 1rem;
  border-bottom: 1px solid var(--hairline);
}

.section-tools {
  margin-top: 2.5rem;
}

.section-tools h2 {
  margin: 0;
}
