/* Map Room: the hub page and its three pieces (see APPS.md in the site repo).
   Uses the app layer's header, switch, icon buttons, buttons, segmented and
   info modal, and the hub gallery. Adds: the studies' plot tokens (from
   style.css), mapped onto the site's tokens where one exists, and the globe
   frame. present.css, shipped beside this file, lays out the presentations. */
:root{
  --surface:var(--bg-medium);--card:var(--bg-card);--muted:var(--text-muted);--caption:var(--text-caption);--hover:var(--hover-bg);
  --selected:var(--text-strong);--selected-text:var(--bg);--sans:var(--font-sans);--mono:var(--font-mono);
  --present-header:59px;
  --plot-ring:#e2e5e6;--plot-home:#bbc4c4;--plot-ink:#477587;--group-0:#367ba0;--group-1:#bb7040;
  --map-land:#f4f6f7;--map-water:#dae5e9;--map-road:#ffffff;--map-park:#e3ece5;--map-building:#e8ebed;
}
html.dark{
  --plot-ring:#30302e;--plot-home:#555b57;--plot-ink:#81b9c8;--group-0:#80bbdf;--group-1:#e7aa78;
  --map-land:#1a1a18;--map-water:#111c20;--map-road:#3c3c38;--map-park:#202e27;--map-building:#272724;
}
@media(max-width:690px){:root{--present-header:51px}}
*{box-sizing:border-box}

/* A piece: the header, then the presentation filling the rest of the screen. */
.app-title a:hover{color:var(--accent-deep)}
.piece{padding:0 var(--gutter)}
.piece-intro{display:flex;justify-content:space-between;align-items:flex-end;gap:24px;max-width:1500px;margin:0 auto;padding:28px 0 20px}
.piece-intro p{max-width:560px;color:var(--text-muted);font-size:14px;line-height:1.65}
.piece-intro .eyebrow{margin-bottom:8px}
.map-credit{max-width:1500px;margin:0 auto;padding:12px 0 24px;font:10px var(--font-mono);color:var(--text-faint)}.map-credit a:hover{color:var(--accent-deep)}

/* The globe frame shared by Flights and Counties. */
.globe-wrap{position:relative;width:100%;background:radial-gradient(ellipse at center,var(--surface),var(--bg) 72%);overflow:hidden;border-radius:var(--radius-xs)}
/* After present.css, which sizes the study's frame. */
body.present-mode .globe-wrap{height:clamp(420px,calc(100dvh - var(--present-header) - 150px),860px);margin:0}
.globe-wrap:fullscreen{height:100%;width:100%;background:var(--bg)}
.globe-wrap>canvas{width:100%;height:100%;display:block;touch-action:none;cursor:grab}.globe-wrap>canvas:active{cursor:grabbing}
.county-wrap{background:var(--map-water);border:1px solid var(--border)}
.globe-corner{position:absolute;left:14px;bottom:14px;display:flex;flex-direction:column;gap:7px;pointer-events:none;text-shadow:0 0 5px var(--bg),0 0 10px var(--bg)}
.globe-corner>span{font:10px var(--font-sans);color:var(--text-muted)}
.map-date{font:500 15px var(--font-sans)!important;letter-spacing:-.2px;color:var(--text)!important;font-variant-numeric:tabular-nums}
#map-tally{font:500 10px var(--font-mono)!important;letter-spacing:.3px;font-variant-numeric:tabular-nums}
.map-progress{position:absolute;left:0;right:0;bottom:0;height:2px;pointer-events:none}.map-progress i{display:block;height:100%;background:var(--accent);transform-origin:left;transform:scaleX(0)}
/* Loading: an eyebrow-style label over the bare map, a hairline filling under it. */
#load-status{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;display:flex;flex-direction:column;align-items:center;gap:12px;font:500 10px/14px var(--font-mono);letter-spacing:.6px;text-transform:uppercase;color:var(--text-muted);text-shadow:0 0 5px var(--bg),0 0 10px var(--bg);white-space:nowrap;pointer-events:none;z-index:2}
#load-status::after{content:'';width:140px;height:2px;border-radius:1px;background:linear-gradient(var(--accent),var(--accent)) no-repeat,color-mix(in srgb,var(--text) 12%,transparent);background-size:calc(var(--load,0) * 100%) 100%,100% 100%;transition:background-size .35s ease}
#load-status{transition:opacity .3s ease}#load-status.done{opacity:0}
#load-status.failed::after{display:none}
@media(prefers-reduced-motion:reduce){#load-status,#load-status::after{transition:none}}
.county-tip{position:absolute;pointer-events:none;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 10px;font-size:11px;line-height:1.5;color:var(--text-muted);max-width:260px;white-space:nowrap;box-shadow:var(--shadow-popover);z-index:2}.county-tip strong{display:block;color:var(--text);font-weight:500;font-size:12px}
.present-tools .button{background:var(--bg-overlay)}
.present-slot .segmented,#present-modes{min-width:0;background:var(--bg-overlay)}.present-slot .segmented button{white-space:nowrap}

/* Full bleed: the map is the page. A back link, the about box and the theme
   button ride on it with the controls; nothing scrolls. */
body.bleed{margin:0;padding:0;height:100dvh;overflow:hidden;background:var(--map-water)}
body.bleed .bleed-stage.globe-wrap{position:fixed;inset:0;height:auto;width:auto;margin:0;border:0;border-radius:0}
.bleed .present-tools{left:max(12px,env(safe-area-inset-left));right:max(12px,env(safe-area-inset-right));top:max(12px,env(safe-area-inset-top))}
.bleed-nav{display:flex;align-items:flex-start;gap:6px;flex-wrap:wrap}
.bleed .present-buttons{gap:6px;align-items:center}.bleed .present-buttons .icon-button{width:40px;height:40px;min-height:0;padding:0;background:var(--bg-overlay);border-color:var(--border)}
.bleed .present-buttons .icon-button:hover{color:var(--text)}.bleed #present-view{margin-right:4px}.bleed #present-view button{min-height:38px}
/* The way back is plain text at the tabs' height, so its words sit on their centre line. */
.bleed-back.bleed-back{display:inline-flex;align-items:center;gap:4px;height:44px;min-height:0;padding:0 10px 0 2px;background:none;border-color:transparent;box-shadow:none;color:var(--text);text-shadow:0 0 5px var(--bg),0 0 10px var(--bg)}.bleed-back.bleed-back:hover{background:none;color:var(--accent-deep)}.bleed #present-modes button{min-height:38px}.bleed-back .icon{width:16px;height:16px}
.bleed .globe-corner{bottom:max(22px,calc(env(safe-area-inset-bottom) + 14px))}
.app-modal .map-credit{padding:8px 0 0;margin:0}
#present-view{background:var(--bg-overlay)}

/* Yarnball at full bleed: the clocks fill the screen under the toolbar, as large as
   fits without scrolling; a tab or a clock opens one over the whole stage. The
   transport (play, reset, full screen) shows only with a clock open. */
body.bleed.present-yarnball{background:var(--bg)}body.present-open .yarn-stage .present{overflow:hidden}
body.bleed .yarn-stage{position:fixed;inset:0;background:var(--bg)}body.bleed.present-yarnball>main.yarn-stage{display:block!important}
body.bleed .yarn-stage .present{position:absolute;inset:0;max-width:none;margin:0;display:grid;place-items:center;padding:calc(var(--tools,60px) + 12px) var(--gutter) calc(20px + env(safe-area-inset-bottom,0px));overflow:auto}
.yarn-stage .present-grid{--tile:min(calc((100vw - 2 * var(--gutter) - (var(--cols,4) - 1) * 28px) / var(--cols,4)),calc((100dvh - 50px - var(--tools,60px) - var(--rows,1) * 80px) / var(--rows,1)),360px);grid-template-columns:repeat(var(--cols,4),var(--tile));gap:28px}
@media(max-width:960px){.yarn-stage .present-grid{--tile:min(calc((100vw - 2 * var(--gutter) - 28px) / 2),300px);grid-template-columns:repeat(2,var(--tile))}}
@media(max-width:420px){.yarn-stage .present-grid{--tile:calc((100vw - 2 * var(--gutter) - 18px) / 2);gap:18px}}
.yarn-stage .present-overlay{position:fixed;inset:0;z-index:2;display:block;padding:0;background:var(--bg)}.yarn-stage .present-overlay[hidden]{display:none}
.yarn-stage .present-stage{position:absolute;left:50%;top:calc((100% + var(--tools,60px)) / 2 - 16px);transform:translate(-50%,-50%);width:min(calc(100vw - 2 * var(--gutter)),calc(100dvh - var(--tools,60px) - 90px))}
body.bleed.present-yarnball:not(.present-open) #present-full{display:none}
.yarn-stage #present-homes button,.yarn-stage #year-tabs button{min-height:38px;flex-shrink:0}
/* Many homes: the tabs scroll sideways rather than run off the screen. */
.yarn-stage .bleed-nav{min-width:0;max-width:100%}.yarn-stage #present-homes,.yarn-stage #year-tabs{max-width:calc(100vw - 24px);overflow-x:auto;scrollbar-width:none}.yarn-stage #present-homes::-webkit-scrollbar,.yarn-stage #year-tabs::-webkit-scrollbar{display:none}
.yarn-stage:fullscreen{background:var(--bg)}

/* Play and reset on every screen, at the bottom right by the scrubber; the keys note rides above them. */
.map-transport{position:absolute;right:max(14px,env(safe-area-inset-right));bottom:max(22px,calc(env(safe-area-inset-bottom) + 14px));z-index:2;display:flex;gap:6px}
.map-transport .icon-button{width:40px;height:40px;min-height:0;padding:0;background:var(--bg-overlay);border-color:var(--border)}.map-transport .icon-button:hover{color:var(--text)}.map-transport [hidden]{display:none}
.bleed .map-keys{bottom:calc(max(22px,calc(env(safe-area-inset-bottom) + 14px)) + 52px)}
.bleed #present-full[hidden]{display:none}

/* On a phone the segmented choices fold into one button naming the choice; it opens a menu of them (map-room.js). */
.picker{display:none;position:relative;min-width:0}.picker[hidden]{display:none!important}
.bleed .present-tools.folded .segmented[role=group]{display:none}.bleed .present-tools.folded .picker{display:block}.bleed .present-tools.folded{flex-wrap:nowrap}.bleed .present-tools.folded .bleed-nav{flex-wrap:nowrap;min-width:0}
.bleed .picker-toggle.picker-toggle{display:inline-flex;align-items:center;gap:4px;max-width:100%;height:40px;min-height:0;padding:0 8px 0 14px;background:var(--bg-overlay);border-color:var(--border);color:var(--text);font-size:13px}
.picker-toggle span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.picker-toggle .icon{flex-shrink:0;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.75}
.picker-menu{position:absolute;left:0;top:calc(100% + 6px);z-index:5;min-width:210px;max-height:calc(100dvh - 90px);overflow:auto;padding:6px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-popover)}
.picker-heading{margin:8px 10px 4px;font:500 9px var(--font-mono);letter-spacing:.6px;text-transform:uppercase;color:var(--text-caption)}.picker-heading:first-child{margin-top:4px}
.picker-item{display:flex;align-items:center;width:100%;min-height:42px;padding:0 10px;border:0;border-radius:var(--radius-xs);background:none;font:14px var(--font-sans);color:var(--text-muted);text-align:left;cursor:pointer}
.picker-item:hover,.picker-item:focus-visible{background:var(--hover-bg);color:var(--text);outline:0}.picker-item[aria-pressed=true]{color:var(--text);font-weight:500}
.picker-item[aria-pressed=true]::after{content:'';margin-left:auto;width:6px;height:6px;border-radius:50%;background:var(--accent)}

@media(max-width:690px){
  .bleed .present-tools{flex-wrap:nowrap;align-items:center}.bleed .bleed-nav{flex-wrap:nowrap;align-items:center;min-width:0}
  .bleed .present-tools .segmented[role=group]{display:none}.map-key{align-items:flex-start}.map-key span{min-width:0;flex:1 1 0;white-space:normal;line-height:1.3}.bleed .picker{display:block}
  .bleed .bleed-back.bleed-back{width:40px;padding:0;justify-content:center;font-size:0;gap:0}.bleed-back.bleed-back .icon{width:20px;height:20px}
  .piece-intro{flex-direction:column;align-items:flex-start;gap:8px;padding:20px 0 14px}
  body.present-mode .globe-wrap{margin:0 calc(-1 * var(--gutter));width:calc(100% + 2 * var(--gutter));border-radius:0;border-left:0;border-right:0;height:min(72vh,600px)}
  .present-tools .button{min-height:36px;font-size:11px;padding:6px 9px}
}

/* The county box: the record and a portrait, a tab each. */
.county-modal .app-modal-header{align-items:flex-start}.county-modal .app-modal-header .eyebrow{margin:0 0 4px}
.county-tabs{margin:14px 24px 0}
.county-modal .app-modal-body{padding-top:16px}
.county-block+.county-block{margin-top:18px}.county-block h3{margin:0 0 6px}
.county-facts{display:grid;grid-template-columns:118px 1fr;gap:4px 18px;margin:0 0 12px;font-size:13px}
.county-facts dt{color:var(--text-caption);font:10.5px/20px var(--font-mono);letter-spacing:.3px;text-transform:uppercase}
.county-facts dd{margin:0;color:var(--text);font-variant-numeric:tabular-nums}
.county-swatch{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:7px;vertical-align:-1px}
.county-empty{color:var(--text-muted)}
.county-photo{margin:0 0 14px}
.county-photo img{display:block;width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:var(--radius-lg);background:var(--bg-medium)}
.county-photo figcaption{margin-top:6px;font:10px var(--font-mono);color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.county-photo figcaption a{color:inherit!important}
.county-links{display:flex;gap:16px;margin-top:14px!important;font-size:13px}
.county-modal .map-credit{padding-top:12px}
/* The highpoint box: the turning terrain, then the photos on bdharva.com. */
.peak-terrain{margin:0 0 14px}.peak-mesh{display:block;width:100%;height:240px}
.peak-terrain figcaption{margin-top:4px;text-align:center;font:10px var(--font-mono);color:var(--text-faint)}
.peak-gallery{display:block;margin-top:14px;color:var(--text)!important;text-decoration:none!important}
.peak-gallery img{display:block;width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:var(--radius-lg);background:var(--bg-medium)}
.peak-gallery span{display:block;margin-top:8px;font-size:13px;color:var(--accent-deep)}.peak-gallery:hover span{text-decoration:underline}
.box-jump{padding:0;border:0;background:none;font:inherit;color:var(--accent-deep);cursor:pointer;text-align:left}.box-jump:hover{text-decoration:underline}
/* Flights at full bleed: the globe's own backdrop, edge to edge. */
body.bleed-globe{background:var(--bg)}
.yarn-stage #present-count{margin:0;font:500 10px var(--font-mono);letter-spacing:.3px;font-variant-numeric:tabular-nums}

/* Beer Styles: the stepped key's unrated cell set apart, the new-style ticks under the scrubber,
   and the beer list in a node's box. */
#beer-tip{white-space:normal;width:max-content;max-width:min(300px,calc(100vw - 32px))}
.map-key .map-key-apart{margin-left:10px}.map-key .map-key-apart i{border-radius:2px;margin-right:0}
.map-events{position:absolute;left:0;bottom:4px;width:100%;height:6px;pointer-events:none;stroke:var(--text-muted);opacity:.55}.map-events line{vector-effect:non-scaling-stroke;stroke-width:1}
.beer-list-head{display:flex;justify-content:space-between;margin:16px 0 4px;font:10px var(--font-mono);letter-spacing:.3px;text-transform:uppercase;color:var(--text-caption)}
.beer-list{list-style:none;margin:0;padding:0}.beer-list li{display:flex;justify-content:space-between;gap:14px;padding:8px 0;border-top:1px solid var(--border)}
.beer-list strong{display:block;font-weight:500;font-size:13px;color:var(--text)}.beer-list small{font-size:11px;color:var(--text-muted)}
.beer-scores{flex-shrink:0;font:12px var(--font-mono);color:var(--text);font-variant-numeric:tabular-nums}
/* A beer's panel: a hero of the label on a blurred wash of its own colours, then the
   description, facts and my check-ins. */
.beer-modal{padding:0;overflow:hidden auto;width:min(560px,calc(100vw - 24px))}
.beer-hero{position:relative;display:grid;grid-template-columns:auto 1fr;gap:20px;align-items:end;padding:56px 24px 22px;overflow:hidden;isolation:isolate;
  background:linear-gradient(160deg,color-mix(in srgb,var(--tone) 55%,transparent),transparent 70%)}
.beer-wash{position:absolute;inset:-40px;z-index:-1;background:center/cover no-repeat;filter:blur(36px) saturate(1.8);opacity:.75;transform:scale(1.2)}
.beer-hero::after{content:'';position:absolute;inset:0;z-index:-1;background:linear-gradient(to bottom,transparent 30%,var(--bg-card) 100%)}
.beer-label{width:148px;height:148px;border-radius:18px;object-fit:cover;background:#fff;box-shadow:0 18px 40px -12px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.12);transform:rotate(-3deg)}
.beer-label[hidden]{display:none}.beer-label[hidden]+.beer-titles{grid-column:1/-1}
.beer-titles{min-width:0}.beer-titles .eyebrow{margin:0 0 6px}.beer-titles h2{margin:0;font-size:28px;line-height:1.1;letter-spacing:-.5px;text-wrap:balance}
.beer-brewery{margin:8px 0 0;font-size:13px;color:var(--text-muted)}
.beer-close.beer-close{position:absolute;top:14px;right:14px;background:var(--bg-overlay)}
.beer-hero.pop .beer-label{animation:beer-pop .55s cubic-bezier(.34,1.56,.64,1) both}
@keyframes beer-pop{from{transform:scale(.6) rotate(-12deg);opacity:0}to{transform:rotate(-3deg);opacity:1}}
@media(prefers-reduced-motion:reduce){.beer-hero.pop .beer-label{animation:none}}
@media(max-width:520px){.beer-hero{grid-template-columns:1fr;padding-top:56px}.beer-label{width:120px;height:120px}.beer-titles h2{font-size:24px}}
.beer-modal .app-modal-body{padding-top:6px}
.beer-description{margin:0 0 16px;font-size:14px;line-height:1.6;color:var(--text-muted)}
.beer-checkins{list-style:none;margin:0;padding:0}.beer-checkins li{padding:10px 0;border-top:1px solid var(--border)}
.beer-checkin-top{display:flex;justify-content:space-between;gap:12px;font-size:13px;color:var(--text-muted)}.beer-checkin-top strong{color:var(--text);font-weight:500;font-variant-numeric:tabular-nums}
/* The hub's ledger: a row of counts under the intro. */
.hub-ledger{display:flex;flex-wrap:wrap;gap:6px 18px;list-style:none;margin:22px 0 0;padding:0;font:12px/1.6 var(--mono);color:var(--muted)}.hub-ledger strong{color:var(--text);font-weight:500}
@media(max-width:690px){.hub-ledger{flex-direction:column;gap:4px}}
/* Yarnball's year view: summary clocks sized by width; the page scrolls. */
.yarn-stage .present-grid.present-years{--tile:min(calc((100vw - 2 * var(--gutter) - (var(--cols,4) - 1) * 28px) / var(--cols,4)),260px)}
body.bleed .yarn-stage .present:has(.present-years){place-items:start center;padding-top:calc(var(--tools,60px) + 52px)}
@media(max-width:960px){.yarn-stage .present-grid.present-years{--tile:min(calc((100vw - 2 * var(--gutter) - 28px) / 2),300px)}}
@media(max-width:420px){.yarn-stage .present-grid.present-years{--tile:calc((100vw - 2 * var(--gutter) - 18px) / 2)}}
/* Yarnball's key: the two colours, bottom left like the other pieces' legends; over an open
   clock it sits above the date and day count. */
.yarn-key{position:fixed;left:14px;bottom:max(22px,calc(env(safe-area-inset-bottom) + 14px));z-index:3;display:flex;flex-wrap:wrap;gap:4px 14px;max-width:calc(100vw - 2 * var(--gutter));margin:0;font:9px/1.6 var(--mono);letter-spacing:.3px;color:var(--muted);text-shadow:0 0 5px var(--bg),0 0 10px var(--bg);pointer-events:none}
.yarn-key span{display:inline-flex;align-items:center;gap:6px}.yarn-key i{width:14px;height:2px;border-radius:1px}.yarn-key .yarn-key-note{color:var(--caption)}
body.loading .yarn-key{opacity:0}
body.present-open .yarn-key{bottom:calc(max(22px,calc(env(safe-area-inset-bottom) + 14px)) + 50px)}
body.bleed .yarn-stage .present{padding-bottom:calc(56px + env(safe-area-inset-bottom,0px))}
/* On a phone a modal (county, beer, about) fills the screen edge to edge and scrolls as one
   page; the county box keeps its title and close button pinned at the top. */
@media(max-width:690px){
  .app-modal{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0;inset:0;border:0;border-radius:0;box-shadow:none}
  .app-modal .app-modal-header{padding-top:calc(18px + env(safe-area-inset-top,0px))}
  .app-modal .app-modal-meta{padding-bottom:calc(18px + env(safe-area-inset-bottom,0px))}
  .county-modal .app-modal-header{position:sticky;top:0;z-index:2;background:var(--bg-card);padding-bottom:12px}
  .beer-modal .beer-hero{padding-top:env(safe-area-inset-top,0px)}
}
/* Focus rings only while tabbing (map-room.js sets .keyboard-nav). */
html:not(.keyboard-nav) :focus-visible{outline:none}
/* A hub card: picture, title, line, and the link. */
.hub-card h2{margin-top:20px}.hub-card p{margin-bottom:14px}.hub-card-cta{font-size:12px;color:var(--accent-deep)}

/* Lists in the info boxes sit flush with the paragraphs: the bullets on the text edge. */
.app-modal-body ul{margin:0 0 8px;padding-left:1.1em}
