/* ===========================================================================
   Hatchure — the public loop pages (/loops, /de/loops)
   ---------------------------------------------------------------------------
   Generated pages (scripts/build-loop-pages.mjs), styled here. Not to be
   confused with loops.css, the planner's "Loops near you" carousel.

   Standalone like welcome.html, for the same reason: css/styles.css is built
   for a fullscreen map and forbids the page from scrolling. The brand's
   tokens come from css/tokens.css, linked before this file; the rules are
   the brand plan's: amber
   means "act here", every number is in IBM Plex Mono, and the make-up bar
   uses the planner's own bucket colours (styles.css .routeMakeupSeg).

   Not in sw.js's PRECACHE_URLS, and the service worker leaves /loops alone
   entirely (isLoopPageRequest there): these are pages to read online, not
   part of the app.
   =========================================================================== */

@font-face{ font-family:'Bricolage Grotesque'; font-weight:600; font-style:normal; font-display:swap; src:url('/fonts/BricolageGrotesque-SemiBold.woff2') format('woff2'); }
@font-face{ font-family:'Bricolage Grotesque'; font-weight:800; font-style:normal; font-display:swap; src:url('/fonts/BricolageGrotesque-ExtraBold.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Sans'; font-weight:400; font-style:normal; font-display:swap; src:url('/fonts/IBMPlexSans-Regular.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Sans'; font-weight:600; font-style:normal; font-display:swap; src:url('/fonts/IBMPlexSans-SemiBold.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Mono'; font-weight:400; font-style:normal; font-display:swap; src:url('/fonts/IBMPlexMono-Regular.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Mono'; font-weight:500; font-style:normal; font-display:swap; src:url('/fonts/IBMPlexMono-Medium.woff2') format('woff2'); }

:root{
  /* The brand's tokens are in tokens.css, linked before this file. */
  --on-ink-soft:#A7B2A9; --quiet:#7E9AA8;
  --wrap:1180px; --radius-lg:16px;
  /* The ground, the lines and the soft text are the brand's warm neutrals
     (tokens.css); Ink and the band are kept for the header, the footer and
     the headings. A card sits on the ground by its shadow, not a 1px line. */
  --lift:0 1px 2px rgba(20,32,26,0.04), 0 12px 32px -20px rgba(20,32,26,0.22);
  --lift-hover:0 1px 2px rgba(20,32,26,0.06), 0 18px 40px -20px rgba(20,32,26,0.32);
  --photo-lift:0 24px 48px -24px rgba(20,32,26,0.45);
  /* The one call to action's card: a cream the amber button sits on. */
  --cta:#FFFBF0; --cta-rim:#F3E3B8;
  color-scheme:light;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    /* The band's rules keep their light-theme colour here, as they always
       have; the homepage's dark set (tokens.css) lightens them. */
    --line-on-ink:#34443B;
    --lift:0 1px 2px rgba(0,0,0,0.3), 0 12px 32px -20px rgba(0,0,0,0.6);
    --lift-hover:0 1px 2px rgba(0,0,0,0.35), 0 18px 40px -20px rgba(0,0,0,0.7);
    --cta:#2E2A1E; --cta-rim:#4A4030;
    color-scheme:dark;
  }
}
:root[data-theme="dark"]{
  --line-on-ink:#34443B;
  --lift:0 1px 2px rgba(0,0,0,0.3), 0 12px 32px -20px rgba(0,0,0,0.6);
  --lift-hover:0 1px 2px rgba(0,0,0,0.35), 0 18px 40px -20px rgba(0,0,0,0.7);
  --cta:#2E2A1E; --cta-rim:#4A4030;
  color-scheme:dark;
}

*{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
/* The site header is sticky (css/site-header.css), so a control Shift+Tab
   reaches going up the page, or the target of a #link, would stop in view
   but under it (WCAG 2.4.11). Scrolling keeps the header's reach clear. */
html{ scroll-padding-top:calc(var(--bar-space) + 8px); }
body{
  margin:0; background:var(--chalk); color:var(--ink);
  font:16px/1.55 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
a{ color:var(--amber-text); }
a:hover{ color:var(--ink); }
img{ max-width:100%; height:auto; display:block; }
/* A list's loop map is a <picture>, for its dark drawing (thumbPicture in
   scripts/loop-pages-lib.mjs). Laid out as if it were not there, so the
   <img> is still the card's, the row's and the grid's own box; the rules
   below that size it by `img` go on matching it. */
.lpCard picture, .lpMini picture, .lpRow picture{ display:contents; }
h1, h2{ font-family:var(--display); letter-spacing:-0.015em; }
.lpWrap{ max-width:var(--wrap); margin:0 auto; padding:0 16px; }
@media (min-width: 900px){ .lpWrap{ padding:0 40px; } }
.lpMono{ font-family:var(--mono); font-variant-numeric:tabular-nums; }
.lpMuted{ color:var(--ink-soft); font-size:14px; }
/* Over everything once focused: the site header is sticky at z-index 100
   and starts at the same corner, so a skip link under it was focused but
   out of sight (its menus are 110, the account dialog's frame 1000). */
.lpSkip{ position:absolute; left:-999px; top:8px; background:var(--amber); color:var(--on-amber); padding:10px 14px; border-radius:var(--radius); z-index:1001; }
.lpSkip:focus{ left:8px; }

.lpBtn{
  display:inline-block; background:var(--amber); color:var(--on-amber); font-weight:600; text-decoration:none;
  padding:13px 22px; border-radius:999px; line-height:1.2; white-space:nowrap;
}
.lpBtn:hover{ background:var(--amber-dark); color:var(--on-amber); }
.lpBtn:focus-visible, a:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
/* The header is the site's (css/site-header.css). */

.lpCrumbs ol{ list-style:none; margin:0; padding:28px 0 0; display:flex; flex-wrap:wrap; gap:6px; font-size:13.5px; color:var(--ink-soft); }
.lpCrumbs li + li::before{ content:"/"; margin-right:6px; }
.lpCrumbs a{ color:var(--ink-soft); }

.lpHead{ padding:16px 0 24px; max-width:880px; }
.lpHead h1{ margin:8px 0 12px; font-weight:800; font-size:clamp(32px, 5vw, 56px); line-height:1.04; overflow-wrap:anywhere; }
/* Mono is for figures (the brand plan): an eyebrow, a label or a crumb is
   small sans, in capitals. */
.lpEyebrow{ font-size:12.5px; font-weight:600; color:var(--amber-text); text-transform:uppercase; letter-spacing:0.1em; }
.lpLede{ margin:0; font-size:clamp(17px, 2vw, 20px); line-height:1.45; color:var(--ink-2); }

.lpStats{ margin:0 0 24px; display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:16px 24px; padding:20px 0; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
@media (min-width: 700px){ .lpStats{ grid-template-columns:repeat(5, minmax(0, 1fr)); gap:0; } .lpStats div + div{ padding-left:24px; border-left:1px solid var(--line); } }
.lpStats div{ padding:0; }
/* Five figures in two columns: the last one takes the whole row. */
@media (max-width: 699px){ .lpStats div:last-child:nth-child(odd){ grid-column:1 / -1; } }
.lpStats dt{ font-size:12px; font-weight:500; color:var(--ink-soft); text-transform:uppercase; letter-spacing:0.06em; }
.lpStats dd{ margin:2px 0 0; font-family:var(--mono); font-size:clamp(20px, 3vw, 28px); font-weight:500; }

.lpMap{ margin:0 0 24px; border-radius:20px; overflow:hidden; background:var(--chalk-dim); box-shadow:var(--photo-lift); }
.lpMap img{ width:100%; }

.lpPanel{ background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); padding:22px 24px; margin-bottom:24px; }
.lpPanel h2{ margin:0 0 12px; font-weight:600; font-size:20px; }
.lpPanelHead .lpMono{ font-size:13px; }
.lpPanelHead{ display:flex; justify-content:space-between; align-items:baseline; gap:12px; }
.lpPanelHead .lpMono{ color:var(--ink-soft); }
.lpProfile{ display:block; width:100%; height:140px; }
.lpProfileFill{ fill:var(--amber-tint); }
.lpProfileLine{ fill:none; stroke:var(--ink); stroke-width:2; stroke-linejoin:round; }
.lpAxis{ display:flex; justify-content:space-between; font-size:12px; color:var(--ink-soft); margin-top:4px; }

.lpColumns{ display:grid; gap:24px; grid-template-columns:minmax(0, 1fr); align-items:start; }
@media (min-width: 960px){ .lpColumns{ grid-template-columns:minmax(0, 1fr) 380px; } }

.lpBar{ display:flex; height:10px; border-radius:5px; overflow:hidden; background:var(--chalk-dim); }
.lpBar span{ display:block; height:100%; }
.is-main{ background:var(--amber); }
.is-quiet{ background:var(--quiet); }
.is-pathway{ background:var(--water); }
.is-unpaved{ background:var(--mustard); }

.lpLandmarks{ list-style:none; margin:0; padding:0; }
.lpLandmarks li{ padding:12px 0; border-top:1px solid var(--chalk-dim); }
.lpLandmarks li:first-child{ border-top:0; padding-top:0; }
.lpLandmarkHead{ display:flex; justify-content:space-between; gap:12px; align-items:baseline; }
.lpLandmarkHead .lpMono{ font-size:13px; color:var(--ink-soft); white-space:nowrap; }
.lpLandmarks p{ margin:6px 0 0; font-size:15px; color:var(--ink-soft); }

.lpStops ol{ list-style:none; margin:0; padding:0; }
.lpStops li{ display:grid; grid-template-columns:64px minmax(0, 1fr); gap:10px; padding:10px 0; border-top:1px solid var(--chalk-dim); }
.lpStops li:first-child{ border-top:0; }
.lpStops li > span:last-child{ display:flex; flex-direction:column; }
.lpKm{ font-size:13px; color:var(--ink-soft); padding-top:2px; }
.lpStops p{ margin:12px 0 0; }

/* The way into the app: a cream card with the amber button, not the dark
   band, which the page keeps for its header and footer. */
.lpCta{ background:var(--cta); color:var(--ink); border:1px solid var(--cta-rim); border-radius:var(--radius-lg); padding:26px 28px; margin-bottom:24px; display:grid; gap:18px; }
@media (min-width: 700px){ .lpCta:not(.lpCtaSmall){ grid-template-columns:minmax(0, 1fr) auto; align-items:center; } }
.lpCta h2{ margin:0 0 6px; font-weight:800; font-size:24px; line-height:1.15; }
.lpCta p{ margin:0; color:var(--ink-2); font-size:15px; }
.lpCtaActions{ display:flex; flex-direction:column; gap:8px; align-items:center; }
.lpCtaActions span{ font-size:13px; color:var(--ink-soft); }
.lpCtaSmall .lpBtn{ justify-self:start; }
/* The Google Play badge beside a card's button (scripts/play-store.mjs):
   Google's artwork as it is, at the button's height. */
.lpCtaButtons{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 12px; }
.storeBadge{ display:inline-flex; text-decoration:none; }
.storeBadge img{ display:block; height:44px; width:auto; }

.lpCards{ list-style:none; margin:0; padding:0; display:grid; gap:20px; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); }
.lpCard a{ display:flex; flex-direction:column; height:100%; background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); overflow:hidden; text-decoration:none; color:var(--ink); transition:box-shadow .15s; }
.lpCard a:hover{ box-shadow:var(--lift-hover); color:var(--ink); }
.lpCard img{ width:100%; aspect-ratio:420 / 190; object-fit:cover; background:var(--chalk-dim); }
.lpCardBody{ display:flex; flex-direction:column; gap:10px; padding:16px 18px 18px; }
.lpCardTitle{ font-family:var(--display); font-weight:600; font-size:19px; line-height:1.25; overflow-wrap:anywhere; }
.lpFigures{ display:flex; flex-wrap:wrap; gap:14px; font-family:var(--mono); font-size:14px; }
.lpCardMeta{ font-size:14px; color:var(--ink-soft); }

.lpSide .lpPanel{ padding-bottom:10px; }
.lpRows{ list-style:none; margin:0; padding:0; }
.lpRows li{ display:flex; justify-content:space-between; gap:12px; padding:10px 0; border-top:1px solid var(--chalk-dim); }
.lpRows li:first-child{ border-top:0; }
.lpRows li > span:first-child{ display:flex; flex-direction:column; }

.lpMore{ padding:24px 0 8px; }
.lpMore h2, .lpSectionTitle{ font-weight:600; font-size:26px; margin:0 0 16px; }
.lpTiles{ list-style:none; margin:0 0 40px; padding:0; display:grid; gap:16px; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr)); }
.lpTiles a{ display:flex; flex-direction:column; gap:4px; padding:18px 20px; background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); text-decoration:none; color:var(--ink); transition:box-shadow .15s; }
.lpTiles a:hover{ box-shadow:var(--lift-hover); color:var(--ink); }
.lpTileTitle{ font-family:var(--display); font-weight:600; font-size:19px; }

/* The quiet line above the footer on loop, climb and ski pages (layout(),
   instagramStrip; help and race pages leave it out):
   the Instagram glyph and "I post new loops on Instagram every week". */
.lpInstagram{ display:flex; align-items:center; gap:12px; margin-top:32px; padding:14px; background:var(--surface); border:1px solid var(--line); border-radius:12px; }
.lpInstagram svg{ flex:none; color:var(--ink); }
.lpInstagram p{ margin:0; min-width:0; font-size:14px; line-height:1.4; color:var(--ink-2); }
.lpInstagram a{ color:var(--ink); font-weight:600; text-decoration:underline; text-decoration-color:var(--amber); text-decoration-thickness:2px; text-underline-offset:3px; }
@media print{ .lpInstagram{ display:none; } }

.lpFooter{ margin-top:48px; background:var(--band); color:var(--on-ink-soft); font-size:13px; }
.lpFooterRow{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:12px 32px; padding-top:28px; padding-bottom:32px; }
.lpFooterRow p{ margin:0; max-width:760px; }
.lpFooterLinks{ display:flex; flex-wrap:wrap; gap:6px 18px; }
.lpFooter a{ color:var(--on-ink); }
/* "Withdraw from contract here" (§ 356a BGB) and "Cancel contracts here"
   (§ 312k BGB): first, bold, in the accent. */
.lpFooter a.lpContract{ color:var(--amber); font-weight:600; }

/* ---------- The explorer on /loops/ (app/js/loop-explorer.js) ---------- */
/* Whatever the display rule, `hidden` hides: the explorer toggles it. */
[hidden]{ display:none !important; }
.lpHidden{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.lpExplorer{ margin:0 0 40px; }
.lpSearch{ display:grid; gap:14px; }
.lpFilterBox{ background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); padding:16px; }
.lpSearchRow, .lpSearchBox{ display:flex; gap:10px; }
.lpSearchBox{ margin:0 0 24px; max-width:720px; }
.lpSearchRow input, .lpSearchBox input{
  flex:1; min-width:0; height:48px; padding:0 14px; font:inherit; font-size:17px; color:var(--ink);
  background:var(--chalk); border:1px solid var(--line); border-radius:var(--radius);
}
.lpSearchRow input:focus, .lpSearchBox input:focus{ outline:2px solid var(--amber); outline-offset:1px; border-color:var(--ink-soft); }
.lpSearchRow .lpBtn, .lpSearchBox .lpBtn{ border:0; font:inherit; font-weight:600; cursor:pointer; }
.lpFilterBox summary{ display:none; }
@media (max-width: 699px){
  .lpFilterBox summary{
    display:flex; align-items:center; gap:8px; min-height:44px; cursor:pointer; font-weight:600; list-style:none;
  }
  .lpFilterBox summary::-webkit-details-marker{ display:none; }
  .lpFilterBox summary::after{ content:"▾"; margin-left:auto; color:var(--ink-soft); }
  .lpFilterBox[open] summary::after{ content:"▴"; }
  .lpFilterBox[open] summary{ margin-bottom:10px; }
}
.lpFilterBox{ padding:18px 20px; }
/* Two rows (loop-pages-lib.mjs explorer()): where and how big, then what the
   loop has. A filter that is set is pale amber, the brand's "act here";
   "Any", the default, stays plain, so amber only ever marks a real filter. */
.lpFilterRow{ display:flex; flex-wrap:wrap; align-items:flex-start; gap:18px 32px; }
.lpFilterRow + .lpFilterRow{ margin-top:18px; padding-top:18px; border-top:1px solid var(--line); }
.lpFilterGroup{ border:0; margin:0; padding:0; min-width:0; }
/* Floated, a fieldset's legend sits in the flow like the country's label. */
.lpFilterGroup > legend, .lpFilterLegend{
  display:block; float:left; padding:0; margin:0 0 8px;
  font-family:var(--mono); font-size:12px; text-transform:uppercase; letter-spacing:0.08em; color:var(--ink-soft);
}
.lpFilterGroup > legend + *{ clear:left; }
.lpCountry{ display:block; width:220px; }
.lpCountry select, .lpSortBy select{
  appearance:none; -webkit-appearance:none; height:36px; padding:0 34px 0 12px; font:inherit; font-size:14px; color:var(--ink); cursor:pointer;
  background:var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5' fill='none' stroke='%237E8A83' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 10px center / 12px;
  border:1px solid var(--line); border-radius:var(--radius);
}
.lpCountry select{ width:100%; background-color:var(--chalk); }
.lpCountry select:hover, .lpSortBy select:hover{ border-color:var(--ink-soft); }
.lpCountry select:focus-visible, .lpSortBy select:focus-visible{ outline:2px solid var(--amber); outline-offset:1px; }
.lpCountry select.isSet{ background-color:var(--amber-tint); border-color:var(--amber); color:var(--amber-text); font-weight:600; }
/* Pick one: a segmented track. */
.lpSeg{ display:flex; flex-wrap:wrap; width:fit-content; gap:2px; padding:3px; background:var(--chalk); border:1px solid var(--line); border-radius:10px; }
.lpSeg label, .lpCheckChips label{ position:relative; }
.lpSeg input, .lpCheckChips input, .lpSwitch input{ position:absolute; opacity:0; width:1px; height:1px; margin:0; }
.lpSeg span{
  display:inline-flex; align-items:center; min-height:30px; padding:0 12px; border-radius:7px; cursor:pointer;
  font-size:14px; color:var(--ink); white-space:nowrap; transition:background .12s, color .12s;
}
.lpSeg label:hover span{ background:color-mix(in srgb, var(--ink) 8%, transparent); }
.lpSeg input:checked + span{ background:var(--surface); box-shadow:0 0 0 1px var(--line); }
.lpSeg input:not([value=""]):checked + span{ background:var(--amber-tint); color:var(--amber-text); box-shadow:0 0 0 1px var(--amber); font-weight:600; }
.lpSeg input:focus-visible + span{ outline:2px solid var(--amber); outline-offset:1px; }
/* Pick several: chips, + until picked, ✓ once. */
.lpCheckChips{ display:flex; flex-wrap:wrap; gap:6px; }
.lpCheckChips span{
  display:inline-flex; align-items:center; gap:6px; min-height:36px; padding:0 14px 0 10px; border-radius:18px; cursor:pointer;
  border:1px solid var(--line); background:var(--surface); color:var(--ink); font-size:14px; white-space:nowrap;
}
.lpCheckChips span::before{
  content:""; flex:none; width:16px; height:16px; background:currentColor; opacity:.6;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5v9M3.5 8h9' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E") center / 16px no-repeat; mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5v9M3.5 8h9' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E") center / 16px no-repeat;
}
.lpCheckChips label:hover span{ border-color:var(--ink-soft); }
.lpCheckChips input:checked + span{ background:var(--amber-tint); border-color:var(--amber); color:var(--amber-text); font-weight:600; }
.lpCheckChips input:checked + span::before{ opacity:1; -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5 6.5 11.5 12.5 4.5' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5 6.5 11.5 12.5 4.5' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.lpCheckChips input:focus-visible + span{ outline:2px solid var(--amber); outline-offset:2px; }
/* On or off: a switch. */
.lpSwitch{ position:relative; display:flex; align-items:center; min-height:36px; cursor:pointer; font-size:14px; }
.lpSwitch span{ position:relative; display:inline-flex; align-items:center; }
.lpSwitch span::before{
  content:""; flex:none; width:38px; height:22px; margin-right:10px; border-radius:11px;
  background:var(--line); box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--ink) 10%, transparent); transition:background .15s;
}
.lpSwitch span::after{
  content:""; position:absolute; left:3px; top:50%; width:16px; height:16px; margin-top:-8px; border-radius:50%;
  background:var(--surface); box-shadow:0 1px 2px rgba(0,0,0,.3); transition:transform .15s;
}
.lpSwitch input:checked + span::before{ background:var(--amber-tint); box-shadow:inset 0 0 0 1px var(--amber); }
.lpSwitch input:checked + span::after{ transform:translateX(16px); background:var(--amber); box-shadow:none; }
.lpSwitch input:focus-visible + span::before{ outline:2px solid var(--amber); outline-offset:2px; }
@media (prefers-reduced-motion: reduce){ .lpSeg span, .lpSwitch span::before, .lpSwitch span::after{ transition:none; } }
@media (max-width: 699px){
  .lpFilterBox{ padding:12px 14px; }
  .lpFilterRow{ flex-direction:column; align-items:stretch; gap:16px; }
  .lpFilterRow + .lpFilterRow{ margin-top:16px; padding-top:16px; }
  .lpCountry{ width:auto; }
  .lpSeg{ width:auto; }
  .lpSeg label{ flex:1 1 auto; }
  .lpSeg span{ justify-content:center; width:100%; padding:0 10px; }
}
/* Sort orders the results, so it sits by their count. */
.lpSortBy{ display:inline-flex; align-items:center; gap:8px; margin-left:auto; font-size:14px; color:var(--ink-soft); }
.lpSortBy + .lpMapToggle{ margin-left:0; }
.lpToggle{ display:inline-flex; align-items:center; gap:8px; min-height:36px; font-size:14px; cursor:pointer; }
.lpToggle input{ width:18px; height:18px; accent-color:var(--ink); }

.lpExplorerBar{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 16px; margin:18px 0 14px; }
.lpExplorerBar p{ margin:0; font-size:15px; }
.lpChip{ display:inline-flex; align-items:center; gap:6px; padding:4px 4px 4px 12px; border-radius:16px; background:var(--amber-tint); font-size:14px; }
.lpChip button{ border:0; background:none; font-size:18px; line-height:1; width:28px; height:28px; border-radius:14px; cursor:pointer; color:var(--ink); }
.lpLinkButton{ border:0; background:none; padding:6px 0; font:inherit; font-size:14px; color:var(--amber-text); text-decoration:underline; cursor:pointer; }
.lpMapToggle{ margin-left:auto; }

.lpExplorerBody{ display:grid; gap:20px; grid-template-columns:minmax(0, 1fr); align-items:start; }
.lpMapCol{ display:none; }
.lpExplorer.lpMapOpen .lpMapCol{ display:block; order:-1; }
#lpMap{ height:360px; border-radius:var(--radius-lg); overflow:hidden; background:var(--chalk-dim); box-shadow:var(--lift); }
/* The map's pins and controls set their own z-indexes; kept inside the box,
   they scroll under the sticky site header (z-index 100) instead of over it. */
#lpMap, .lpClimbMap{ isolation:isolate; }
.lpMapCol .lpToggle{ margin-top:8px; }
@media (min-width: 1100px){
  .lpExplorerBody{ grid-template-columns:minmax(0, 1fr) 420px; }
  .lpMapCol, .lpExplorer.lpMapOpen .lpMapCol{ display:block; order:0; position:sticky; top:16px; }
  #lpMap{ height:calc(100vh - 80px); max-height:720px; }
  .lpMapToggle{ display:none; }
}
.lpResultsCol .lpCards{ grid-template-columns:repeat(auto-fill, minmax(260px, 1fr)); }
.lpEmpty{ grid-column:1 / -1; padding:32px 0; color:var(--ink-soft); }
/* The pages of results: previous, the numbers, next — the filters' chips
   in shape, the current page filled as a checked chip is. */
.lpPager{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; margin:24px 0 0; }
.lpPager[hidden]{ display:none; }
.lpPagerNum, .lpPagerEdge{
  display:inline-flex; align-items:center; justify-content:center; gap:6px; min-width:44px; min-height:44px; padding:0 12px; box-sizing:border-box;
  background:var(--surface); color:var(--ink); border:1px solid var(--line); border-radius:999px;
  font-family:var(--mono); font-size:14px; text-decoration:none;
}
.lpPagerEdge{ font-family:inherit; font-size:15px; }
a.lpPagerNum:hover, a.lpPagerEdge:hover{ border-color:var(--ink); color:var(--ink); text-decoration:none; }
.lpPagerNum[aria-current="page"]{ background:var(--ink); border-color:var(--ink); color:var(--chalk); }
.lpPagerEdge[aria-disabled="true"]{ opacity:0.4; }
.lpPagerGap{ min-width:20px; text-align:center; color:var(--ink-soft); }
.lpPager a:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
/* A phone: the arrows alone, so the numbers keep one row. */
@media (max-width:520px){
  .lpPager{ gap:2px; }
  .lpPagerWord{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); }
  .lpPagerNum, .lpPagerEdge{ min-width:40px; padding:0 6px; }
  .lpPagerGap{ min-width:14px; }
}
.lpExplorer:not(.isReady) .lpExplorerBody{ min-height:200px; }
.lpBrowse{ margin-top:16px; }

/* The map, dressed for the page: the clusters in the one accent, since a
   cluster is something to tap; the popup in the page's type. */
.lpMapCol .maplibregl-map{ font:14px/1.4 'IBM Plex Sans', system-ui, sans-serif; background:var(--chalk-dim); }
.lpMapCol .maplibregl-popup-content{ font:14px/1.4 'IBM Plex Sans', system-ui, sans-serif; }
.lpMapCol .maplibregl-popup-content a{ color:var(--ink); }
/* A bubble of loops. Drawn by the map as GL circles (loop-explorer.js
   reads these colours and sizes from here): a translucent halo, the amber
   disc ringed in ink, the count. */
.lpCluster{ width:40px; height:40px; background:rgba(240,179,58,0.35); border-radius:50%; }
.lpCluster div{
  width:30px; height:30px; margin:5px; border-radius:50%; background:#F0B33A; color:#14201A; text-align:center;
  font:600 12px/30px 'IBM Plex Mono', ui-monospace, monospace; box-shadow:0 0 0 2px #14201A;
}

/* "Put this loop on your site": collapsed until asked for, since most
   readers came to ride, not to embed. The preview is the snippet itself,
   with its own inline styles, so it shows exactly what a host page gets. */
.lpEmbed summary{ cursor:pointer; list-style:none; display:flex; align-items:center; gap:10px; }
.lpEmbed summary::-webkit-details-marker{ display:none; }
.lpEmbed summary::after{ content:"▾"; margin-left:auto; color:var(--ink-soft); }
.lpEmbed[open] summary::after{ content:"▴"; }
.lpEmbed summary h2{ margin:0; }
.lpEmbed[open] summary{ margin-bottom:10px; }
.lpEmbed > p{ margin:0 0 16px; font-size:15px; }
.lpEmbedPreview{ margin-bottom:16px; }
.lpEmbedLabel{ display:block; font-size:13px; font-weight:600; margin-bottom:6px; }
.lpEmbedCode{
  display:block; width:100%; resize:vertical; margin-bottom:12px; padding:10px 12px;
  font:12px/1.5 var(--mono); color:var(--ink); background:var(--chalk);
  border:1px solid var(--line); border-radius:var(--radius);
}
.lpEmbedCode:focus{ outline:2px solid var(--amber); outline-offset:1px; }
.lpEmbedCopy{ border:0; font:inherit; font-weight:600; cursor:pointer; }
.lpEmbedCopy[hidden]{ display:none; }

/* ---------------------------------------------------------------------------
   Climbs, and the loop page on one km axis
   --------------------------------------------------------------------------- */

.lpPill{ display:inline-flex; align-items:center; gap:6px; min-height:36px; padding:6px 12px; background:var(--surface); border:1px solid var(--line); border-radius:999px; color:var(--ink); text-decoration:none; font-size:15px; }
.lpPill:hover{ border-color:var(--ink); color:var(--ink); }
.lpPill .lpMono{ font-size:13px; color:var(--ink-soft); }
.lpPills{ display:flex; flex-wrap:wrap; gap:8px; margin:0; }
.lpOver{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:0 0 14px; }
.lpOver > span{ color:var(--ink-soft); font-size:15px; margin-right:2px; }

/* The map beside the numbers that decide the ride. */
.lpHero{ display:grid; gap:20px; margin-bottom:24px; align-items:stretch; }
@media (min-width: 960px){ .lpHero{ grid-template-columns:minmax(0, 1fr) 380px; } }
.lpHero .lpMap{ margin:0; }
.lpHero .lpMap img{ height:100%; object-fit:cover; }
.lpSummary{ background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); padding:24px; display:flex; flex-direction:column; gap:16px; }
.lpSummary .lpStats{ margin:0; grid-template-columns:repeat(2, minmax(0, 1fr)); border:0; padding:0; gap:16px 12px; }
.lpSummary .lpStats div, .lpSummary .lpStats div + div{ padding:0; border:0; }
.lpSummary .lpStats div:last-child:nth-child(odd){ grid-column:auto; }
.lpSummary .lpStats dd{ font-size:clamp(22px, 2.6vw, 28px); }
.lpSummary > p{ margin:0; text-align:center; }
/* With a height profile, it sits under the map, the two as tall as the
   summary beside them: the profile at its own height, the map taking the
   rest (a map stretched to the whole summary is cropped into a close-up).
   On a phone: the map, the numbers, then the profile. */
.lpHero.hasRide{ grid-template-areas:"media" "side" "ride"; }
.lpHero.hasRide > .lpMap, .lpHero.hasRide > .lpCarousel{ grid-area:media; }
.lpHero.hasRide > .lpSummary{ grid-area:side; }
.lpHero.hasRide > .lpRide{ grid-area:ride; margin:0; }
.lpHero.hasRide > .lpCarousel{ margin-bottom:22px; }
@media (min-width: 960px){
  .lpHero.hasRide{ grid-template-areas:"media side" "ride side"; grid-template-rows:1fr auto; }
}
.lpBtnBig{ display:block; text-align:center; font-size:17px; padding:15px 18px; margin-top:auto; }
.lpSummary .lpBtnBig + .lpSummaryActions{ margin-top:-6px; }
@media (min-width: 700px){ .lpStats.lpStats4{ grid-template-columns:repeat(4, minmax(0, 1fr)); } }

/* The height profile with the passes on it. */
.lpRideLabels{ position:relative; margin-top:6px; }
.lpRideLabel{ position:absolute; transform:translateX(-50%); white-space:nowrap; font-size:13px; font-weight:600; line-height:20px; }
.lpRideLabel.isStart{ transform:none; }
.lpRideLabel.isEnd{ transform:translateX(-100%); }
.lpRideLabel .lpMono{ font-weight:400; color:var(--ink-soft); font-size:12px; }
/* Too narrow for names over the chart: the dashed marks stay, and the list
   under it names each pass at its km. */
@media (max-width: 699px){ .lpRideLabels{ display:none; } }
.lpRide .lpProfile{ height:180px; }
.lpRideDry{ fill:var(--ink); opacity:0.1; }
.lpRideMark{ stroke:var(--ink); stroke-width:1; stroke-dasharray:3 3; }
.lpRideTicks{ display:block; width:100%; height:10px; margin-top:4px; }
.lpRideTick{ fill:var(--water); }
.lpRideKey{ display:flex; flex-wrap:wrap; gap:6px 18px; margin:10px 0 0; }
.lpRideKey span{ display:inline-flex; align-items:center; gap:6px; }
.lpKeyTick{ width:3px; height:12px; background:var(--water); display:inline-block; }
.lpKeyDry{ width:12px; height:12px; background:var(--ink); opacity:0.18; display:inline-block; }

/* The passes and the stops, in riding order. */
.lpTimeline{ list-style:none; margin:0; padding:0; }
.lpTimeline li{ display:grid; grid-template-columns:78px minmax(0, 1fr); gap:10px; padding:12px 0; border-top:1px solid var(--chalk-dim); }
.lpTimeline li:first-child{ border-top:0; }
.lpTimeline li > span:last-child{ display:flex; flex-direction:column; gap:2px; }
/* A pass or a sight on the way: the same row, its name in display type,
   its km in amber and its photo beside it where it has one. */
.lpTimeline li.lpTlClimb{ padding:16px 0; }
.lpTimeline li.lpTlClimb.hasPhoto{ grid-template-columns:78px 96px minmax(0, 1fr); gap:12px 16px; }
.lpTlPhoto{ width:96px; height:96px; object-fit:cover; border-radius:12px; background:var(--chalk-dim); }
@media (max-width: 560px){ .lpTimeline li.lpTlClimb.hasPhoto{ grid-template-columns:78px minmax(0, 1fr); } .lpTlPhoto, .lpTimeline li.lpTlClimb.hasPhoto > span:last-child{ grid-column:2; } .lpTlPhoto{ width:100%; height:140px; } }
.lpTlClimb strong{ font-family:var(--display); font-weight:800; font-size:22px; line-height:1.15; }
.lpTlClimb .lpKm{ color:var(--amber-text); font-weight:500; }
.lpTlClimb .lpMuted{ color:var(--ink-2); font-size:14.5px; }
.lpTlClimb strong + .lpMuted{ font-family:inherit; font-size:12px; font-weight:500; text-transform:uppercase; letter-spacing:0.06em; color:var(--ink-soft); }
.lpTimelinePanel h3{ margin:20px 0 8px; font-size:16px; }
.lpWarn{ color:var(--amber-text); font-size:14px; }

.lpMini{ list-style:none; margin:0 0 10px; padding:0; display:grid; gap:12px; }
.lpMini a{ display:grid; grid-template-columns:120px minmax(0, 1fr); gap:12px; align-items:center; color:var(--ink); text-decoration:none; }
.lpMini img{ border-radius:var(--radius); aspect-ratio:120 / 54; object-fit:cover; }
.lpMini a > span{ display:flex; flex-direction:column; gap:2px; line-height:1.3; }
.lpMini a:hover strong{ text-decoration:underline; }

/* On a phone the way into the app stays at hand. */
.lpSticky{ display:none; }
@media (max-width: 699px){
  .lpSticky{ display:flex; align-items:center; gap:12px; position:fixed; left:0; right:0; bottom:0; z-index:5; padding:10px 16px calc(10px + env(safe-area-inset-bottom)); background:var(--band); color:var(--on-ink-soft); font-size:13px; line-height:1.35; box-shadow:0 -4px 16px rgba(20, 32, 26, 0.18); }
  .lpSticky span{ flex:1; min-width:0; }
  body:has(.lpSticky) .lpFooter{ padding-bottom:96px; }
  /* A control the keyboard reaches is scrolled clear of the bar, not just
     into the window: without this the browser stops as soon as it is in
     view, which near the bottom is under the bar ("Put this loop on your
     site" was focused and hidden, WCAG 2.4.11). The bar is ~60 px tall,
     more with a long line or the home indicator. */
  html:has(.lpSticky){ scroll-padding-bottom:calc(96px + env(safe-area-inset-bottom)); }
}

/* The /loops/ hub: famous climbs under the search. */
.lpFamous{ margin:8px 0 28px; }
.lpSectionHead{ display:flex; justify-content:space-between; align-items:baseline; gap:12px; flex-wrap:wrap; }
.lpClimbTiles{ list-style:none; margin:0; padding:0; display:grid; gap:12px; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); }
.lpClimbTiles a{ display:flex; flex-direction:column; gap:6px; height:100%; padding:18px; background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); color:var(--ink); text-decoration:none; transition:box-shadow .15s; }
.lpClimbTiles a:hover{ box-shadow:var(--lift-hover); }
.lpClimbTiles .lpEyebrow{ font-size:11.5px; color:var(--ink-soft); }
.lpClimbTiles .lpTileTitle{ font-family:var(--display); font-weight:800; font-size:21px; line-height:1.15; }
.lpClimbTiles .lpMono{ font-size:14px; }

/* A climb's loops. */
.lpExtract{ margin:12px 0 0; font-size:16px; }
.lpChooseHead{ display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:8px; }
.lpChooseHead h2{ margin:0; font-size:28px; font-weight:800; }
.lpGroupTitle{ margin:22px 0 10px; font-size:12.5px; font-weight:500; text-transform:uppercase; letter-spacing:0.06em; color:var(--ink-soft); }
.lpRows2{ list-style:none; margin:0; padding:0; display:grid; gap:12px; }
/* A climb's lists are laid out and painted only as they come near the
   screen, and their lazy maps wait with them: Chrome otherwise fetches them
   all while the page loads, and on a slow phone connection they share it
   with the climb's photo, the page's largest paint. On the list, not each
   row: a phone's rows are as tall as the tallest (grid-auto-rows below),
   which a row not yet drawn would set to its placeholder height. The
   heights are guesses until a list has been drawn once. The clip margin
   keeps a row's focus ring (2px, 2px out) clear of the list's edge. */
.lpRows2{ content-visibility:auto; contain-intrinsic-block-size:auto 300px; overflow-clip-margin:4px; }
@media (max-width: 699px){ .lpRows2{ contain-intrinsic-block-size:auto 650px; } }
.lpRow > a, .lpRow.lpRing{ display:grid; grid-template-columns:minmax(0, 1fr); gap:10px 18px; align-items:center; background:var(--surface); border-radius:var(--radius-lg); box-shadow:var(--lift); overflow:hidden; color:var(--ink); text-decoration:none; transition:box-shadow .15s; }
.lpRow > a:hover{ box-shadow:var(--lift-hover); }
.lpRow img{ width:100%; aspect-ratio:210 / 95; object-fit:cover; }
.lpRowBody{ display:flex; flex-direction:column; gap:6px; padding:0 16px; }
.lpRowBody strong{ font-size:18px; }
.lpRowFigures{ display:flex; flex-direction:column; gap:2px; padding:0 16px 14px; font-size:15px; }
/* Every row the same height, whatever it crosses: the list of what else it
   crosses (up to a dozen names) stops at two lines, whole in its title, and
   a ring's start towns keep to one row that scrolls. So the map beside it
   is always cut the same, not zoomed in on a long row. */
.lpRowBody{ min-width:0; }
.lpRowBody strong{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lpRowSub{ display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-clamp:2; overflow:hidden; }
.lpRing .lpRowSub{ -webkit-line-clamp:1; line-clamp:1; }
.lpRing .lpPills{ flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none; }
.lpRing .lpPills::-webkit-scrollbar{ display:none; }
.lpRing .lpPill{ flex-shrink:0; }
/* A phone stacks the map over the words: every row in a list as tall as its
   tallest, the map at the top of each. */
@media (max-width: 699px){
  .lpRows2{ grid-auto-rows:1fr; }
  .lpRow:not(.lpRing){ display:grid; }
  .lpRow > a, .lpRow.lpRing{ align-content:start; }
}
@media (min-width: 700px){
  .lpRow > a, .lpRow.lpRing{ grid-template-columns:210px minmax(0, 1fr) auto; height:124px; }
  .lpRow img{ height:100%; }
  .lpRowBody{ padding:12px 0; }
  .lpRowFigures{ text-align:right; padding:12px 20px 12px 0; }
}
.lpRing .lpPills{ margin-top:4px; }
.lpRing .lpPill{ min-height:32px; font-size:14px; padding:4px 10px; }
.lpJump{ display:flex; flex-wrap:wrap; gap:8px; margin:0 0 8px; }

/* A country's smaller regions, as sections of its page. */
.lpSmallRegion{ scroll-margin-top:16px; }
.lpSmallRegion h3{ font-family:var(--display); font-size:22px; margin:24px 0 12px; }
.lpSmallRegion h3 .lpMono{ font-family:var(--mono); font-size:14px; font-weight:400; }

/* A climb's map: every loop over it, drawn by app/js/loop-climb-map.js. */
/* A climb's hero: the words on the left and, on the right, its photo where
   it has one that is not wide enough for the banner (lpClimbPhoto), else
   the map of its loops. With both, the map takes the row under them. */
.lpClimbHero{ display:grid; gap:0 48px; align-items:start; }
@media (min-width: 960px){
  .lpClimbHero.hasMap, .lpClimbHero.hasPhoto{ grid-template-columns:minmax(0, 1fr) 500px; }
  .lpClimbHero.hasMap:not(.hasPhoto) .lpClimbMap{ margin-top:24px; }
  .lpClimbHero.hasPhoto .lpClimbMap{ grid-column:1 / -1; height:360px; }
  .lpClimbHero.hasPhoto .lpClimbPhoto{ margin-top:36px; }
}
.lpClimbMap{ height:420px; border-radius:var(--radius-lg); overflow:hidden; background:var(--chalk-dim); box-shadow:var(--lift); margin-bottom:24px; }
@media (max-width: 699px){ .lpClimbMap{ height:300px; } }
.lpClimbMap .glTooltip{ font:14px/1.35 'IBM Plex Sans', sans-serif; color:#14201A; }
.lpClimbMap .glTooltip .lpMono{ font-size:13px; }
.lpPassMark svg{ display:block; filter:drop-shadow(0 1px 2px rgba(20, 32, 26, 0.35)); }
.lpClimbMap .lpPassLabel{ font-weight:600; background:var(--band); color:var(--on-ink); border:0; box-shadow:none; padding:3px 8px; }
.lpClimbMap .glTooltip-top.lpPassLabel::before{ border-top-color:var(--band); }
.lpRow.isLit > a, .lpRow.isLit.lpRing{ box-shadow:0 0 0 2px var(--amber), var(--lift); }

/* The hub's search: one wide bar under the heading, its button attached. */
.lpHeroSearch{ display:flex; max-width:820px; background:var(--surface); border:2px solid var(--ink); border-radius:var(--radius-lg); overflow:hidden; }
.lpHeroSearch:focus-within{ box-shadow:0 0 0 3px var(--amber); }
.lpHeroSearch input{ flex:1; min-width:0; height:64px; padding:0 22px; border:0; background:transparent; color:var(--ink); font:inherit; font-size:19px; }
.lpHeroSearch input:focus{ outline:none; }
.lpHeroSearch .lpBtn{ border:0; border-radius:0; padding:0 28px; font:inherit; font-size:17px; font-weight:600; cursor:pointer; }
@media (max-width: 560px){ .lpHeroSearch input{ height:54px; padding:0 14px; font-size:17px; } .lpHeroSearch .lpBtn{ padding:0 16px; } }
.lpTry{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:0 0 12px; font-size:15px; color:var(--ink-soft); }
.lpTry > span{ margin-right:2px; }
.lpTry button.lpPill{ font:inherit; font-size:15px; cursor:pointer; }
.lpExploreTitle{ margin:12px 0 0; }
.lpTry .lpPill.isOn{ background:var(--ink); color:var(--chalk); border-color:var(--ink); }
/* Scrolled to ("Near me", another page): clear of the sticky site header. */
/* The header's reach is html's scroll-padding-top now (above). */
.lpExplorerBar{ scroll-margin-top:0; }

/* Where to fill up on a climb, one start town at a time. */
.lpFillPanel{ margin-top:32px; }
.lpFillPanel > h2{ font-size:26px; font-weight:800; }
.lpFillSide{ padding:16px 0; border-top:1px solid var(--chalk-dim); }
.lpFillSide h3{ margin:0 0 10px; font-size:18px; }
.lpFill{ margin:0 0 10px; display:grid; gap:6px; }
.lpFill div{ display:grid; grid-template-columns:minmax(120px, 190px) minmax(0,1fr); gap:10px; }
@media (max-width:560px){ .lpFill div{ grid-template-columns:1fr; gap:0; } }
.lpFill dt{ font-size:12px; font-weight:500; text-transform:uppercase; letter-spacing:0.06em; color:var(--ink-soft); padding-top:3px; }
.lpFill dd{ margin:0; }
.lpFillLoops{ list-style:none; margin:0; padding:0; display:grid; gap:6px; font-size:15px; }

/* A climb's photo across the page, its heading over the darkened foot. */
.lpBanner{ position:relative; height:420px; overflow:hidden; background:var(--band); color:var(--on-ink); }
@media (max-width:699px){ .lpBanner{ height:300px; } }
.lpBanner > img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:50% 45%; }
.lpBanner::after{ content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(20,32,26,0.05) 0%, rgba(20,32,26,0.45) 38%, rgba(20,32,26,0.93) 100%); }
.lpBannerText{ text-shadow:0 1px 12px rgba(20,32,26,0.6); }
.lpBannerText{ position:absolute; left:0; right:0; bottom:38px; z-index:1; display:flex; flex-direction:column; gap:10px; }
.lpBannerText h1{ margin:0; font-weight:800; font-size:clamp(28px, 5vw, 58px); line-height:1.03; max-width:900px; color:#EDEFE8; }
.lpBannerText .lpEyebrow{ color:#F0B33A; }
.lpBannerText .lpCrumbs ol{ padding-top:0; color:#D5DCD6; }
.lpBannerText .lpCrumbs a{ color:#D5DCD6; }
.lpCredit{ position:absolute; right:12px; bottom:10px; z-index:1; margin:0; padding:4px 8px; border-radius:4px; background:rgba(20,32,26,0.72); font-family:var(--mono); font-size:11.5px; color:#EDEFE8; }
.lpCredit a{ color:#EDEFE8; }
@media (max-width:699px){ .lpBannerText{ bottom:40px; } }
.lpBanner + main .lpClimbHero .lpHead{ padding-top:24px; }

/* Famous climb tiles with their photo. */
.lpClimbTiles a{ padding:0; overflow:hidden; gap:0; }
.lpTilePhoto{ display:block; width:100%; height:130px; object-fit:cover; background:var(--band); }
.lpTileMark svg{ display:block; width:100%; height:100%; }
.lpTileBody{ display:flex; flex-direction:column; gap:6px; padding:16px 18px 18px; }
.lpCredits{ margin:10px 0 0; font-size:12.5px; color:var(--ink-soft); }
.lpCredits a{ color:var(--ink-soft); }
/* Folded to one line under a row of tiles (photoCredits). */
.lpCredits summary{ display:inline-flex; align-items:center; gap:6px; min-height:32px; cursor:pointer; list-style:none; }
.lpCredits summary::-webkit-details-marker{ display:none; }
.lpCredits summary::after{ content:"▾"; }
.lpCredits[open] summary::after{ content:"▴"; }
.lpCredits summary:hover{ color:var(--ink); }
.lpCredits summary:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; border-radius:4px; }
.lpCredits p{ margin:4px 0 0; }

/* A photo too narrow for the banner, under the climb's lead instead. */
.lpClimbPhoto{ margin:18px 0 24px; max-width:520px; position:relative; }
.lpClimbPhoto img{ width:100%; aspect-ratio:4 / 3; object-fit:cover; border-radius:20px; background:var(--chalk-dim); box-shadow:var(--photo-lift); }
.lpClimbPhoto figcaption{ position:absolute; right:12px; bottom:10px; margin:0; padding:4px 8px; border-radius:6px; background:rgba(20,32,26,0.72); color:#EDEFE8; }
.lpClimbPhoto figcaption a{ color:#EDEFE8; }
.lpClimbPhoto figcaption{ font-size:11.5px; color:var(--ink-soft); }

/* "Save this loop": the second way into the app, quieter than the first. */
.lpBtnGhost{
  display:inline-flex; align-items:center; justify-content:center; gap:6px; min-height:38px; padding:7px 11px; border:1px solid var(--line); border-radius:999px;
  background:var(--surface); color:var(--ink); text-decoration:none; font-weight:500; font-size:13px;
}
.lpBtnGhost:hover{ border-color:var(--ink); color:var(--ink); text-decoration:none; }
/* Under the summary's one amber button: save, start elsewhere, share, as
   small pills in a row, not three more buttons. */
.lpSummaryActions{ display:flex; flex-wrap:wrap; gap:8px; }
.lpSummaryActions .lpShare{ width:auto; }

/* The all-climbs page: the same photo tiles, a little smaller, in every country. */
.lpClimbTilesAll{ grid-template-columns:repeat(auto-fill, minmax(190px, 1fr)); }
.lpClimbTilesAll .lpTilePhoto{ height:110px; }
.lpClimbTilesAll .lpTileTitle{ font-size:18px; }
.lpClimbTilesAll .lpTileBody{ padding:12px 14px 14px; }

/* The search on /climbs/: one box and the filters under it, which narrow
   the tiles below them. */
.lpClimbSearch{ display:grid; gap:12px; margin:0 0 20px; }
.lpClimbSearch .lpSearchBox{ align-items:center; margin:0; }
.lpClimbSearch #lpClimbCount{ white-space:nowrap; }
#lpClimbNone{ margin:0 0 20px; }

/* A loop page's carousel: the map, then the landmarks' photos. The strip
   scrolls and snaps on its own; loop-carousel.js adds arrows and dots. */
.lpCarousel{ position:relative; min-width:0; }
.lpSlides{ display:flex; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none; border-radius:20px; background:var(--chalk-dim); box-shadow:var(--photo-lift); height:100%; }
.lpSlides::-webkit-scrollbar{ display:none; }
.lpSlides:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
.lpSlide{ flex:0 0 100%; scroll-snap-align:start; margin:0; position:relative; min-height:300px; }
.lpCarousel .lpMap{ border-radius:0; box-shadow:none; }
.lpSlide > img{ width:100%; height:100%; object-fit:cover; position:absolute; inset:0; }
.lpCarousel .lpMap img{ position:static; }
.lpSlide figcaption{ position:absolute; left:0; right:0; bottom:0; display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 10px; padding:40px 16px 12px; background:linear-gradient(180deg, rgba(20,32,26,0), rgba(20,32,26,0.88)); color:#EDEFE8; font-size:15px; }
.lpSlide figcaption .lpMono{ color:#D5DCD6; font-size:13px; }
.lpSlideCredit{ flex-basis:100%; font-family:var(--mono); font-size:11px; color:#D5DCD6; }
.lpSlideCredit a{ color:#D5DCD6; }
.lpSlideBtn{ position:absolute; top:50%; transform:translateY(-50%); width:44px; height:44px; border:0; border-radius:50%; background:rgba(20,32,26,0.72); color:#EDEFE8; font-size:28px; line-height:1; cursor:pointer; }
.lpSlideBtn:disabled{ opacity:0; pointer-events:none; }
.lpSlidePrev{ left:10px; } .lpSlideNext{ right:10px; }
.lpDots{ position:absolute; left:0; right:0; bottom:-22px; display:flex; justify-content:center; gap:6px; }
.lpDots button{ width:8px; height:8px; padding:0; border:0; border-radius:50%; background:var(--line); cursor:pointer; }
.lpDots button[aria-current="true"]{ background:var(--ink); }
.lpHero:has(.lpCarousel){ margin-bottom:40px; }
.lpShare{ font:inherit; font-weight:500; cursor:pointer; }

/* ---- Sports (Ride · Hike · Run) ------------------------------------------
   The switch above each sport's hub (sportSwitch() in loop-pages-lib.mjs):
   plain links, the current one in ink. Shown only once two sports have
   loops. */
.lpSports{ display:flex; gap:4px; width:max-content; max-width:100%; margin:0 0 20px; padding:4px; background:var(--surface); border:1px solid var(--line); border-radius:8px; overflow-x:auto; }
.lpSport{ display:flex; align-items:center; gap:8px; min-height:44px; padding:8px 16px; border-radius:6px; color:var(--ink); text-decoration:none; font-weight:600; white-space:nowrap; }
.lpSport:hover{ background:var(--chalk-dim); color:var(--ink); }
.lpSport .lpMono{ font-weight:400; font-size:13px; color:var(--ink-soft); }
.lpSport[aria-current="page"]{ background:var(--ink); color:var(--chalk); }
.lpSport[aria-current="page"] .lpMono{ color:inherit; opacity:.75; }
/* Under a hike's or run's figures: whose time it is. */
.lpTimeNote{ margin:-4px 0 0; font-size:13px; }
/* A climb page's other sports: anchors under its figures, a section each. */
.lpClimbSports{ margin:0 0 24px; }
.lpChooseSport{ margin-top:36px; }
.lpChooseSport .lpChooseHead{ align-items:baseline; }

/* Trail difficulty on a hike's or run's page: the planner's SAC colours
   (tokens.css --sac-*), dashed for T3–T4 and dotted for T5–T6 as on the
   trail map, so the grade reads without the colour too. */
.lpGrade, .lpMakeup{ margin:16px 0 20px; }
.lpMakeup + .lpGrade{ margin-top:0; }
.lpGradeHead, .lpMakeupHead{ margin:0 0 6px; font-size:12px; font-weight:500; color:var(--ink-soft); text-transform:uppercase; letter-spacing:0.06em; }
.lpGradeBar .is-t1, .lpGradeSwatch.is-t1{ background:var(--sac-t1); }
.lpGradeBar .is-t2, .lpGradeSwatch.is-t2{ background:var(--sac-t2); }
.lpGradeBar .is-t3, .lpGradeSwatch.is-t3{ background:repeating-linear-gradient(90deg, var(--sac-t3) 0 7px, transparent 7px 10px); }
.lpGradeBar .is-t4, .lpGradeSwatch.is-t4{ background:repeating-linear-gradient(90deg, var(--sac-t4) 0 7px, transparent 7px 10px); }
.lpGradeBar .is-t5, .lpGradeSwatch.is-t5{ background:repeating-linear-gradient(90deg, var(--sac-t5) 0 2px, transparent 2px 5px); }
.lpGradeBar .is-t6, .lpGradeSwatch.is-t6{ background:repeating-linear-gradient(90deg, var(--sac-t6) 0 2px, transparent 2px 5px); }
.lpGradeBar .is-unknown, .lpGradeSwatch.is-unknown{ background:var(--sac-t0); opacity:0.5; }
.lpGradeRows, .lpMakeupRows{ list-style:none; margin:8px 0 0; padding:0; display:grid; gap:4px; font-size:14px; }
.lpGradeRows li, .lpMakeupRows li{ display:grid; grid-template-columns:22px 1fr auto; gap:8px; align-items:center; }
.lpGradeRows b{ font-weight:500; }
.lpGradeSwatch, .lpMakeupSwatch{ display:block; width:22px; height:6px; border-radius:3px; }
.lpGradeChip{ font-family:var(--mono); font-weight:500; padding:0 6px; border-radius:4px; border:1px solid var(--line); }

/* A climb page's sport tabs (app/js/loop-tabs.js): the homepage's tab bar
   (welcome.html .ltTab), an amber rule under the open one, on the page's own
   ground so it reads in both themes. */
/* The line under the tabs is an inset shadow, which the selected tab's
   border paints over: a tab pulled down over a border (margin-bottom:-1px)
   overflows the bar, and overflow-x:auto then scrolls it vertically too. */
.lpTabs{ display:flex; gap:4px; margin:8px 0 24px; box-shadow:inset 0 -1px 0 var(--line); overflow-x:auto; overflow-y:hidden; scrollbar-width:none; }
.lpTabs::-webkit-scrollbar{ display:none; }
.lpTab{ display:flex; align-items:center; gap:8px; min-height:48px; padding:0 16px; border-bottom:2px solid transparent; color:var(--ink-soft); font-weight:600; text-decoration:none; white-space:nowrap; }
.lpTab:hover{ color:var(--ink); text-decoration:none; }
.lpTab.isOn{ color:var(--ink); border-bottom-color:var(--amber); }
.lpTab .lpMono{ font-weight:400; font-size:13px; color:var(--ink-soft); }
.lpTab svg{ flex-shrink:0; }
.lpTab:focus-visible{ outline:3px solid var(--amber); outline-offset:-3px; }
.lpSportPanel + .lpSportPanel{ margin-top:32px; }
.lpSportPanel[hidden] + .lpSportPanel, .lpSportPanel + .lpSportPanel[hidden]{ margin-top:0; }
@media (max-width:440px){ .lpTab{ flex:1; flex-direction:column; justify-content:center; gap:2px; padding:6px 8px; min-height:60px; font-size:13px; } }

/* On a hub, country or region page the tabs lead to the other sports' pages
   (sportSwitch), so they sit above the search, closer to it. */
.lpSportTabs{ margin:0 0 16px; }
/* A hub's: under its search, which they carry to the other sports. */
.lpHubTabs{ margin:16px 0 12px; }
.lpHubTabs .lpMono{ transition:opacity .15s; }
.lpHubTabs.isCounting .lpTab:not(.isOn) .lpMono{ opacity:.45; }

/* ---- Glass (css/tokens.css; the rule is the iOS app's, css/chrome.css
   "Glass"): what floats over a photo, a map or the scrolling page — the
   phone's sticky bar, the slide arrows, the photo credit, a map's +/− —
   is glass; the cards and the text stay opaque. ---- */
@media (max-width:720px){
  .lpSticky{
    background:color-mix(in srgb, var(--band) var(--glass-a-header), transparent);
    -webkit-backdrop-filter:var(--glass-blur); backdrop-filter:var(--glass-blur);
    border-top:1px solid color-mix(in srgb, var(--line-on-ink) 80%, transparent);
  }
}
.lpSlideBtn, .lpCredit{
  background:color-mix(in srgb, #14201A var(--glass-a-pill), transparent);
  -webkit-backdrop-filter:var(--glass-blur); backdrop-filter:var(--glass-blur);
  border:1px solid color-mix(in srgb, #EDEFE8 22%, transparent);
  box-shadow:var(--glass-edge), var(--glass-lift);
}
.lpCredit{ border-radius:999px; padding:4px 10px; }
.lpMapCol .maplibregl-ctrl-group, .lpClimbMap .maplibregl-ctrl-group{
  border:1px solid var(--glass-rim); border-radius:22px; overflow:hidden;
  background:color-mix(in srgb, var(--ink) var(--glass-a-control), transparent);
  -webkit-backdrop-filter:var(--glass-blur); backdrop-filter:var(--glass-blur);
  box-shadow:var(--glass-edge), var(--glass-lift);
}
.lpMapCol .maplibregl-ctrl-group button, .lpClimbMap .maplibregl-ctrl-group button{
  width:40px; height:40px; line-height:40px; font-size:19px;
  background:transparent; color:var(--chalk);
  border:0; border-bottom:1px solid color-mix(in srgb, var(--chalk) 22%, transparent);
}
.lpMapCol .maplibregl-ctrl-group button .maplibregl-ctrl-icon, .lpClimbMap .maplibregl-ctrl-group button .maplibregl-ctrl-icon{ font-size:19px; }
.lpMapCol .maplibregl-ctrl-group button:last-child, .lpClimbMap .maplibregl-ctrl-group button:last-child{ border-bottom:0; }
.lpMapCol .maplibregl-ctrl-group button:not(:disabled):hover, .lpClimbMap .maplibregl-ctrl-group button:not(:disabled):hover{ background:color-mix(in srgb, var(--chalk) 12%, transparent); color:var(--chalk); }

/* When to go (docs/when-to-go.md, js/loop-when.js): the next five days, the
   chosen day's verdict, which way round and when to leave. Hidden until the
   forecast has come. Green only for a good day, as for an open stop. */
.lpWhen .lpPanelHead{ flex-wrap:wrap; }
.lpWhenSource{ font-size:12.5px; color:var(--ink-soft); }
.lpWhenDays{ display:grid; grid-template-columns:repeat(5, minmax(0, 1fr)); gap:10px; margin:6px 0 18px; }
.lpWhenDayBtn{
  display:flex; flex-direction:column; align-items:flex-start; gap:6px; min-height:64px; padding:10px 12px;
  background:var(--chalk); color:var(--ink-soft); border:1px solid transparent; border-radius:12px;
  font:inherit; text-align:left; cursor:pointer;
}
.lpWhenDayBtn .lpMono{ font-size:12px; letter-spacing:.03em; }
.lpWhenDayBtn strong{ font-size:14px; font-weight:600; }
.lpWhenDayBtn.isGood{ background:var(--open-tint); }
.lpWhenDayBtn.isGood strong, .lpWhenDayBtn.isGood .lpMono{ color:var(--open); }
.lpWhenDayBtn[aria-selected="true"]{ border:2px solid var(--amber); padding:9px 11px; color:var(--ink); background:var(--surface); }
.lpWhenDayBtn:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
.lpWhenVerdict{ margin:0 0 10px; font-family:var(--display); font-weight:500; font-size:22px; line-height:1.3; }
.lpWhenVerdict.isBad{ color:var(--ink-soft); font-size:19px; }
.lpWhenNext{ display:inline-block; margin-top:4px; }
.lpWhenFacts{ list-style:none; margin:0 0 18px; padding:0; display:flex; flex-wrap:wrap; gap:8px; }
.lpWhenFacts li{ font-size:12.5px; padding:5px 11px; border:1px solid var(--line); border-radius:999px; }
.lpWhenCards{ display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1.3fr); gap:16px; }
.lpWhenCard{ display:flex; flex-direction:column; gap:6px; padding:16px 18px; background:var(--chalk); border-radius:12px; }
.lpWhenCard strong{ font-size:17px; }
.lpWhenCard p{ margin:0; font-size:15px; line-height:1.5; }
.lpWhenLabel{ font-size:11.5px; font-weight:500; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-soft); }
.lpWhenReverse{ margin-top:8px; border-color:var(--amber); }
.lpWhenBar{ position:relative; height:22px; margin:8px 0 2px; background:var(--chalk-dim); border-radius:4px; }
.lpWhenBar span{ position:absolute; top:0; bottom:0; }
.lpWhenLight{ background:var(--line); border-radius:4px; }
.lpWhenWindow{ top:-4px !important; bottom:-4px !important; border:1.5px solid var(--open); border-radius:5px; box-sizing:border-box; }
.lpWhenRide{ top:7px !important; bottom:7px !important; background:var(--amber); border-radius:3px; }
.lpWhenTop{ top:-6px !important; bottom:-6px !important; width:2px; background:var(--ink); }
.lpWhenLegend{ list-style:none; margin:4px 0 4px; padding:0; display:flex; flex-wrap:wrap; gap:4px 14px; font-size:12.5px; color:var(--ink-soft); }
.lpWhenCredit{ margin:14px 0 0; font-size:12px; }
.lpWhenCredit a{ color:var(--ink-soft); }
@media (max-width: 699px){
  .lpWhenDays{ display:flex; overflow-x:auto; gap:8px; margin-left:-22px; margin-right:-22px; padding:0 22px 4px; scroll-snap-type:x mandatory; }
  .lpWhenDayBtn{ flex:0 0 84px; scroll-snap-align:start; }
  .lpWhenCards{ grid-template-columns:1fr; }
  .lpWhenVerdict{ font-size:20px; }
}

/* Good days (docs/when-to-go.md §7): the explorer's and the climb pages'
   filter chip, a climb row's five-day strip, a ring's good starts. Green only
   for a good day. */
.lpGood{ cursor:pointer; font:inherit; }
.lpGood.isOn, .lpGood[aria-pressed="true"]{ background:var(--open-tint); color:var(--open); border-color:var(--open); font-weight:600; }
.lpDays{ display:flex; gap:3px; margin-top:6px; }
.lpDay{ display:flex; flex-direction:column; align-items:center; gap:3px; width:32px; }
.lpDayBar{ width:22px; height:6px; border-radius:3px; background:var(--line); }
.lpDayName{ font-family:var(--mono); font-size:10.5px; color:var(--ink-soft); }
.lpDay.isGood .lpDayBar{ background:var(--open); }
.lpDay.isGood .lpDayName{ color:var(--open); font-weight:600; }
.lpPill.isGood{ border-color:var(--open); color:var(--open); background:var(--open-tint); }
.lpDaysLegend{ margin:10px 0 0; font-size:13px; }
.lpGood[hidden], .lpDays[hidden], .lpRow[hidden], .lpRows2[hidden], .lpGroupTitle[hidden], .lpDaysLegend[hidden]{ display:none; }
