/* Sky tab styles. Loaded in the order base, weather, sky, about. */
.sky-scene{position:relative;isolation:isolate;overflow:hidden}
.sky-scene::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background-image:var(--scene-image,none);background-size:cover;background-position:center;background-repeat:no-repeat;filter:var(--picture-filter)}
#visibleTonightCard::before{background-position:72% center}
#visibleTonightCard{min-height:270px;padding:30px}
.sky-score,.iss-card{position:relative;overflow:hidden;isolation:isolate;background-color:#0d0c31;background-image:none!important}
.sky-score::before,.iss-card::before{content:"";position:absolute;inset:0;z-index:-1;background-repeat:no-repeat;background-position:center;background-size:cover;transform:scale(1.06);filter:var(--picture-filter)}
.sky-score::before{background-image:url('/api/sky-image?name=conditions&v=3')}
/* VAL-06 follow-up, Marcus's site audit 2026-09-23: the ISS photo (previously the removed "Satellite passes"
   tile's background) moved here, onto the surviving "Next ISS passes" card, instead of being dropped -- Marcus's
   no-degradation condition on this audit work. Same picture, same NASA/JSC credit (issPictureCredit() in
   sky.js, unchanged), same .on-picture ink treatment as the other picture tiles. */
.iss-card::before{background-image:url('/api/sky-image?name=iss&v=1')}
/* Marcus: a tile picture was too bright behind its text (see test/sky-ink.test.mjs, "Brightness is a property
   of the picture as shown"). The ISS photo, unlike the conditions picture sharing this rule, measured 0.362 mean
   luminance through the shared filter alone -- brightness(.6) brings it under the 0.12 ceiling, the same
   treatment the satellite tile's picture had before VAL-06 (carried forward here, not reinvented). */
.iss-card::before{filter:brightness(.6) var(--picture-filter)}
.iss-card{min-height:clamp(170px,20vw,240px)}
#planetBars:empty{display:none}
.pbars{margin-top:14px}.pbar-rows{display:grid;gap:8px}
.pbar{display:grid;grid-template-columns:72px minmax(0,1fr);align-items:center;gap:10px;font-size:1rem;font-weight:700;color:var(--ink)}
.pbar-track{position:relative;display:block;height:14px;border-radius:7px;background:var(--track-soft);overflow:hidden}
.pbar-track:before{content:"";position:absolute;top:0;bottom:0;left:var(--bl);width:var(--bw);background:rgba(var(--accent-rgb),.16)}
.pbars-now .pbar-track:after{content:"";position:absolute;top:-1px;bottom:-1px;left:var(--now);width:2px;background:var(--focus);box-shadow:0 0 2px #000}
.pbar-track i{position:absolute;top:2px;bottom:2px;border-radius:5px;background:var(--sky)}
.pbar-axis{display:flex;justify-content:space-between;margin:6px 0 0 82px;font-size:1rem;color:var(--ink-soft)}
.pbar-key{display:block;margin-top:4px;color:var(--muted);font-size:1rem}
.moon-row{display:grid;grid-template-columns:36px minmax(0,1fr);column-gap:12px;align-items:center}.moon-row-icon{grid-row:span 2;color:#f1edff;filter:drop-shadow(0 0 1px #000) drop-shadow(0 0 3px rgba(0,0,0,.8))}
.iss-graphic{list-style:none;color:#f1edff;padding:6px 0 10px}.iss-graphic svg{display:block;width:min(240px,70%);height:auto;filter:drop-shadow(0 0 1px #000) drop-shadow(0 0 3px rgba(0,0,0,.8))}
.sky-hero{padding:30px;margin-top:10px;background:linear-gradient(135deg,rgba(72,38,112,.74),rgba(20,28,66,.7))}
.sky-hero h2{font-size:clamp(2rem,5vw,3.6rem);letter-spacing:-.06em;margin:8px 0}
.sky-hero p{max-width:620px;color:#ddd4ee;line-height:1.55;margin:0}
.sky-grid{display:grid;grid-template-columns:1.25fr .75fr;gap:18px;margin-top:18px}
.sky-score{padding:25px}
.sky-score b{display:block;font-size:2rem;letter-spacing:-.05em;margin:10px 0}
.sky-score p{color:#d4cae6;line-height:1.5;margin:0}
/* PLATFORM, 2026-09-23: at 320px #skyFacts ran 7px past the screen -- a pre-existing bug this HOLD's real-screen
   pinned test exposed (the old scrollWidth/innerWidth check couldn't see it, for the same reason the header
   overflow could hide from it: mobile emulation widens the reported viewport to fit unshrinkable content). A
   grid track written as a bare 1fr does not override its item's own automatic minimum size (the same gotcha as
   a flex item's default min-width:auto): each .sky-fact card's longest label ("Moon illumination") plus its
   fixed 44px icon padding needed more than half the row at 320px, so the grid grew past its container instead
   of wrapping the label. minmax(0,1fr) lets the track (and so the card) shrink below that content minimum;
   min-width:0 on .sky-fact carries the same permission through to the label text so it wraps instead of forcing
   the card wider. */
.sky-facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.sky-fact{min-width:0}
.sky-fact{padding:18px}
.sky-fact{position:relative}
.sky-fact>span{padding-right:44px}
.fact-icon{position:absolute;top:16px;right:16px;width:28px;height:28px;color:var(--ink)}
/* Marcus, 2026-09-23 (screenshot): align-items:stretch grew Planet times' own card border to match the left
   column's height, leaving the leftover space bordered and empty -- with a ~400px imbalance at the time, that
   read as a broken, obviously-empty card, so stretch was dropped in favor of align-items:start (each card
   sizes to its own content, the leftover sits in the grid gap outside both cards).
   Marcus, 2026-09-24 (screenshot, Port Orange FL): with the imbalance down to ~190px, align-items:start's
   leftover read as a large dead gap next to a short card, so stretch was tried instead -- but PLATFORM's
   mobile-emulation review found stretch just moves the same problem: a tall-left case leaves 466-915px of
   empty bordered space inside Planet times' own border, and a tall-right case (Planet times taller) makes the
   last-child:flex:1 rule stretch the left column's own last tile by 1503-2467px. Marcus's decision (option 1,
   2026-09-24): no stretch at all -- back to align-items:start and no flex:1 stretch on .data-col's last tile --
   and shorten the left column instead by widening Night conditions to 3 columns above 1024px (see
   #nightConditionsList below), so the two columns' content heights stay close without any card growing past
   its own content (test/sky-nightcond-gap.test.mjs). .tonight-row keeps its own align-items:stretch (line
   below) unaffected -- a different row, its own reasons, already fine either way. */
.sky-data-row,.tonight-row{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:18px;align-items:start}.data-col{display:flex;flex-direction:column;gap:18px;min-width:0}
.tonight-row{align-items:stretch}.tonight-row>section{margin-top:0;min-width:0;display:flex;flex-direction:column}.tonight-row>section>.card{flex:1}
.data-tile{padding:20px}
.data-tile>b,.iss-card .on-picture>b{display:block;font-size:1.05rem;margin-bottom:6px}
.data-tile p+p{margin-top:8px}.viz-body{display:grid;grid-template-columns:minmax(0,1fr) minmax(170px,44%);gap:16px;align-items:center}.viz{min-width:0}.viz-svg{display:block;width:100%;height:auto;color:var(--ink)}.viz-wide{margin-top:14px}.viz-ring{fill:none;stroke:var(--muted);stroke-width:1.5}.viz-grid{fill:none;stroke:var(--muted);stroke-width:1;opacity:.55}.viz-dir,.viz-tick{fill:currentColor;font-size:11px}
.viz-dir{paint-order:stroke fill;stroke:#0d0c31;stroke-width:3px;stroke-linejoin:round}.viz-alt{color:var(--ink);fill:currentColor;font-size:11px;paint-order:stroke fill;stroke:#0d0c31;stroke-width:3px;stroke-linejoin:round}.viz-planet circle{fill:rgb(var(--accent-rgb))}.viz-planet text,.viz-moon text{color:#241a42;fill:currentColor;font-size:10px;font-weight:700}.viz-moon circle{fill:#f1edff}.viz-sun{fill:none;stroke:var(--ink);stroke-width:2}.viz-band{fill:rgba(255,255,255,.14)}.viz-bar{fill:rgb(var(--accent-rgb))}.viz-track{fill:rgba(255,255,255,.1)}.viz-tw1{fill:rgba(241,237,255,.55)}.viz-tw2{fill:rgba(241,237,255,.75)}.viz-tw3{fill:rgba(241,237,255,.9)}.viz-dark{fill:#f1edff}.viz-moonup{fill:rgb(var(--accent-rgb))}.viz-now-halo{stroke:#f1edff;stroke-width:5;stroke-linecap:round}
.viz-now{stroke:#0d0c31;stroke-width:2;stroke-linecap:round}.viz-nowhead{fill:var(--ink)}@media(max-width:720px){.viz-body{grid-template-columns:1fr}.viz-body .viz-svg{max-width:300px;margin:0 auto}}.data-tile p+.times-list{margin-top:12px}
.data-tile p{color:var(--muted);margin:0;font-size:1rem;line-height:1.5}
.data-note{display:block;color:var(--muted);font-size:1rem;margin-top:10px;line-height:1.4}
.times-list{list-style:none;margin:0;padding:0;display:grid;gap:12px}
.times-list li{display:grid;gap:2px;font-size:1rem}
.times-list strong{font-size:1rem}
.times-list span{color:var(--muted)}
@media(max-width:720px){.sky-data-row,.tonight-row{grid-template-columns:1fr}}
/* Marcus's follow-up decision, 2026-09-23: superseded the two-column #nightConditionsList idea above (batch31,
   1b6e87b) before it shipped -- the list now runs the card's full width instead, with the cloud strip moved
   below it, so it needs no 720px override of its own (repeat(auto-fill,...) already collapses to one column at
   any width narrow enough to need it).
   Marcus's option-1 decision, 2026-09-24 (see .sky-data-row above): above 1024px the list runs 3 columns
   instead of 2, shortening Night conditions' own height so the left column (Dark window + Night conditions)
   stays close to Planet times' height without either card stretching past its own content. A fixed
   repeat(2)/repeat(3) by viewport width, not repeat(auto-fill,...) by container width, because the 1024px
   line is Marcus's own -- container-width auto-fill would not land on that exact break. */
#nightConditionsCard .viz-body{display:flex;flex-direction:column;align-items:stretch;gap:16px}
#nightConditionsList{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:1025px){#nightConditionsList{grid-template-columns:repeat(3,minmax(0,1fr))}}
#nightConditionsCard .viz{width:100%}
.sky-fact span{display:block;color:var(--muted);font-size:1rem;margin-bottom:8px}
.sky-fact b{font-size:1rem}
@media(max-width:720px){.sky-grid{grid-template-columns:1fr}.sky-facts{grid-template-columns:repeat(2,1fr)}}
.sky-hero h2,.sky-score b{font-family:Orbitron,"Segoe UI",sans-serif}
.sky-hero h2{font-size:clamp(1.85rem,4.5vw,3.2rem);letter-spacing:-.04em}
.sky-score b{font-size:1.55rem}
.sky-score-layout{display:flex;justify-content:space-between;gap:20px;align-items:center}
.condition-visual{text-align:center;min-width:120px}
.condition-ring{--clarity:50%;width:90px;height:90px;border-radius:50%;display:grid;place-items:center;margin:auto;background:radial-gradient(circle at center,#1a1d50 57%,transparent 59%),conic-gradient(#d3adff var(--clarity),rgba(216,198,255,.16) 0);box-shadow:0 0 24px rgba(194,136,255,.18)}
.condition-ring span{font-family:Orbitron,"Segoe UI",sans-serif;font-size:1.05rem}
.condition-visual small{display:block;margin-top:8px;color:var(--muted);font-size:1rem}
.planet-list{display:grid;grid-template-columns:repeat(5,1fr);overflow:auto}
.planet{padding:18px;min-width:148px;border-right:1px solid var(--line)}
.planet:last-child{border:0}
.planet strong{font-family:Orbitron,"Segoe UI",sans-serif;font-size:1rem}
.planet b{display:block;font-size:1rem;margin:10px 0 4px}
.planet small{color:var(--muted);font-size:1rem}
@media(max-width:720px){.sky-grid{grid-template-columns:1fr}.sky-score-layout{align-items:flex-start}.condition-visual{min-width:95px}.condition-ring{width:76px;height:76px}}
.sky-score-layout{position:relative;z-index:1}
:where(.on-picture){position:relative}
.on-picture{isolation:isolate;paint-order:stroke fill;-webkit-text-stroke:3px rgba(0,0,0,.6);text-shadow:var(--ink-shadow)}
#skyView .tile-text,#skyView .sky-score-layout>div:first-child,#skyView .condition-visual>small,#skyView #visibleTonightCard>div,#skyView .iss-card>.on-picture{background:none;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0;padding:0}
.condition-ring{position:relative;overflow:hidden;isolation:isolate}
.condition-ring img{position:absolute;inset:11%;width:78%;height:78%;border-radius:50%;object-fit:cover;z-index:-1;filter:var(--picture-filter)}
.condition-ring::after{content:"";position:absolute;inset:11%;border-radius:50%;background:rgba(6,8,30,.68);z-index:0}
.condition-ring span{position:relative;z-index:1;text-shadow:0 1px 8px #08051d}
.sky-scene{min-height:clamp(170px,20vw,240px)}
#visibleTonightCard>div{display:inline-block;max-width:min(100%,560px);padding:14px 16px}
.tile-text,.sky-score-layout>div:first-child,.iss-card>.on-picture{background:rgba(6,8,30,var(--panel-alpha,.8));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:16px;padding:14px 16px}
.condition-visual>small{background:rgba(6,8,30,var(--panel-alpha,.8));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:10px;padding:3px 10px}
.tile-text{display:inline-block;max-width:min(100%,440px)}
.sky-score-layout>div:first-child{max-width:340px}
#visibleTonightCard>div{background:rgba(6,8,30,var(--panel-alpha,.8));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:16px}
.sky-status{margin:0 0 14px;padding:12px 16px;font-size:1rem;line-height:1.4}
/* Marcus, 2026-09-24 (screenshot, Port Orange FL): display:flex on the whole paragraph turned each bare text
   run between the two links ("Air quality: ", " (", "), rounded and sorted...") into its own anonymous flex
   item, which flex-wrap could wrap independently of the <a> beside it -- "(" landed on its own line, split
   from the CC BY 4.0 link. The paragraph is plain flowing text now (like every other credit line on the
   page, e.g. .allergen-credit); .cams-credit a keeps its own inline-flex + min-height:44px for the tap
   target (the same pattern .detail b a already uses in weather.css), which still flows inline with the
   surrounding text instead of breaking it into flex items. */
.cams-credit{margin:10px 0 0;font-size:1rem;line-height:1.45;color:var(--ink-soft)}.cams-credit a{display:inline-flex;align-items:center;min-height:44px;color:var(--link);text-decoration:underline}
