/* Only the forest game's page loads this stylesheet. */

/* ---- Trees ---------------------------------------------------------------
   Drawn in tools/forest_trees.py: four kinds at three ages. A tree on the
   page shows the drawing that matches its data-stage, so growing is a change
   of shape. The foot of every drawing is at 95% of its box; the box is placed
   by that point (forest-scene.js). No filters: a tree is a few flat shapes. */
.forest-kinds{position:absolute;width:0;height:0;overflow:hidden}
.forest-patch{display:none;position:absolute;z-index:3;width:130px;height:156px;transform:translate(-50%,-95%) scale(var(--tree-scale,1));transform-origin:50% 95%;transition:transform 1.2s cubic-bezier(.2,.8,.2,1),opacity .6s;pointer-events:none}
.forest-patch[data-forest-seeded]{animation:forest-sprout 1.3s cubic-bezier(.2,.8,.2,1) both}
@keyframes forest-sprout{from{opacity:0;transform:translate(-50%,-95%) scale(.15)}}
.is-playing .forest-patch{display:block}
.forest-plant{display:block;width:100%;height:100%;overflow:visible;stroke:none;transform-origin:50% 95%;animation:tree-sway var(--sway,5.6s) ease-in-out var(--sway-start,0s) infinite alternate}
.tree-age{display:none;transform-origin:50px 114px}
.forest-plant[data-stage="1"] .tree-age[data-age="1"],.forest-plant[data-stage="2"] .tree-age[data-age="2"],.forest-plant[data-stage="3"] .tree-age[data-age="3"]{display:inline;animation:tree-grow 1.15s cubic-bezier(.2,.9,.3,1) both}
/* The whole tree leans from its foot, top farthest, the way a trunk bends. */
@keyframes tree-sway{from{transform:rotate(-1.2deg) skewX(1.1deg)}to{transform:rotate(1.2deg) skewX(-1.1deg)}}
/* A new age comes up out of the old one's height, a little past, then settles. */
@keyframes tree-grow{from{transform:scale(.74,.5);opacity:.4}55%{transform:scale(1.03,1.07);opacity:1}to{transform:none}}
.forest-root{position:absolute;left:24%;right:24%;bottom:2%;height:7px;border-radius:50%;background:#07180fb8}
/* A tree being carried off is the same drawing, still. */
.cat-game-letter .forest-plant,.cat-game-letter .tree-age{animation:none!important}
.space-stage[data-game-state=paused] .forest-plant,.space-stage[data-game-state=over] .forest-plant{animation-play-state:paused}
@media(prefers-reduced-motion:reduce){.forest-patch{transition:none}.forest-patch[data-forest-seeded],.forest-plant,.forest-plant .tree-age{animation:none!important}}
@media(max-width:699px){.forest-patch{width:98px;height:118px}}
@media(max-width:699px) and (max-height:650px){.forest-patch{width:74px;height:89px}}
@media(min-width:700px) and (max-height:700px){.forest-patch{width:100px;height:120px}}
@media(min-width:700px) and (max-height:520px){.forest-patch{width:66px;height:79px}}

/* Without the rendered sky the planet is a flat strip of the same picture,
   placed so the Amazon (8 S, 62 W) lies under the tree row. */
.forest-fallback{display:none;pointer-events:none;position:absolute;z-index:2;left:-5%;right:-5%;top:430px;height:260px;border-radius:50% 50% 0 0;background:linear-gradient(#1a394455,#03131bed),url('assets/earth-nasa.jpg') calc(55vw - 1311px) -944px/4000px 2000px;box-shadow:0 -1px 18px #7dcac733}
.space-stage.is-playing[data-sky=fallback] .forest-fallback{display:block}
.forest-study-return{position:fixed;right:20px;bottom:16px;z-index:35;display:inline-flex;align-items:center;min-height:44px;padding:8px 14px;background:#101b27e8;border:1px solid #8facbb55;border-radius:999px;color:#bdcbd7;font:400 12px/1.4 Inter,system-ui,sans-serif;text-decoration:none}
@media(max-width:699px){.forest-study-return{font-size:11px;right:12px;bottom:10px}}

/* ---- The page becomes the game -------------------------------------------
   Starting a run: the name, the byline and the header step back, a frame
   closes round the play field and darkens what is outside it, the cat leaves
   its place for its orbit (cat-game.js moves it), and the planet rises inside
   the frame. Close game runs it backwards. Only opacity and transforms move;
   nothing is resized while it happens. The play field is the whole window,
   so the project list is below it and out of sight. */
.space-stage.is-playing{padding-top:max(100svh,var(--forest-play-height,0px))}
.arena-frame{position:fixed;z-index:6;left:8px;top:8px;width:calc(100vw - 16px);height:calc(100svh - 16px);box-sizing:border-box;pointer-events:none;visibility:hidden;opacity:0;transform:scale(1.07);border:2px solid #a9dfe2;border-radius:22px;box-shadow:0 0 0 var(--arena-mat,16px) #03070ec2,inset 0 0 0 1px #03070eb3;transition:opacity .3s ease,transform .3s ease,visibility 0s .3s}
.space-stage[data-arena] .arena-frame{visibility:visible;opacity:1;transform:none;transition:opacity .45s ease,transform .75s cubic-bezier(.2,.9,.25,1.14)}
/* Four corner pieces arrive last and lock the frame. */
.arena-frame i{position:absolute;width:30px;height:30px;border:3px solid var(--ink);opacity:0;transition:opacity .2s,transform .3s}
.arena-frame i:nth-child(1){left:-2px;top:-2px;border-right:0;border-bottom:0;border-radius:22px 0 0 0;transform:translate(-14px,-14px)}
.arena-frame i:nth-child(2){right:-2px;top:-2px;border-left:0;border-bottom:0;border-radius:0 22px 0 0;transform:translate(14px,-14px)}
.arena-frame i:nth-child(3){left:-2px;bottom:-2px;border-right:0;border-top:0;border-radius:0 0 0 22px;transform:translate(-14px,14px)}
.arena-frame i:nth-child(4){right:-2px;bottom:-2px;border-left:0;border-top:0;border-radius:0 0 22px 0;transform:translate(14px,14px)}
.space-stage[data-arena] .arena-frame i{opacity:1;transform:none;transition:opacity .3s .45s,transform .45s .45s cubic-bezier(.2,.9,.25,1.3)}
.space-stage .hero-copy{transition:opacity .45s ease,scale .5s ease,translate .5s ease}
.space-stage[data-arena] .hero-copy{opacity:0;scale:.9;translate:0 -22px}
.space-stage .navigation{transition:opacity .35s ease,top .3s ease}
.space-stage[data-arena] .navigation{opacity:0}
.space-stage[data-arena] .scene-sky-control{visibility:hidden}
html.game-held .projects-section{visibility:hidden}
/* The cat is moved by cat-game.js from where it rests to its orbit and back:
   one transform about its own centre. On the far side of the orbit it goes
   under the trees and is cut where the planet covers it. */
.space-stage[data-arena] .studio-cat{transform-origin:50% 50%}
.space-stage[data-arena] .studio-cat[data-tired=true] .pupil{fill:#b86a3c}
#game-fx{position:absolute;inset:0;z-index:23;pointer-events:none}
@media(prefers-reduced-motion:reduce){.arena-frame,.arena-frame i,.space-stage .hero-copy,.space-stage .navigation{transition:none!important}}

/* ---- Readout, messages and the two buttons --------------------------------
   One band along the top of the frame. The readout is ordinary type, large.
   Close game has the right-hand column to itself; Resume (and Start
   defending, if it is switched back on) comes and goes in the column to its
   left, so nothing ever slides under a finger. Tab order: the button to play
   first. */
.space-stage.is-playing .play-controls{position:absolute;z-index:24;left:calc(var(--arena-x,8px) + 16px);right:auto;top:calc(var(--arena-y,8px) + 10px);bottom:auto;width:calc(var(--arena-w,100vw - 16px) - 32px);max-width:none;min-height:var(--forest-controls-height,0px);display:grid;grid-template-columns:minmax(0,1fr) auto auto;column-gap:14px;row-gap:2px;align-items:start;align-content:start}
.space-stage.is-playing .forest-hud{grid-column:1;grid-row:1}
.space-stage.is-playing #forest-ready,.space-stage.is-playing #forest-resume{grid-column:2;grid-row:1;margin:0}
.space-stage.is-playing #play-stop{grid-column:3;grid-row:1;margin:0;font-size:14px}
.space-stage.is-playing .play-status{grid-column:1/-1;grid-row:2;max-width:46ch;font-size:14px;line-height:1.5}
.space-stage.is-playing .forest-clue{grid-column:1/-1;grid-row:3}
.forest-hud{margin:0;min-height:44px;display:flex;align-items:center;font:600 clamp(20px,2.3vw,28px)/1.2 Inter,system-ui,sans-serif;letter-spacing:-.015em;color:var(--ink);text-shadow:0 2px 8px #000d}
.forest-clue{margin:4px 0 0;max-width:46ch;font:italic 400 14px/1.5 Inter,system-ui,sans-serif;color:#c3d3bf;text-shadow:0 2px 6px #000;text-wrap:pretty}
@media(min-width:700px){.space-stage.is-playing .play-status,.space-stage.is-playing .forest-clue{max-width:72ch}}
/* A short window: the messages use the frame's width and smaller type, so the band stays shallow. */
@media(max-height:520px){.space-stage.is-playing .play-status,.space-stage.is-playing .forest-clue{max-width:none;font-size:13px;line-height:1.4}.forest-clue{margin-top:2px}.forest-hud{font-size:20px}}
.forest-ready{display:inline-flex;align-items:center;min-height:44px;padding:8px 16px;border:1px solid #b6d1b77a;border-radius:999px;background:#0b141ccc;color:var(--ink);font:500 14px/1.4 Inter,system-ui,sans-serif}
.forest-ready:hover{border-color:var(--teal);color:var(--ink);background:#1a2b2fcc}
.space-stage.is-playing:focus-visible .play-controls{outline:none}
/* While the game is closed: how the last run went, quietly, under the byline. */
.hero-copy .forest-last{margin:12px 0 0;font:400 14px/1.5 Inter,system-ui,sans-serif;letter-spacing:0;color:var(--dim);transition:opacity .2s}
.is-docking .forest-last{opacity:0}
/* On a phone the cat's ears are under the byline, so the line sits above the name, at the right. */
@media(max-width:699px){.hero-copy .forest-last{position:absolute;top:-40px;right:0;margin:0;white-space:nowrap}}
@media(max-width:359px){.space-stage .hero-copy p.forest-last{top:-48px;max-width:150px;white-space:normal;text-align:right;line-height:1.3}}

.forest-results{position:fixed;z-index:25;left:50%;top:var(--forest-results-centre,50%);transform:translate(-50%,-50%);width:min(330px,calc(100vw - 48px));max-height:calc(100svh - 150px);overflow:auto;overscroll-behavior:contain;padding:22px 24px 18px;border:1px solid #9bcb9452;border-radius:16px;background:#070e14eb;box-shadow:0 12px 40px #00000099;text-align:center;color:var(--ink)}
.forest-results h2{margin:0 0 10px;font:600 20px/1.3 Inter,system-ui,sans-serif;letter-spacing:-.01em}
.forest-results p{margin:0;font:400 14px/1.8 Inter,system-ui,sans-serif;color:#c4cdd8}
.forest-results button{display:inline-flex;align-items:center;justify-content:center;min-height:44px;margin-top:12px;padding:8px 20px;border:1px solid #b6d1b77a;border-radius:999px;background:#91b98416;color:var(--ink);font:500 14px/1.4 Inter,system-ui,sans-serif}
.forest-results button:hover{border-color:var(--teal);background:#91b98429}
@media(max-height:420px){.forest-results{max-height:calc(100svh - 76px);top:calc(50% + 30px);padding:12px 20px 10px}.forest-results p{line-height:1.5}.forest-results button{margin-top:6px}}

/* Staying in the game. From the first frame to Close game the page outside
   the play field is inert (cat-game.js); here it also stops answering a
   finger: no scroll, zoom, pull-to-refresh, text selection or long-press
   menu. A paused game holds the page as well, so Resume and Close game stay
   in view (HOLD_PAGE_WHEN_PAUSED in cat-game.js gives scrolling back). */
html.game-held{overscroll-behavior:none}
html.game-held .space-stage.is-playing{touch-action:none}
html.game-paused-scrolls .space-stage.is-playing[data-game-state=paused]{touch-action:auto}
html.game-held .space-stage.is-playing{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}
html.game-held .space-stage.is-playing .scene-controls{visibility:hidden}
.space-stage.is-playing[data-game-state=paused] #game-canvas{opacity:.55;touch-action:auto}
.space-stage.is-playing .scene-shade{background:none}
