/* SolarGaze — AGPL-3.0-or-later.
   Layout grammar: the left rail is what you SEE, the right column is WHEN.
   Groups carry labels, which is what keeps a dozen round buttons from turning
   back into an anonymous icon stack. */

:root{
  /* Terracotta and water: the warmth of a city's stone and the cool of its
     air and its nights, on a warm charcoal. */
  --accent:#e2673f;
  --accent-rgb:226,103,63;
  --accent-ink:#1d1410;
  --cool:#45c4b0;
  --panel:rgba(35,30,27,.68);
  --panel-solid:#231e1b;
  --panel-hi:rgba(255,245,235,.08);
  --stroke:rgba(255,245,235,.10);
  --text:#f5efe8;
  --muted:rgba(245,239,232,.58);
  --muted-2:rgba(245,239,232,.40);
  --danger:#ff5c5c;
  --r-lg:26px;
  --r-md:18px;
  --r-sm:12px;
  --shadow:0 10px 34px rgba(0,0,0,.42);
  --blur:saturate(165%) blur(22px);
  --gutter:16px;
  --ui-font:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --glass:var(--panel);
  /* The left column and the right panel share one width: the screen reads
     as a frame round the map, not as two unrelated boxes. */
  --side-w:min(360px,calc(100vw - 2*var(--gutter)));
}

*{box-sizing:border-box}
/* Any rule of ours that sets `display` outranks the UA's `[hidden]{display:none}`
   on equal specificity, so state it once, loudly, and stop worrying about it. */
[hidden]{display:none!important}

html,body{height:100%}
body{
  margin:0;background:#14110f;color:var(--text);
  font-family:var(--ui-font);
  -webkit-font-smoothing:antialiased;
  overflow:hidden;
  overscroll-behavior:none;
}
button,input,select{font-family:inherit;color:inherit}
button{cursor:pointer;border:0;background:none;padding:0}
svg{display:block}

.icon-btn svg,.round svg,.tab svg,.stack-btn svg,.wx-ico,.wordmark-mark,.search-ico,
.tools svg,.in-bar svg{
  fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;
}
.stack-btn svg .fill,.tools svg .fill{fill:currentColor;stroke:none}

#scene{position:fixed;inset:0}
#scene canvas{outline:none;touch-action:none}
button,input,select,.tab{touch-action:manipulation}
#scene.is-grabbing canvas{cursor:grabbing}
#scene.can-grab canvas{cursor:grab}

/* Cesium chrome we don't want, minus the credits (attribution must stay visible).
   The container is stretched edge to edge and the text centred inside it: it
   used to be translated by half its own width, which put the first half of
   Google's attribution off the left edge of the screen. The offsets are
   `!important` because the Viewer writes its own left/bottom/right inline on
   every resize, and inline beats any selector. */
.cesium-viewer-bottom{
  position:absolute;left:0!important;right:0!important;bottom:2px!important;top:auto!important;
  transform:none;
  display:flex;justify-content:center;
  font-family:var(--ui-font);font-size:10px;color:rgba(255,255,255,.72);
  text-shadow:0 1px 3px rgba(0,0,0,.9);z-index:2;pointer-events:none;
}
.cesium-viewer-bottom .cesium-widget-credits{
  pointer-events:auto;max-width:calc(100% - 560px);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.cesium-credit-logoContainer img{opacity:.85}
.cesium-widget-errorPanel{font-family:var(--ui-font)}

/* shared glass surface */
.glass,.panel,.search,.round,.compass,.zoom,.chip,.group-body{
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--shadow);
}

/* ══════════════════ top left: wordmark ══════════════════ */
.wordmark{
  position:relative;z-index:12;
  display:flex;align-items:center;gap:9px;height:44px;padding:0 18px 0 15px;
  border-radius:22px;text-decoration:none;color:#fff;
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--shadow);
  font-size:15.5px;font-weight:600;letter-spacing:-.015em;
  transition:transform .14s,color .14s;
}
.wordmark:hover{transform:translateY(-1px)}
.wordmark-mark{width:22px;height:22px;transition:transform .35s ease}
.wordmark-mark .sun{fill:var(--accent);stroke:none;transition:transform .35s ease}
.wordmark-mark .contours{stroke:var(--cool);stroke-width:2.6}
.wordmark-mark .contours path + path{opacity:.55}
/* The sun rises a little over its hills. */
.wordmark:hover .wordmark-mark .sun{transform:translateY(-1.5px)}

/* ══════════════════ left rail: what you see ══════════════════ */
.leftrail{
  position:fixed;left:var(--gutter);top:calc(var(--gutter) + 58px);z-index:11;
  display:flex;flex-direction:column;gap:16px;align-items:flex-start;
}
.group{display:flex;flex-direction:column;gap:6px}
.group-label{
  margin:0 0 0 6px;font-size:9.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.68);
  text-shadow:0 1px 5px rgba(0,0,0,.95),0 0 12px rgba(0,0,0,.6);
}
.group-body{
  display:flex;flex-direction:column;gap:4px;padding:5px;border-radius:24px;
}

.icon-btn{
  width:44px;height:44px;border-radius:50%;
  display:grid;place-items:center;color:var(--accent);
  transition:background .15s,color .15s,transform .12s;
}
.icon-btn svg{width:21px;height:21px}
.icon-btn:hover{background:var(--panel-hi);transform:scale(1.04)}
.icon-btn[aria-pressed="false"]{color:rgba(255,255,255,.4)}
.icon-btn.is-on{background:var(--accent);color:var(--accent-ink)}
.icon-btn.is-on:hover{background:var(--accent);filter:brightness(1.06)}
/* On, but stepping aside for now (the sun path while a layer colours the ground). */
.icon-btn.is-on.is-muted{background:rgba(var(--accent-rgb),.16);color:var(--accent)}

/* the pin-and-padlock: the shackle lifts and tilts when unlocked */
/* Seat the lock lower in the head. Centring it on the circle leaves the glyph
   looking high, because the eye reads the teardrop's tail as part of the shape
   and puts the optical centre below the geometric one. In viewBox units, so
   about 1 px at the rendered 22 px — nudge this alone to re-balance. */
.pinlock .lock{
  transform:translateY(1.2px);
  transform-box:view-box;transform-origin:12px 12px;
}
.pinlock .pin-body{fill:none}
.pinlock .lock-body{fill:currentColor;stroke:none}
.pinlock .lock-shackle{
  stroke-width:1.7;fill:none;
  transform-origin:14px 10.3px;
  transition:transform .22s cubic-bezier(.4,1.5,.5,1);
}
.icon-btn[aria-pressed="false"] .pinlock .lock-shackle{transform:translateY(-1.6px) rotate(-26deg)}

/* ── the point card ────────────────────────────────────────────────
   Two rows that share one surface. The drop-shadow sits on the wrapper and
   follows the painted shape rather than a bounding box, so the L casts an
   L-shaped shadow and there is no seam where the rows meet. */
.point-card{
  display:flex;flex-direction:column;align-items:flex-start;
  filter:drop-shadow(0 8px 22px rgba(0,0,0,.45));
}
.card-row{
  display:flex;align-items:center;padding:5px;
  background:var(--panel);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
}
/* The row is deliberately narrower than its contents when closed, so nothing
   inside may shrink to fit — the arm has to overflow and be clipped, otherwise
   the buttons squeeze up and the minus sign peeks past the edge. */
.card-row > *{flex:none}
.card-row-top{border-radius:27px 27px 0 0}
.card-row-alt{
  width:54px;overflow:hidden;
  border-radius:0 0 27px 27px;
  transition:width .26s cubic-bezier(.35,1.15,.45,1),
             border-radius .26s cubic-bezier(.35,1.15,.45,1);
}
.card-row-alt.is-open{width:168px;border-radius:0 27px 27px 27px}

.alt-arm{display:flex;align-items:center;flex:none;padding-left:2px}
.alt-arm button{
  width:30px;height:44px;font-size:17px;color:var(--muted);transition:color .15s;
}
.alt-arm button:hover{color:var(--accent)}
.alt-value{
  display:flex;align-items:baseline;justify-content:center;gap:2px;
  width:50px;flex:none;
}
.alt-value input{
  width:30px;background:none;border:0;outline:none;text-align:right;
  font-size:14px;font-weight:600;font-variant-numeric:tabular-nums;
  -moz-appearance:textfield;appearance:textfield;
}
.alt-value input::-webkit-outer-spin-button,
.alt-value input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.alt-value span{font-size:10.5px;color:var(--muted)}

/* a locked-out control should look unavailable, not broken */
.icon-btn[disabled]{opacity:.32;cursor:default}
.icon-btn[disabled]:hover{background:none;transform:none}
.icon-btn[aria-expanded="true"]{background:var(--accent);color:var(--accent-ink)}

/* ══════════════════ top right: when ══════════════════ */
.topright{
  position:fixed;right:var(--gutter);top:var(--gutter);z-index:11;
  width:min(420px,calc(100vw - 2*var(--gutter)));
  display:flex;flex-direction:column;gap:10px;
}
.searchrow{position:relative;display:flex;gap:10px;align-items:center}
.search{
  /* min-width:0 or the bar keeps its content's width and pushes the help
     button off a phone's edge. */
  flex:1;min-width:0;display:flex;align-items:center;gap:10px;height:52px;padding:0 8px 0 18px;
  border-radius:var(--r-lg);border:1px solid transparent;transition:border-color .15s;
}
.search:focus-within{border-color:rgba(var(--accent-rgb),.5)}
.search-ico{width:19px;height:19px;color:var(--muted);flex:none}
.search input{flex:1;min-width:0;background:none;border:0;outline:none;font-size:15px}
.search input::placeholder{color:var(--muted)}
.search input::-webkit-search-cancel-button{-webkit-appearance:none}

.in-bar{
  width:36px;height:36px;flex:none;border-radius:50%;display:grid;place-items:center;
  color:var(--muted);transition:background .15s,color .15s;
}
.in-bar svg{width:17px;height:17px}
.in-bar:hover{background:var(--panel-hi);color:var(--accent)}
.in-bar.is-done{color:var(--accent)}

.round{
  width:52px;height:52px;flex:none;border-radius:50%;
  display:grid;place-items:center;color:#fff;transition:transform .12s;
}
.round:hover{transform:scale(1.06)}
.round svg{width:21px;height:21px}
.round.accent{background:var(--accent);color:var(--accent-ink);font-weight:700;font-size:21px}

.results{
  position:absolute;top:60px;left:0;right:62px;margin:0;padding:6px;list-style:none;
  background:var(--panel-solid);border-radius:var(--r-md);box-shadow:var(--shadow);
  max-height:320px;overflow:auto;z-index:3;border:1px solid var(--stroke);
}
.results li{padding:11px 14px;border-radius:var(--r-sm);cursor:pointer;font-size:14px;line-height:1.35}
.results li small{display:block;color:var(--muted);font-size:12px;margin-top:2px}
.results li:hover,.results li[aria-selected="true"]{background:var(--panel-hi)}
.results li.empty{color:var(--muted);cursor:default}

/* ══════════════════ time panel ══════════════════ */
.panel{border-radius:var(--r-lg);overflow:hidden}
.sheet-handle{display:none;width:100%;height:22px;place-items:center;background:rgba(0,0,0,.18)}
.sheet-handle i{display:block;width:38px;height:4px;border-radius:2px;background:rgba(255,255,255,.35)}
.tabs{display:grid;grid-auto-flow:column;grid-auto-columns:1fr}
.tab{
  display:flex;align-items:center;justify-content:center;gap:8px;
  height:46px;font-size:12.5px;font-weight:700;letter-spacing:.09em;
  color:var(--muted);background:rgba(0,0,0,.18);transition:background .15s,color .15s;
}
.tab svg{width:16px;height:16px}
.tab:hover{color:#fff}
.tab.is-active{background:var(--accent);color:var(--accent-ink)}
.tabpane{padding:14px 18px 18px}

.clockrow{display:flex;align-items:center;gap:12px}
.clock{font-size:29px;font-weight:600;letter-spacing:-.01em;line-height:1;padding:2px 0}
.clock:hover{color:var(--accent)}
.tz{font-size:9.5px;line-height:1.25;color:var(--muted);letter-spacing:.04em;margin-left:-4px}
.tz b{color:rgba(255,255,255,.8);font-size:10.5px;font-weight:600}
.pill{
  height:34px;padding:0 16px;border-radius:17px;border:1px solid rgba(255,255,255,.28);
  font-size:13.5px;font-variant-numeric:tabular-nums;transition:border-color .15s,background .15s;
}
.pill:hover{border-color:var(--accent);background:rgba(var(--accent-rgb),.08)}
.stack-btn{
  display:flex;flex-direction:column;align-items:center;gap:2px;color:#fff;
  min-width:38px;transition:color .15s;
}
.stack-btn:hover{color:var(--accent)}
.stack-btn svg{width:22px;height:22px}
.stack-btn em{font-style:normal;font-size:9px;font-weight:600;letter-spacing:.06em;color:var(--muted)}
.stack-btn.is-on,.stack-btn.is-on em{color:var(--accent)}
#btn-now{margin-left:auto}

.sliderrow{display:flex;align-items:center;gap:12px;margin-top:14px}
.endlabel{
  font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;
  min-width:36px;flex:none;
}
.sliderrow .endlabel:last-child{text-align:right}
.slider-wrap{flex:1;min-width:0;display:flex;align-items:center}

.rng{-webkit-appearance:none;appearance:none;width:100%;height:18px;background:none;outline:none;margin:0}
.rng::-webkit-slider-runnable-track{height:5px;border-radius:3px;background:var(--track)}
.rng::-moz-range-track{height:5px;border-radius:3px;background:var(--track)}
.rng::-webkit-slider-thumb{
  -webkit-appearance:none;width:15px;height:15px;border-radius:50%;background:#fff;
  margin-top:-5px;box-shadow:0 2px 6px rgba(0,0,0,.5);transition:transform .12s;
}
.rng::-moz-range-thumb{
  width:15px;height:15px;border:0;border-radius:50%;background:#fff;
  box-shadow:0 2px 6px rgba(0,0,0,.5);
}
.rng:active::-webkit-slider-thumb{transform:scale(1.25)}
.rng:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px rgba(var(--accent-rgb),.55)}
.rng-day{--track:linear-gradient(90deg,var(--accent) 0 var(--pct,50%),rgba(255,255,255,.22) var(--pct,50%) 100%)}
.rng-year{--track:linear-gradient(90deg,rgba(255,255,255,.34) 0 var(--pct,50%),rgba(255,255,255,.18) var(--pct,50%) 100%)}
.rng-day.is-night{--track:linear-gradient(90deg,#4a6ea8 0 var(--pct,50%),rgba(255,255,255,.22) var(--pct,50%) 100%)}
/* The year row is quieter than the two the app is about: thinner, dimmer. */
.rng-yr{--track:linear-gradient(90deg,rgba(255,255,255,.26) 0 var(--pct,50%),rgba(255,255,255,.12) var(--pct,50%) 100%)}
.sliderrow-year{margin-top:8px}
.sliderrow-year .rng::-webkit-slider-runnable-track{height:3px}
.sliderrow-year .rng::-moz-range-track{height:3px}
.sliderrow-year .rng::-webkit-slider-thumb{width:12px;height:12px;margin-top:-4.5px}
.sliderrow-year .rng::-moz-range-thumb{width:12px;height:12px}
.sliderrow-year .endlabel{color:var(--muted-2)}

/* ANALYZE */
.hint{margin:2px 0 12px;font-size:12px;line-height:1.5;color:var(--muted)}
.cta{
  width:100%;height:42px;border-radius:21px;background:var(--accent);color:var(--accent-ink);
  font-weight:700;font-size:13.5px;letter-spacing:.02em;transition:filter .15s;
}
.cta:hover{filter:brightness(1.07)}
.cta:disabled{opacity:.55;cursor:default}
.bigstat{display:flex;align-items:baseline;gap:8px;margin:16px 0 10px}
.bigstat b{font-size:32px;font-weight:600;color:var(--accent);line-height:1}
.bigstat span{font-size:12px;color:var(--muted)}
.strip{display:flex;height:12px;border-radius:6px;overflow:hidden;background:rgba(255,255,255,.12)}
.strip i{flex:1 1 0;min-width:0}
.strip i.sun{background:var(--accent)}
.strip i.part{background:rgba(var(--accent-rgb),.42)}
.strip i.shade{background:rgba(255,255,255,.14)}
.striplabels{display:flex;justify-content:space-between;font-size:10.5px;color:var(--muted-2);margin-top:5px}

/* AIR. Five layers and their fine print outgrow the panel on a short screen,
   so the pane scrolls rather than the panel running under the tools. */
#pane-analyze{max-height:calc(100vh - 190px);overflow-y:auto;overscroll-behavior:contain}
.pane-h{margin:14px 0 6px;font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted,#9aa0a6)}
.pane-h:first-child{margin-top:2px}
.atmo-label{display:inline-flex;align-items:center;gap:8px;padding:0 4px;font-weight:600}
.atmo-label svg{width:18px;height:18px}
.atmo-item + .atmo-item{margin-top:12px}
.atmo-row{display:flex;align-items:center;gap:12px}
.atmo-toggle{
  display:flex;align-items:center;gap:7px;flex:none;min-width:96px;height:36px;padding:0 13px;
  border-radius:18px;background:rgba(255,255,255,.09);color:var(--muted);
  font-size:12.5px;font-weight:600;transition:background .15s,color .15s;
}
.atmo-toggle svg{
  width:17px;height:17px;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;
}
.atmo-toggle svg .fill{fill:currentColor;stroke:none}
.atmo-toggle:hover{color:#fff;background:rgba(255,255,255,.14)}
.atmo-toggle.is-on{background:var(--accent);color:var(--accent-ink)}
.atmo-read{display:flex;align-items:baseline;gap:8px;min-width:0;flex-wrap:wrap}
.atmo-read b{font-size:20px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums}
.atmo-read span{font-size:11.5px;color:var(--muted)}
.atmo-read .band{
  font-style:normal;font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:2px 7px;border-radius:7px;background:var(--c,#888);color:#111;align-self:center;
}
.wind-arrow{
  width:18px;height:18px;align-self:center;color:var(--cool);
  fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;
  transition:transform .3s ease;
}
.seg-metric,.seg-mode{margin:8px 0 2px;flex-wrap:wrap}
.seg-mode + .seg-metric{margin-top:6px}
.seg-mode button{background:rgba(255,255,255,.06);border:1px solid var(--stroke)}
.seg-mode button.is-on{border-color:transparent}
.seg-metric button{padding:5px 11px;font-size:11.5px}
/* A legend bar drawn from the very stops the drape is painted with. */
.legend{
  position:relative;height:9px;margin-top:9px;border-radius:5px;
  background:var(--ramp,rgba(255,255,255,.2));
}
.legend-mark{
  position:absolute;top:-4px;left:0;width:3px;height:17px;margin-left:-1.5px;border-radius:2px;
  background:#fff;box-shadow:0 0 0 1.5px rgba(0,0,0,.55);transition:left .25s ease;
}
.legend-lbl{display:flex;justify-content:space-between;margin-top:4px;font-size:10.5px;color:var(--muted-2)}
.atmo-label{
  display:flex;align-items:center;gap:7px;flex:none;min-width:96px;height:36px;padding:0 13px;
  border-radius:18px;background:rgba(255,255,255,.06);color:var(--muted);font-size:12.5px;font-weight:600;
}
.atmo-label svg{width:17px;height:17px;flex:none;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.atmo-label svg .fill{fill:currentColor;stroke:none}
/* Drawn on the map right now: said, not offered — the switch is the rail's. */
.atmo-label.is-on{color:var(--accent);background:rgba(var(--accent-rgb),.12)}
.fineprint{margin-top:12px}
.fineprint summary{cursor:pointer;font-size:11.5px;color:var(--muted);list-style:none}
.fineprint summary::-webkit-details-marker{display:none}
.fineprint summary::before{content:'›';display:inline-block;margin-right:6px;transition:transform .15s}
.fineprint[open] summary::before{transform:rotate(90deg)}
.fineprint .atmo-fine{margin-top:8px}

/* The legend of the layer colouring the ground, over the map, above the
   weather chip; on narrower screens above the rail row. */
.maplegend{
  position:fixed;left:var(--gutter);bottom:calc(var(--gutter) + 46px + 10px);z-index:10;
  width:250px;padding:10px 14px 9px;border-radius:var(--r-md);
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:0 8px 28px rgba(0,0,0,.35);
}
.maplegend .ml-title{display:flex;align-items:center;gap:7px;font-size:12px;font-weight:600;color:#fff}
.maplegend .ml-title svg{width:15px;height:15px;flex:none;fill:none;stroke:var(--accent);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.maplegend .ml-title svg .fill{fill:var(--accent);stroke:none}
.maplegend .legend{margin-top:8px}
body.is-gated .maplegend{display:none}
.atmo-err{color:#ffb4b4}
.atmo-fine{margin:12px 0 0;font-size:11px;color:var(--muted-2)}

/* ══════════════════ bottom left: status ══════════════════ */
.bottomleft{
  position:fixed;left:var(--gutter);bottom:var(--gutter);z-index:10;
  display:flex;flex-direction:column;gap:8px;align-items:flex-start;
}
.chip{
  display:flex;align-items:center;gap:10px;height:46px;padding:0 16px;
  border-radius:23px;text-align:left;
}
.wx-ico{width:22px;height:22px;color:var(--muted);flex:none}
.chip-txt{display:flex;flex-direction:column;line-height:1.15}
.chip-txt b{font-size:16px;font-weight:600}
.chip-txt span{font-size:10.5px;color:var(--muted)}

.usage{padding:0 18px;transition:transform .12s}
.usage:hover{transform:translateY(-1px)}
.usage-body{display:flex;flex-direction:column;gap:5px;min-width:148px}
.usage-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.usage-head span{font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.usage-head b{font-size:12px;font-weight:600;font-variant-numeric:tabular-nums}
.meter{height:4px;border-radius:2px;background:rgba(255,255,255,.16);overflow:hidden}
.meter i{display:block;height:100%;width:0;background:var(--accent);border-radius:2px;transition:width .4s ease}
.meter.is-warm i{background:#ff9f45}
.meter.is-hot i{background:var(--danger)}

/* ══════════════════ bottom right: where you look ══════════════════ */
/* A column now: the mouse card sits over the row of view controls, both
   flushed right so their edges line up against the gutter. */
.tools{
  position:fixed;right:var(--gutter);bottom:var(--gutter);z-index:10;
  display:flex;flex-direction:column;align-items:flex-end;gap:10px;
}
.toolrow{display:flex;align-items:center;gap:10px}
.compass{width:52px;height:52px;border-radius:50%;display:grid;place-items:center}
.compass svg{width:40px;height:40px;overflow:visible}
.compass .c-bg{fill:none;stroke:rgba(255,255,255,.18);stroke-width:1}
.compass .c-n{fill:var(--danger);stroke:none}
.compass .c-s{fill:rgba(255,255,255,.75);stroke:none}
.compass .c-lbl{
  fill:rgba(255,255,255,.85);stroke:none;font-size:8px;font-weight:700;
  text-anchor:middle;font-family:var(--ui-font);
}
.zoom{display:flex;height:52px;border-radius:26px;overflow:hidden}
.zoom button{width:50px;font-size:23px;font-weight:300;color:#fff;transition:background .15s}
.zoom button:hover{background:var(--panel-hi)}
.zoom button:first-child{border-right:1px solid var(--stroke)}


/* ── mouse cheat sheet ─────────────────────────────────────────────
   Collapsing animates grid-template-rows 1fr→0fr rather than height, which
   needs no measured pixel value and so survives a text-size change or a
   translated label. The clip child owns `overflow:hidden`; putting it on the
   grid parent instead would clip the card's own rounded corners. */
.mousecard{
  border-radius:var(--r-md);overflow:hidden;
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--shadow);
  min-width:186px;
}
.mousecard-head{margin:0;font-size:inherit;font-weight:inherit}
.mousecard-head button{
  display:flex;align-items:center;gap:7px;width:100%;
  padding:9px 12px 9px 11px;color:var(--muted);
  font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  transition:color .15s;
}
.mousecard-head button:hover{color:#fff}
.mousecard-ico{width:15px;height:15px;flex:none}
.mousecard-chev{width:14px;height:14px;flex:none;margin-left:auto;transition:transform .22s ease}
.mousecard[data-open="false"] .mousecard-chev{transform:rotate(-90deg)}

.mousecard-clip{display:grid;grid-template-rows:1fr;transition:grid-template-rows .22s ease}
.mousecard[data-open="false"] .mousecard-clip{grid-template-rows:0fr}
.mousecard-clip > *{overflow:hidden;min-height:0}

.mousecard-list{margin:0;padding:0 12px 11px}
.mousecard-list > div{
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:4px 0;
}
.mousecard-list dt{font-size:11.5px;color:rgba(255,255,255,.86);white-space:nowrap}
.mousecard-list dd{margin:0;display:flex;align-items:center;gap:3px}
.mousecard-list dd i{font-style:normal;font-size:9.5px;color:var(--muted-2);padding:0 1px}
.mousecard-list dd i.alt{
  font-size:8.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;padding:0 3px;
}
.mousecard kbd{
  font-family:inherit;font-size:9.5px;font-weight:600;letter-spacing:.02em;
  padding:2.5px 5px;border-radius:5px;line-height:1;
  background:rgba(255,255,255,.09);border:1px solid var(--stroke);
  color:rgba(255,255,255,.72);white-space:nowrap;
}

/* ══════════════════ tooltip ══════════════════ */
.tooltip{
  position:fixed;z-index:60;pointer-events:none;
  max-width:236px;padding:9px 13px;border-radius:11px;
  background:#0f1217;border:1px solid var(--stroke);
  box-shadow:0 8px 26px rgba(0,0,0,.5);
  font-size:12.5px;line-height:1.4;font-weight:500;
  opacity:0;transform:translateY(3px);transition:opacity .13s,transform .13s;
}
.tooltip.is-in{opacity:1;transform:translateY(0)}
.tooltip em{
  display:block;margin-top:3px;font-style:normal;font-size:11.5px;
  font-weight:400;color:var(--muted);
}

/* ══════════════════ modal, toast ══════════════════ */
.modal{
  position:fixed;inset:0;z-index:40;display:grid;place-items:center;padding:20px;
  background:rgba(8,10,13,.62);backdrop-filter:blur(4px);
}
.sheet{
  position:relative;width:min(560px,100%);max-height:88vh;overflow:auto;
  background:var(--panel-solid);border:1px solid var(--stroke);
  border-radius:var(--r-lg);box-shadow:0 24px 70px rgba(0,0,0,.6);padding:30px 32px 28px;
}
.sheet-x{position:absolute;top:14px;right:18px;font-size:26px;line-height:1;color:var(--muted)}
.sheet-x:hover{color:#fff}
.sheet h2{margin:0 0 6px;font-size:20px;font-weight:600;letter-spacing:-.01em}
.sheet h3{margin:22px 0 8px;font-size:12px;font-weight:700;letter-spacing:.09em;color:var(--accent)}
.sheet p{margin:0 0 12px;font-size:13.5px;line-height:1.6;color:rgba(255,255,255,.78)}
.sheet a{color:var(--accent)}
.sheet ol,.sheet ul{margin:0 0 12px;padding-left:20px;font-size:13.5px;line-height:1.7;color:rgba(255,255,255,.78)}
.sheet ul.sources li{margin-bottom:6px}
.sheet code{
  background:rgba(255,255,255,.09);padding:1px 6px;border-radius:5px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;
  /* A hyphenated identifier broken over two lines reads as two words. */
  white-space:nowrap;
}
.field{display:flex;gap:10px;margin:10px 0 4px}
.field input{
  flex:1;min-width:0;height:44px;padding:0 16px;border-radius:22px;
  background:rgba(0,0,0,.32);border:1px solid var(--stroke);outline:none;font-size:14px;
}
.field input:focus{border-color:var(--accent)}
.field button{
  height:44px;padding:0 22px;border-radius:22px;background:var(--accent);
  color:var(--accent-ink);font-weight:700;font-size:13.5px;
}
.rowopt{
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:11px 0;border-top:1px solid var(--stroke);font-size:13.5px;
}
.rowopt:first-of-type{border-top:0}
.rowopt small{display:block;color:var(--muted);font-size:11.5px;margin-top:2px;line-height:1.45}
.switch{
  width:44px;height:25px;border-radius:13px;background:rgba(255,255,255,.2);
  position:relative;flex:none;transition:background .18s;
}
.switch::after{
  content:'';position:absolute;top:3px;left:3px;width:19px;height:19px;border-radius:50%;
  background:#fff;transition:transform .18s;
}
.switch[aria-pressed="true"]{background:var(--accent)}
.switch[aria-pressed="true"]::after{transform:translateX(19px)}
.seg{display:flex;gap:6px}
.seg button{
  padding:7px 14px;border-radius:14px;background:rgba(255,255,255,.1);
  font-size:12px;font-weight:600;transition:background .15s;
}
.seg button.is-on{background:var(--accent);color:var(--accent-ink)}
.seg-btn{
  padding:8px 16px;border-radius:15px;background:rgba(255,255,255,.12);
  font-size:12.5px;font-weight:600;flex:none;transition:background .15s;
}
.seg-btn:hover{background:rgba(255,255,255,.2)}

/* illustrated guide steps */
.steps{counter-reset:step;list-style:none;margin:0;padding:0}
.steps li{
  counter-increment:step;position:relative;padding:0 0 22px 40px;
  border-left:1px solid var(--stroke);margin-left:13px;
}
.steps li:last-child{border-left-color:transparent;padding-bottom:4px}
.steps li::before{
  content:counter(step);position:absolute;left:-13px;top:-2px;
  width:26px;height:26px;border-radius:50%;background:var(--accent);color:var(--accent-ink);
  font-size:12.5px;font-weight:700;display:grid;place-items:center;
}
.steps h4{margin:2px 0 6px;font-size:14.5px;font-weight:600}
.steps p{margin:0 0 10px;font-size:13px}
.shot{
  display:block;width:100%;border-radius:12px;border:1px solid var(--stroke);
  background:rgba(0,0,0,.28);margin:0 0 4px;
}
.shot-missing{
  display:grid;place-items:center;min-height:104px;border-radius:12px;
  border:1px dashed rgba(255,255,255,.2);background:rgba(0,0,0,.22);
  font-size:11.5px;color:var(--muted-2);text-align:center;padding:14px;line-height:1.5;
}

.toast{
  position:fixed;left:50%;bottom:34px;transform:translateX(-50%);z-index:50;
  padding:12px 22px;border-radius:22px;background:var(--panel-solid);
  border:1px solid var(--stroke);box-shadow:var(--shadow);font-size:13.5px;
  animation:rise .22s ease-out;max-width:calc(100vw - 40px);text-align:center;
}
.toast.err{border-color:rgba(255,92,92,.5)}
@keyframes rise{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}

.spinner{
  width:16px;height:16px;flex:none;border-radius:50%;
  border:2px solid rgba(255,255,255,.22);border-top-color:var(--accent);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

.visually-hidden{
  position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ══════════════════ responsive ══════════════════
   Three widths. A laptop gets the layout above. Under 820px the labels go and
   the chrome shrinks. Under 640px — a phone held upright — the panel becomes a
   sheet docked to the bottom edge, and everything else that lived down there
   stacks on top of it, measured by `--panel-h` (see js/ui/sheet.js). */
@media (max-width:940px){
  :root{--gutter:10px}
  .wordmark{height:44px;width:44px;padding:0;justify-content:center;border-radius:22px}
  .wordmark span{display:none}
  .topright{width:min(420px,calc(100vw - 2*var(--gutter) - 54px));right:var(--gutter);left:auto}
  .leftrail{top:calc(var(--gutter) + 56px)}
  .group-label{display:none}
  .bottomleft{display:none}
  .mousecard{display:none}
  .maplegend{bottom:var(--gutter)}
  .clock{font-size:25px}
  .cesium-viewer-bottom .cesium-widget-credits{max-width:calc(100% - 260px)}
}
@media (max-width:640px){
  :root{
    --gutter:10px;--panel-h:0px;
    --top-inset:env(safe-area-inset-top,0px);
    --bottom-inset:env(safe-area-inset-bottom,0px);
  }
  .wordmark{top:calc(var(--gutter) + var(--top-inset))}

  /* Search stays at the top, the panel goes to the bottom: same column, its two
     ends pushed apart. The column itself must not eat taps meant for the map. */
  .topright{
    top:calc(var(--gutter) + var(--top-inset));
    bottom:calc(var(--gutter) + var(--bottom-inset));
    left:var(--gutter);right:var(--gutter);width:auto;
    justify-content:space-between;pointer-events:none;
  }
  .topright > *{pointer-events:auto}
  .searchrow{margin-left:54px}
  .search{height:44px;padding-left:14px}
  .search input{font-size:16px}          /* under 16px iOS zooms the page on focus */
  .round{width:44px;height:44px;font-size:19px}
  .results{top:52px;right:54px;max-height:40vh}

  .panel{border-radius:var(--r-md) var(--r-md) 0 0;margin:0 calc(-1*var(--gutter)) calc(-1*var(--gutter) - var(--bottom-inset))}
  .sheet-handle{display:grid}
  .panel.is-collapsed .tabpane{display:none!important}
  .tabpane{padding:10px 16px calc(14px + var(--bottom-inset))}
  /* Short enough that the rail row above the sheet clears the tools column. */
  #pane-analyze{max-height:40vh}
  .tab{height:42px;font-size:11px;letter-spacing:.06em;gap:6px}
  .clockrow{gap:10px}
  .clock{font-size:24px}
  .pill{height:32px;padding:0 12px;font-size:12.5px}
  .sliderrow{margin-top:10px}
  .atmo-toggle{min-width:0;padding:0 11px;font-size:12px}

  /* The rail is a row over the sheet; the tools a column above its right end. */
  .leftrail{
    top:auto;left:var(--gutter);right:var(--gutter);
    bottom:calc(var(--panel-h) + var(--gutter) + var(--bottom-inset));
    flex-direction:row;align-items:flex-end;gap:8px;
    overflow-x:auto;scrollbar-width:none;pointer-events:none;
  }
  .leftrail::-webkit-scrollbar{display:none}
  .leftrail > *{pointer-events:auto;flex:none}
  .group-body{flex-direction:row;padding:4px;gap:2px;border-radius:22px}
  .icon-btn{width:36px;height:36px}
  .icon-btn svg{width:18px;height:18px}
  .point-card{flex-direction:row;align-items:center}
  .card-row{padding:4px}
  .card-row-top{border-radius:22px 0 0 22px}
  .card-row-alt{width:44px;border-radius:0 22px 22px 0}
  .card-row-alt.is-open{width:158px;border-radius:0 22px 22px 0}
  .alt-arm button{height:36px}

  /* Anchored under the search bar rather than over the sheet: the sheet's
     height changes with the tab, and a column that rode up and down with it
     read as the controls wandering about. */
  .tools{
    right:var(--gutter);bottom:auto;
    top:calc(var(--gutter) + var(--top-inset) + 44px + 34px);
  }
  .toolrow{flex-direction:column;align-items:flex-end;gap:8px}
  .zoom{display:none}
  .round,.compass{width:44px;height:44px}

  /* Attribution moves up under the search bar, short of the tools column, and
     wraps rather than truncates: Google's line has to stay legible in full,
     and on a phone ion's logo alone would fill a single line. */
  #scene .cesium-viewer-bottom{
    top:calc(var(--gutter) + var(--top-inset) + 50px)!important;bottom:auto!important;
    left:var(--gutter)!important;right:calc(var(--gutter) + 54px)!important;
    justify-content:flex-start;font-size:9px;line-height:1.5;
  }
  #scene .cesium-viewer-bottom .cesium-widget-credits{max-width:100%;white-space:normal;overflow:visible}
  #scene .cesium-viewer-bottom img{height:12px;width:auto;vertical-align:middle}
  .atmo-fine{font-size:10px;margin-top:8px}
  .atmo-item + .atmo-item{margin-top:8px}
  .atmo-label{min-width:0;padding:0 11px;font-size:12px}
  .maplegend{
    left:var(--gutter);width:min(250px,calc(100vw - 2*var(--gutter) - 60px));padding:8px 12px 7px;
    bottom:calc(var(--panel-h) + var(--gutter) + var(--bottom-inset) + 54px);
  }

  .toast{top:calc(var(--gutter) + var(--top-inset) + 66px);bottom:auto;font-size:12.5px;padding:10px 16px}
  @keyframes rise{from{opacity:0;transform:translate(-50%,-8px)}to{opacity:1;transform:translate(-50%,0)}}

  /* Sheets fill the screen. The wordmark stays on top of everything (it has
     to outrank the gate), so the title starts below its row and the back
     arrow sits beside it rather than under it. */
  .modal{padding:0}
  .sheet{
    width:100%;max-height:100%;height:100%;border-radius:0;border:0;
    padding:calc(62px + var(--top-inset)) 18px calc(24px + var(--bottom-inset));
  }
  .sheet-x{top:calc(12px + var(--top-inset));right:12px;width:40px;height:40px}
  .sheet-back{top:calc(16px + var(--top-inset));left:62px}
  .sheet-back + #modal-body h2{margin-top:0}
  .demo-bar{bottom:calc(var(--panel-h) + 2*var(--gutter) + var(--bottom-inset) + 44px)}
  .meshload-card{margin:0 24px}
}
@media (max-height:640px){
  .bottomleft{display:none}
  .mousecard{display:none}
}
/* A phone on its side: the desktop arrangement, squeezed. The rail runs
   along the top-left as a row, since a column of eight would not fit, and the
   attribution takes the strip between the rail's end and the view tools. */
@media (max-height:500px) and (pointer:coarse){
  .tabpane{padding:8px 14px 10px}
  .sliderrow{margin-top:6px}
  .clock{font-size:22px}
  .tab{height:36px}
  .group-label{display:none}
  .leftrail{flex-direction:row;align-items:flex-start;gap:8px;top:calc(var(--gutter) + 54px)}
  .group-body{flex-direction:row;padding:4px;gap:2px;border-radius:22px}
  .icon-btn{width:36px;height:36px}
  .icon-btn svg{width:18px;height:18px}
  .point-card{flex-direction:row}
  .card-row{padding:4px}
  .card-row-top{border-radius:22px 0 0 22px}
  .card-row-alt{width:44px;border-radius:0 22px 22px 0}
  .card-row-alt.is-open{width:158px;border-radius:0 22px 22px 0}
  #scene .cesium-viewer-bottom{
    left:var(--gutter)!important;right:calc(var(--gutter) + 190px)!important;justify-content:flex-start;
    font-size:9px;line-height:1.4;
  }
  #scene .cesium-viewer-bottom .cesium-widget-credits{max-width:100%;white-space:normal;overflow:visible}
  #scene .cesium-viewer-bottom img{height:12px;width:auto;vertical-align:middle}
}
/* Fingers need bigger slider thumbs and a taller strip to land on. */
@media (pointer:coarse){
  .rng{height:30px}
  .rng::-webkit-slider-thumb{width:22px;height:22px;margin-top:-8.5px}
  .rng::-moz-range-thumb{width:22px;height:22px}
  .zoom{display:none}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* ══════════════════ guide: clips and shortcut tables ══════════════════ */
/* The clip sits flush to the sheet's text column, with the caption tucked
   under it — a border would box in a still that is already a framed rectangle. */
.guide-clip{margin:0 0 20px}
.guide-clip video{
  display:block;width:100%;aspect-ratio:1000/600;object-fit:cover;
  border-radius:var(--r-md);background:#12151a;border:1px solid var(--stroke);
}
.guide-clip figcaption{
  margin-top:7px;font-size:11.5px;line-height:1.45;color:var(--muted-2);
}

/* Shortcut tables. The keys are right-aligned so their edge makes a column,
   which is what lets you find a binding without reading the labels. */
.keys{margin:0 0 14px;padding:0}
.keys > div{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding:6px 0;border-bottom:1px solid rgba(255,255,255,.055);
}
.keys > div:last-child{border-bottom:0}
.keys dt{font-size:13px;color:rgba(255,255,255,.78);line-height:1.4}
.keys dd{margin:0;display:flex;align-items:center;gap:4px;flex:none}
.keys dd i{font-style:normal;font-size:10px;color:var(--muted-2);padding:0 1px}
.keys dd i.alt{font-size:9px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;padding:0 3px}
.keys kbd{
  font-family:inherit;font-size:10.5px;font-weight:600;letter-spacing:.02em;
  padding:3px 6px;border-radius:5px;line-height:1;white-space:nowrap;
  background:rgba(255,255,255,.09);border:1px solid var(--stroke);
  color:rgba(255,255,255,.75);
}

/* guide screenshots: annotations ride on top as percentage-positioned boxes,
   so they stay put whatever size the sheet is */
.shot-wrap{position:relative;display:block;margin:0 0 4px}
.shot-wrap .shot{margin:0}
.shot-wrap .shot-missing{display:none}
.shot-wrap.is-missing .shot{display:none}
.shot-wrap.is-missing .shot-missing{display:grid}
.shot-wrap.is-missing .point{display:none}

.point{
  position:absolute;transform:translate(-50%,-100%);
  display:flex;flex-direction:column;align-items:center;gap:2px;
  color:var(--accent);pointer-events:none;
  animation:nudge 1.7s ease-in-out infinite;
}
.point svg{
  width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2.6;
  stroke-linecap:round;stroke-linejoin:round;
  filter:drop-shadow(0 2px 5px rgba(0,0,0,.7));
}
/* Kept small: the screenshot is shown at about half size, so a label sized for
   the page would blot out the very control it is pointing at. */
/* `--dx` slides the label sideways without moving the arrow, for the cases
   where a centred label would land on the very text it is pointing past. */
.point b{
  transform:translateX(var(--dx,0));
  font-size:9.5px;font-weight:700;letter-spacing:.01em;
  padding:2px 7px;border-radius:8px;white-space:nowrap;
  background:var(--accent);color:var(--accent-ink);
  box-shadow:0 2px 6px rgba(0,0,0,.45);
}
@keyframes nudge{0%,100%{transform:translate(-50%,-100%)}50%{transform:translate(-50%,-108%)}}

.ghost-cta{
  display:flex;align-items:center;gap:10px;width:100%;margin-top:14px;
  padding:12px 16px;border-radius:14px;border:1px solid var(--stroke);
  background:rgba(255,255,255,.04);font-size:13.5px;font-weight:500;text-align:left;
  transition:border-color .15s,background .15s;
}
.ghost-cta:hover{border-color:var(--accent);background:rgba(var(--accent-rgb),.07)}
.ghost-cta svg{
  width:19px;height:19px;flex:none;color:var(--accent);
  fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;
}

/* back arrow on a nested sheet, opposite the close button */
.sheet-back{
  position:absolute;top:16px;left:20px;z-index:2;
  display:flex;align-items:center;gap:4px;
  padding:5px 12px 5px 7px;border-radius:14px;
  color:var(--muted);font-size:12.5px;font-weight:600;
  transition:background .15s,color .15s;
}
.sheet-back:hover{background:var(--panel-hi);color:#fff}
.sheet-back svg{
  width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;
}
.sheet-back + #modal-body h2{margin-top:26px}

/* ══════════════════ the credential gate ══════════════════
   Not a modal you dismiss: without Cesium ion there is no mesh, and without a
   mesh nothing casts a shadow. So the close button goes, the chrome behind it
   goes with it, and the backdrop is opaque enough that the bare globe reads as
   "nothing loaded yet" rather than as a map you were nearly allowed to use. */
.modal.is-gate{
  /* The Colosseum, already blurred in the file so the GPU is not asked to blur
     a full-screen layer every frame. 4.5 KB, and it doubles as the backdrop
     when ion is unreachable and there is no live mesh to show. */
  background:
    linear-gradient(rgba(8,10,13,.48),rgba(8,10,13,.74)),
    url('../docs/colosseum-blur.webp') center/cover no-repeat,
    #0b0d11;
}
.modal.is-gate .sheet-x{display:none}

/* The wordmark outranks the gate: whatever else is missing, the visitor should
   always be able to see whose page this is and get to the source. */
.wordmark{z-index:41}

/* Hide the cockpit while there is no world under it. */
body.is-gated .topleft > :not(.brandrow),
body.is-gated #btn-help,
body.is-gated .layerpanel,
body.is-gated .tools,
body.is-gated .bottomleft{display:none}
/* The wordmark stays over the gate, as it always has. */
body.is-gated .topleft{z-index:60}

.gate-hero{
  margin:-8px -8px 20px;border-radius:var(--r-md);overflow:hidden;
  background:rgba(0,0,0,.35);border:1px solid var(--stroke);
  aspect-ratio:640/370;   /* reserved so the sheet does not jump when the video lands */
}
.gate-hero video,.gate-hero img{display:block;width:100%;height:100%;object-fit:cover}

.gate-fine{margin-top:12px;font-size:12.5px;color:rgba(255,255,255,.5)}

.gate-alert{
  padding:12px 15px;border-radius:var(--r-md);
  background:rgba(var(--accent-rgb),.09);border:1px solid rgba(var(--accent-rgb),.32);
  color:rgba(255,255,255,.88);
}

.gate-signin-alt{justify-content:center;margin-top:10px}

.gate-alt{margin-top:18px;border-top:1px solid var(--stroke);padding-top:14px}
.gate-alt summary{
  cursor:pointer;list-style:none;font-size:13px;font-weight:600;color:var(--muted);
  display:flex;align-items:center;gap:7px;
}
.gate-alt summary::-webkit-details-marker{display:none}
.gate-alt summary::before{
  content:'';width:7px;height:7px;flex:none;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(-45deg);transition:transform .15s;
}
.gate-alt[open] summary::before{transform:rotate(45deg)}
.gate-alt summary:hover{color:#fff}
.gate-alt p{margin-top:10px}

/* ══════════════════ the loader: the mark in motion ══════════════════
   The sun rising and setting behind the contour lines as they flow past.
   Sized by `font-size` on the host so one rule serves a 16px slot in the
   search bar and a 34px one in the middle of a panel. */
.sunload{
  display:inline-block;width:1em;height:1em;flex:none;
  color:var(--accent);vertical-align:-.15em;
}
.sunload svg{display:block;width:100%;height:100%;overflow:hidden}
/* The sun rises and sets behind the near line; the lines flow by one period. */
.sunload .sl-sun{
  fill:var(--accent);
  animation:sl-rise 2.8s cubic-bezier(.45,0,.55,1) infinite;
}
.sunload .sl-waves{fill:none;stroke:var(--cool);stroke-width:2.6;stroke-linecap:round}
.sunload .sl-w1{animation:sl-flow1 3.2s linear infinite}
.sunload .sl-w2{opacity:.55;animation:sl-flow2 4.4s linear infinite}
@keyframes sl-rise{0%,100%{transform:translateY(0)}50%{transform:translateY(8.5px)}}
@keyframes sl-flow1{to{transform:translateX(26px)}}
@keyframes sl-flow2{to{transform:translateX(-20px)}}
@media (prefers-reduced-motion:reduce){
  .sunload .sl-sun,.sunload .sl-w1,.sunload .sl-w2{animation-duration:12s}
}

/* Inside a button, standing in for the label while the work runs. */
.is-working{display:inline-flex;align-items:center;justify-content:center;gap:9px}
.is-working .sunload{font-size:17px}

/* ══════════════════ mesh loading ══════════════════
   Sits above the scene and below the gate: the gate has its own busy state, and
   the two must never stack. Pointer events pass through — the camera stays
   usable while tiles stream, which is half the reason to show this at all. */
.meshload{
  position:fixed;inset:0;z-index:30;display:grid;place-items:center;
  /* Blur what is behind it: during the wait the canvas is either empty or half
     a mesh, and neither is worth reading. Lighter than the gate's backdrop,
     because this is a pause, not a door. */
  background:rgba(8,10,13,.42);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  pointer-events:none;
}
.meshload-card{
  display:flex;flex-direction:column;align-items:center;gap:11px;
  padding:30px 38px 28px;border-radius:var(--r-lg);
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border:1px solid var(--stroke);box-shadow:var(--shadow);
  animation:meshload-in .25s ease both;
}
.meshload-card b{font-size:14.5px;font-weight:600}
/* Wide enough to hold the longer note on two lines: three lines made the card
   bottom-heavy, which is what read as "off centre" even though it is not. */
.meshload-card small{font-size:12px;color:var(--muted);max-width:38ch;text-align:center}
.meshload-card #meshload-sun{font-size:54px;display:block}
@keyframes meshload-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ══════════════════ offline demo ══════════════════
   A recorded day standing in for the live mesh. The plate covers the canvas and
   the real chrome stays on top, because the point is to show what the controls
   would do — with every control that needs geometry visibly switched off. */
.demo{position:fixed;inset:0;z-index:5}
.demo-video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  background:#0b0d11;
}
.demo-bar{
  position:fixed;left:50%;bottom:calc(var(--gutter) + 6px);transform:translateX(-50%);
  z-index:31;width:min(430px,calc(100vw - 2*var(--gutter)));
  padding:15px 19px 17px;border-radius:var(--r-lg);
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border:1px solid rgba(var(--accent-rgb),.34);box-shadow:var(--shadow);
}
.demo-bar b{display:block;font-size:13.5px;color:var(--accent);margin-bottom:5px}
.demo-bar p{margin:0 0 7px;font-size:12.5px;line-height:1.55;color:rgba(255,255,255,.8)}
.demo-bar small{display:block;font-size:11.5px;line-height:1.5;color:var(--muted)}
.demo-bar small b{display:inline;color:#fff;font-size:11.5px}
.demo-bar .cta{height:38px;margin-top:11px;font-size:13px}

/* Only the time slider survives. Everything else would be lying. */
body.is-demo #search-input,
body.is-demo #btn-share,
body.is-demo #btn-help,
body.is-demo #clock-btn,
body.is-demo #date-pill,
body.is-demo #btn-now,
body.is-demo #btn-play,
body.is-demo .layerpanel,
body.is-demo .sliderrow:last-child,
body.is-demo .tools,
body.is-demo .bottomleft{
  pointer-events:none;opacity:.32;filter:grayscale(1);
}
/* The clock is a readout here, not a control: it must stay legible as the
   slider moves, or dragging tells you nothing. */
body.is-demo #clock-btn{opacity:.75;filter:none}
body.is-demo .demo-bar,body.is-demo #time-slider{pointer-events:auto}
body.is-demo #meshload,
body.is-gated #meshload{display:none}

/* A box round a whole group in a guide screenshot. Used where an arrow would
   single out one of several equally good choices. */
.markbox{
  position:absolute;border-radius:7px;pointer-events:none;
  border:2px solid var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.16),0 2px 10px rgba(0,0,0,.35);
}
.shot-wrap.is-missing .markbox{display:none}


/* ══════════════════ layout: who, where, when on the left; what to see on the right ══════════════════
   The left column is the identity (with the guide beside it), the search
   and the one selector of date and time that everything reads from. The
   right panel is a stack of cards, one per theme, each a switch. The point's
   own controls join the view tools at the bottom right. */
.topleft{
  position:fixed;left:var(--gutter);top:var(--gutter);z-index:11;
  width:var(--side-w);
  display:flex;flex-direction:column;gap:10px;
}
.brandrow{display:flex;align-items:center;gap:8px}
.brandrow .round{width:44px;height:44px;font-size:19px}
.topleft .results{right:0}
.datepanel{padding:14px 16px 16px}
.datepanel .clockrow{gap:9px}
.datepanel .pill{padding:0 12px}
.datepanel .stack-btn{min-width:0}

.layerpanel{
  position:fixed;right:var(--gutter);top:var(--gutter);z-index:11;
  width:var(--side-w);
  max-height:calc(100vh - 2*var(--gutter) - 72px);
  display:flex;flex-direction:column;
}
.layerpane{padding:12px;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;gap:8px}
#layer-rows{display:flex;flex-direction:column;gap:8px}
/* Clear of the mouse card while it is open (a first visit's reminder). */
body:has(.mousecard[data-open="true"]) .layerpanel{max-height:calc(100vh - 2*var(--gutter) - 230px)}

/* A card: its head is the switch, and looks like one. */
.lcard{
  border-radius:var(--r-md);border:1px solid rgba(255,245,235,.08);background:rgba(255,245,235,.025);
  padding:4px 12px 10px;transition:border-color .15s,background .15s;
}
.lcard.is-on{border-color:rgba(var(--accent-rgb),.65);background:rgba(var(--accent-rgb),.07)}
.lcard-head{
  display:flex;align-items:center;gap:9px;width:100%;height:40px;padding:0;
  font-size:14px;font-weight:600;color:var(--text);text-align:left;cursor:pointer;
}
.lcard-head svg{width:19px;height:19px;flex:none;fill:none;stroke:var(--muted);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;transition:stroke .15s}
.lcard-head svg .fill{fill:currentColor;stroke:none}
.lcard.is-on .lcard-head svg{stroke:var(--accent)}
.lcard-name{flex:none}
.lcard-tag{
  font-style:normal;font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  padding:2px 7px;border-radius:7px;background:rgba(255,245,235,.08);color:var(--muted);
}
.lcard-switch{
  margin-left:auto;flex:none;position:relative;width:34px;height:20px;border-radius:10px;
  background:rgba(255,245,235,.16);transition:background .18s;
}
.lcard-switch::after{
  content:'';position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;
  background:#fff;transition:transform .18s;
}
.lcard.is-on .lcard-switch{background:var(--accent)}
.lcard.is-on .lcard-switch::after{transform:translateX(14px)}
.lcard-head:hover .lcard-switch{background:rgba(255,245,235,.26)}
.lcard.is-on .lcard-head:hover .lcard-switch{background:var(--accent)}
.lcard-read{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;min-width:0}
.lcard-read b{font-size:20px;font-weight:600;line-height:1.1;font-variant-numeric:tabular-nums}
/* The detail always on its own line under the number: whether it fitted
   beside it depended on the text, and the card jumped between two layouts. */
.lcard-read span{font-size:11.5px;color:var(--muted);flex-basis:100%;margin-top:1px}
.lcard-read .band,.lcard-sub .band{
  font-style:normal;font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:2px 7px;border-radius:7px;background:var(--c,#888);color:#111;align-self:center;
}
.lcard .seg-metric{margin:8px 0 0}
.lcard-legend{margin-top:2px}
.lcard-subs:empty{display:none}
.lcard-sub{
  display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;margin-top:8px;padding-top:8px;
  border-top:1px solid var(--stroke);font-size:12px;
}
.lcard-sub-name{color:var(--muted);font-weight:600}
.lcard-sub b{font-size:14px;font-weight:600}
.lcard-sub span:last-child{font-size:11px;color:var(--muted);flex-basis:100%}
.lcard-more{margin-top:8px}
.lcard-more .ghost-cta{margin:0;width:100%;height:38px;font-size:13px}
.lcard-more .bigstat{margin-top:10px}

/* The point's controls in the tools row: lock, then the height arm. */
.toolrow .point-card{flex-direction:row;align-items:center}
.toolrow .card-row{padding:4px}
.toolrow .card-row-top{border-radius:26px 0 0 26px}
.toolrow .card-row-alt{width:52px;border-radius:0 26px 26px 0}
.toolrow .card-row-alt.is-open{width:166px;border-radius:0 26px 26px 0}
.toolrow .icon-btn{width:44px;height:44px}

@media (max-width:940px){
  :root{--side-w:min(330px,calc(50vw - 2*var(--gutter)))}
  .datepanel{padding:12px 14px 14px}
}
@media (max-width:640px){
  /* The phone rules above were written for a panel docked at the bottom;
     the date panel is not, and the layer panel docks itself. */
  .datepanel,.layerpanel{margin:0}
  .datepanel{border-radius:var(--r-md)}
  /* A phone: identity and search on top, the date under them as a compact
     strip, the cards as the bottom sheet, the tools on the right. */
  .topleft{
    top:calc(var(--gutter) + var(--top-inset));left:var(--gutter);right:var(--gutter);width:auto;gap:8px;
  }
  .brandrow .round{width:40px;height:40px;font-size:17px}
  .topleft .search{height:42px;padding-left:14px}
  .topleft .search input{font-size:16px}
  .datepanel{padding:8px 12px 10px}
  .datepanel .sliderrow{margin-top:6px}
  .datepanel .clock{font-size:22px}
  /* The hour stays a slider; the day and the year are the date pill's (a
     calendar), so the map keeps its middle. */
  .datepanel .sliderrow + .sliderrow{display:none}
  /* The credits are a strip across the top of the sheet, the tools above them. */
  #scene .cesium-viewer-bottom{
    top:auto!important;bottom:calc(var(--panel-h) + 4px)!important;
    left:var(--gutter)!important;right:var(--gutter)!important;
  }
  .layerpanel{
    top:auto;bottom:0;left:0;right:0;width:auto;max-height:46vh;
    border-radius:var(--r-md) var(--r-md) 0 0;
  }
  .layerpanel .sheet-handle{display:grid}
  .layerpanel.is-collapsed .layerpane{display:none}
  .layerpane{padding:8px 10px calc(10px + var(--bottom-inset))}
  .lcard{padding:2px 10px 8px}
  .lcard-head{height:36px;font-size:13.5px}
  .lcard-read b{font-size:18px}
  .tools{
    right:var(--gutter);bottom:calc(var(--panel-h) + 58px);top:auto;
  }
  .toolrow{flex-direction:row;flex-wrap:wrap;justify-content:flex-end;gap:6px}
  .toolrow .round,.toolrow .compass{width:42px;height:42px}
  .toolrow .icon-btn{width:36px;height:36px}
  .toolrow .card-row-alt{width:44px}
  .toolrow .card-row-alt.is-open{width:150px}
}
