:root { color-scheme:dark; font-family:Inter,ui-sans-serif,system-ui,sans-serif; color:#eef4ff; --glass:#141c4294; --edge:#ffffff73; --muted:#9aa6c4; --accent:#ffd9a0 }
* { box-sizing:border-box }
html,body { height:100%; margin:0; overflow:hidden; background:#04050d }
/* As the feed has it. An iPhone's installed app measures 100% short of the screen by its status
   bar, and the layers fixed to the window stop short with it; 100vh is the whole screen. */
html { height:100vh }
body { background:radial-gradient(120% 90% at 50% 45%,#141a3a 0%,#080a1a 55%,#03040a 100%) }
/* The sky sits behind everything. The plain backdrop would cover it, so it goes once the sky has loaded. */
#sky { position:fixed; z-index:-1; inset:0; width:100%; height:100%; pointer-events:none }
#sky[hidden] { display:none }
body.has-sky { background:none }
#space { position:fixed; inset:0; touch-action:none; cursor:grab }
/* Nothing in the scene is text to select: an iPhone takes tap and hold for choosing a word, and
   would lay its blue selection over the whole view (see TAP in go.js). */
#space,#sky,#horizon,#beacons,#orbs,#labels,#avatar { -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; -webkit-tap-highlight-color:transparent }
#space:active { cursor:grabbing }
#space.can-travel { cursor:pointer }

/* Spheres and their labels take no pointer events, so dragging anywhere still turns the view. */
#beacons,#orbs,#labels { position:fixed; inset:0 var(--scene-right,0px) 0 0; overflow:hidden; pointer-events:none }
.orb { --lum:1; --sat:1; position:absolute; left:0; top:0; width:120px; height:120px; border-radius:50%; overflow:hidden; transform-origin:50% 50%; will-change:transform;
  background:radial-gradient(circle at 32% 28%,hsl(var(--hue) calc(95% * var(--sat)) calc(86% * var(--lum))) 0%,hsl(var(--hue) calc(78% * var(--sat)) calc(58% * var(--lum))) 34%,hsl(var(--hue) calc(70% * var(--sat)) calc(26% * var(--lum))) 78%,hsl(var(--hue) calc(70% * var(--sat)) calc(12% * var(--lum))) 100%);
  box-shadow:0 0 22px hsl(var(--hue) 85% 60% / calc(.5 * var(--lum))); transition:opacity .2s }
/* Discovering (see go.js): until it is discovered a sphere is lit only faintly, enough to make
   it out, its picture and title dim with it; the light comes up with a flare as the chain
   reaches it. Known, it wears a gold ring; in a known cluster, a stronger glow of its own colour. */
body.is-discovering .orb:not([data-light]) { --lum:.5; --sat:.45 }
body.is-discovering .orb.has-image:not([data-light]) img { opacity:.3 }
body.is-discovering .orb-label:not([data-light]) { color:#dfe7ff80 }
:where(body.is-discovering) .orb[data-light="cluster"] { box-shadow:0 0 34px hsl(var(--hue) 95% 66% / .85) }
:where(body.is-discovering) .orb[data-light="known"] { box-shadow:0 0 0 calc(var(--ring,1px)*2) #ffd9a0,0 0 34px hsl(var(--hue) 95% 66% / .85) }
.orb.is-lighting { animation:ignite .9s ease-out }
@keyframes ignite { from { filter:brightness(2.6) saturate(1.4) } }
/* In front of the brain and covering it: see-through, so you can still tell where you are. */
.orb.is-veil { opacity:.3 }
.orb img { position:absolute; inset:0; width:100%; height:100%; border-radius:50%; object-fit:cover; opacity:0 }
.orb.has-image img { opacity:1 }
/* The same shading over an image, so it still reads as a ball. */
.orb.has-image::after { content:""; position:absolute; inset:0; border-radius:50%; background:radial-gradient(circle at 32% 28%,#ffffff55 0%,#ffffff00 30%,#00000000 55%,#000000aa 100%) }
/* Hover: a ring of the sphere's own colour. In focus (shown in the reading panel): a thin ring in the gold of
   the brain's, which sends a second one out from it twice, in time with the brain's own pulse.
   (`--ring` is one pixel on the screen, however the sphere is scaled.) */
.orb.is-hovered { box-shadow:0 0 0 4px hsl(var(--hue) 95% 80%),0 0 30px hsl(var(--hue) 90% 70% / .9) }
.orb.is-near { overflow:visible; box-shadow:0 0 0 calc(var(--ring,1px)*1.5) #ffe9c8e6,0 0 calc(var(--ring,1px)*18) #ffd9a066 }
/* The ring sent out is a ring of its own that only grows and fades, which the graphics card does
   by itself: nothing is painted again for it. It goes 9 pixels out and then 14 (`--out` is how
   much larger it is for each pixel). It lies outside the sphere, so the sphere no longer cuts off
   what is outside it while it is in focus; its picture is round by itself. */
.orb.is-near::before { content:""; position:absolute; inset:0; border-radius:50%; box-shadow:0 0 0 calc(var(--ring,1px)*1.5) #ffe9c8; opacity:0; will-change:transform,opacity; animation:beat 2.4s ease-out infinite }
@keyframes beat {
  0% { transform:scale(1); opacity:.85 }
  18% { transform:scale(calc(1 + var(--out,.02)*9)); opacity:0 }
  18.01% { transform:scale(1); opacity:.7 }
  42%,100% { transform:scale(calc(1 + var(--out,.02)*14)); opacity:0 }
}
/* Titles wrap to two centred lines; anything longer is cut with an ellipsis. */
.orb-label { position:absolute; left:0; top:0; max-width:150px; padding:1px 6px; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; overflow:hidden; text-align:center; text-wrap:balance; overflow-wrap:anywhere; font-size:12px; line-height:14px; color:#dfe7ffd0; text-shadow:0 1px 5px #000,0 0 2px #000 }
.orb-label.is-strong { color:#fff; font-weight:650 }
/* A beacon: its topics' names, one to a line, in its leading topic's colour, behind the
   spheres and on the cloud drawn for it. The names are set as the app sets its category pills. */
.beacon { position:absolute; left:0; top:0; display:grid; justify-items:center; gap:0; white-space:nowrap; transition:opacity .3s; will-change:transform,opacity;
  font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif; font-size:calc(12px*var(--grow,1)); font-weight:500; line-height:calc(15px*var(--grow,1)); text-transform:capitalize; color:hsl(var(--hue) 90% 88%); text-shadow:0 1px 6px #000,0 0 2px #000 }

/* The reading panel keeps its place whether or not an article is in reach. */
/* The reading panel has no surface of its own: it runs to the window's edges, over the sky.
   (Nothing of the scene is drawn there, so there is nothing for it to keep clear of.) */
#reader { position:fixed; z-index:2000001; top:0; right:0; bottom:0; width:min(456px,37vw); display:flex; background:none; overflow:hidden; text-shadow:0 1px 5px #000b }
#reader .reader-empty { margin:auto; padding:28px; text-align:center; color:var(--muted); font-size:14px; line-height:1.5 }
#reader .reader-empty strong { display:block; margin-bottom:6px; color:#eef4ff; font-size:16px }
#reader .reader-empty p { margin:0 }
/* The feed's expanded card, made to fill the panel instead of the feed column. */
#reader .card.reader-card { position:relative; inset:auto; display:flex; flex-direction:column; width:100%; height:100%; max-width:none; max-height:none; min-height:0; margin:0; padding:0; border:0; border-radius:0; box-shadow:none; background:none; transform:none; animation:none; transition:none; overflow:hidden; cursor:auto }
/* Lying over the scene (see PANEL_SQUEEZES), the panel has a scrim: dark under the text, and
   fading away to its left so that spheres dim as they pass behind it and are not cut off.
   The photo's left edge fades the same way. */
body.is-overlaid #reader { width:min(520px,41vw); background:linear-gradient(90deg,#0000 0,#0009 36px,#000000d9 84px,#000000f0 38%) }
/* Spheres and dust show dimly through the scrim; titles and beacons' names would only be words
   behind words, so those layers stop where the scrim begins to count. */
body.is-overlaid #beacons,body.is-overlaid #labels { right:max(0px,calc(var(--panel-right,0px) - 60px)) }
body.is-overlaid #reader .reader-content { padding-left:84px }
body.is-overlaid #reader .reader-pills { padding-left:78px }
body.is-overlaid #reader .reader-media::before,body.is-overlaid #reader .reader-media img {
  --fade:linear-gradient(to bottom,#000 0%,#000 var(--fade-from),rgba(0,0,0,.92) calc(var(--fade-from) + var(--fade-span) * .2),rgba(0,0,0,.48) calc(var(--fade-from) + var(--fade-span) * .55),transparent calc(var(--fade-from) + var(--fade-span)));
  -webkit-mask-image:var(--fade),linear-gradient(to right,transparent 0,#000 26%); -webkit-mask-composite:source-in;
  mask-image:var(--fade),linear-gradient(to right,transparent 0,#000 26%); mask-composite:intersect;
}
body.is-overlaid #reader .reader-media .title { padding-left:82px }
#reader .reader-media { position:relative; flex:none; height:clamp(190px,36vh,340px); display:flex; align-items:flex-end; justify-content:center; background:none }
/* The photo (or, without one, a wash of the topic's colour) fades away to nothing towards
   its foot, on the same curve as the feed's card photos, and the title sits over the fade. */
#reader .reader-media::before { content:""; position:absolute; inset:0; background:linear-gradient(160deg,hsl(var(--preview-hue) 60% 34%),hsl(var(--preview-hue) 55% 14%)) }
#reader .reader-media img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover }
#reader .reader-media::before,#reader .reader-media img {
  --fade-from:42%; --fade-span:54%;
  -webkit-mask-image:linear-gradient(to bottom,#000 0%,#000 var(--fade-from),rgba(0,0,0,.92) calc(var(--fade-from) + var(--fade-span) * .2),rgba(0,0,0,.48) calc(var(--fade-from) + var(--fade-span) * .55),transparent calc(var(--fade-from) + var(--fade-span)));
  mask-image:linear-gradient(to bottom,#000 0%,#000 var(--fade-from),rgba(0,0,0,.92) calc(var(--fade-from) + var(--fade-span) * .2),rgba(0,0,0,.48) calc(var(--fade-from) + var(--fade-span) * .55),transparent calc(var(--fade-from) + var(--fade-span)));
}
#reader .reader-media .title { position:relative; z-index:1; width:100%; max-width:100%; margin:0; padding:0 22px 12px; white-space:normal; overflow-wrap:anywhere; text-wrap:balance; text-align:center; font-size:26px; font-weight:650; line-height:1.15; color:#fff; text-shadow:0 2px 10px #000c }
#reader .reader-content { position:relative; flex:1; min-height:0; margin:0; padding:14px 24px 8px; overflow-y:auto; opacity:1; mask-image:none; -webkit-mask-image:none }
#reader .reader-content .meta { margin:0 0 12px; font-size:17px; color:#eef4ff }
#reader .reader-content .extract { display:block; opacity:1; font-size:15.5px; line-height:1.62; color:#e7ecfb; overflow:visible; max-height:none }
#reader .reader-content .extract p { margin:0 0 12px }
#reader .reader-heading { margin:20px 0 8px; font-size:13px; letter-spacing:.08em; text-transform:uppercase; color:var(--accent) }
#reader .reader-note { color:var(--muted); font-size:13px }
#reader .reader-pills { flex:none; display:flex; flex-wrap:wrap; gap:6px; justify-content:center; margin:0; padding:10px 18px 16px; opacity:1; position:static; max-height:84px; overflow:hidden }

/* In the app an article opens as the For You page's expanded card (see syncCard in go.js): the
   feed's own card and styles, in a layer over the map with the feed's margins round it, so the
   map shows past its edges. The layer takes no touch itself: the map round the card stays live.
   The feed's page is dark behind its cards, where here there is the map, so the card is given
   a ground of its own to be read on: dark glass, which blurs the map behind it. (It is the one
   blurred layer over the scene, and only while an article is up.) */
#card-layer { --card-margin:clamp(16px,3vw,32px); --card-glass:#070a1ac7; --card-blur:blur(22px) saturate(1.35); position:fixed; z-index:2000001; inset:0; display:flex; flex:none; justify-content:center; align-items:flex-start; padding:calc(var(--edge-top) + var(--card-margin)) calc(var(--edge-right) + var(--card-margin)) calc(var(--edge-bottom) + var(--card-margin)) calc(var(--edge-left) + var(--card-margin)); overflow:visible; pointer-events:none; touch-action:auto }
#card-layer > .card { max-width:680px; pointer-events:auto; background:var(--card-glass); -webkit-backdrop-filter:var(--card-blur); backdrop-filter:var(--card-blur) }
/* The keyboard overlays the map. Its comment card must fit above it, too. */
body.is-handheld #card-layer:has(.card-comment-list) { bottom:var(--keyboard,0px) }
body.is-handheld #card-layer .card:has(.card-comment-list) { --expanded-preview-spacer:0px !important }
body.is-handheld #card-layer .card-comment-input { min-width:0; font-size:16px }
/* The shape between a sphere and its card (see morph in js/infinity-card.js): the sphere's
   colour at the sphere, the card's glass at the card. One empty box, moved by the page. */
.infinity-card-morph { position:fixed; z-index:1; box-sizing:border-box; overflow:hidden; pointer-events:none; background:var(--card-glass); border:1px solid #ffffff8c; box-shadow:0 10px 40px #00000080,0 0 26px color-mix(in srgb,var(--morph-colour,#fff) 55%,transparent); will-change:left,top,width,height }
.infinity-card-morph-frame { position:absolute; left:0; top:0; width:100%; overflow:hidden; pointer-events:none }
.infinity-card-morph-picture { position:absolute; max-width:none; object-fit:cover; pointer-events:none }
/* The sphere's shading over its picture (as .orb.has-image::after), which goes as the shape leaves the sphere. */
.infinity-card-morph-shade { position:absolute; inset:0; border-radius:inherit; background:radial-gradient(circle at 32% 28%,#ffffff55 0%,#ffffff00 30%,#00000000 55%,#000000aa 100%) }
.infinity-card-morph-tint { position:absolute; inset:0; background:radial-gradient(circle at 34% 28%,color-mix(in srgb,var(--morph-colour,#fff) 62%,#fff) 0%,var(--morph-colour,#fff) 46%,color-mix(in srgb,var(--morph-colour,#fff) 62%,#000) 100%) }
/* Reading in the card: however many pages an article has, the page being read has a segment
   of the progress bar wide enough to watch its timer fill and turn green (on a long article
   the rest are a couple of pixels each). Once it has counted, Next turns green and says so. */
#card-layer .progress-bar.progress-segmented .progress-segment.current { min-width:28px }
#card-layer .card.card-expanded-active:has(.progress-segment.current.qualified) .expanded-card-hint-next { color:#4ade80 }
#card-layer .card.card-expanded-active:has(.progress-segment.current.qualified) .expanded-card-hint-next .expanded-card-hint-label::before { content:'✓ ' }
/* (At a desk the top row stays up, and the card begins under it.) */
body:not(.is-handheld) #card-layer { padding-top:76px }
body.has-card #reader { display:none }
/* The feed's layers are numbered for its own page. Here the map's spheres are stacked by depth
   far above those numbers, so what the card raises as it opens, what a swipe shows beside it
   and the XP that flies out of it are numbered from the card's layer up. */
:root { --z-orbs:2000001; --z-navbar:2000003; --z-celebration:2000012 }
/* XP flies into P's brain (see createXpQueue in js/infinity-card.js). The map places the brain
   with a transform every frame, so the feed's pulse, which is one too, is left to the picture inside. */
#avatar.brain-orb-knowledge-absorb { animation:none }
#avatar { position:absolute; left:0; top:0; width:54px; height:54px; display:grid; place-items:center; border-radius:50%; pointer-events:none; background:radial-gradient(circle,#ffd9a055 0%,#ffd9a014 55%,transparent 72%); box-shadow:0 0 0 2px #ffd9a0cc,0 0 22px #ffd9a088 }
#avatar[hidden] { display:none }
/* Its pulse is a brighter ring and glow laid over its own, which only fades in and out: the
   graphics card does that by itself, and nothing is painted again for it. */
#avatar::after { content:""; position:absolute; inset:0; border-radius:50%; box-shadow:0 0 0 2px #ffd9a0,0 0 30px #ffd9a0b3; opacity:0; will-change:opacity; animation:pulse 2.4s ease-in-out infinite }
@keyframes pulse { 50% { opacity:1 } }
#avatar img { width:34px; height:34px; filter:drop-shadow(0 1px 4px #000a) }
/* Another orb on the map: the same brain in a ring of its own colour, and a white ring while P follows it. */
.peer { position:absolute; left:0; top:0; width:54px; height:54px; display:grid; place-items:center; border-radius:50%; pointer-events:none; will-change:transform; background:radial-gradient(circle,hsl(var(--hue) 90% 80% / .33) 0%,hsl(var(--hue) 90% 80% / .08) 55%,transparent 72%); box-shadow:0 0 0 2px hsl(var(--hue) 90% 76% / .85),0 0 22px hsl(var(--hue) 90% 76% / .5) }
.peer[hidden] { display:none }
.peer.is-followed { box-shadow:0 0 0 2px hsl(var(--hue) 90% 76%),0 0 0 5px #fff,0 0 26px #fffc }
.peer img { width:34px; height:34px; filter:drop-shadow(0 1px 4px #000a) }
#compass .reading[hidden] { display:none }
/* A signed-in orb's name, under it: white, glowing in the colour of its ring. This page's own glows as its own ring does. */
.peer-name { position:absolute; left:0; top:0; max-width:160px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12px; font-weight:700; line-height:15px; color:#fff; text-shadow:0 0 9px hsl(var(--hue) 95% 62%),0 0 4px hsl(var(--hue) 95% 62%),0 1px 3px #000d }
.peer-name.is-mine { text-shadow:0 0 9px #ffd9a0,0 0 4px #ffd9a0,0 1px 3px #000d }
/* A name its owner typed, with no account behind it. */
.peer-name.is-guest { font-style:italic; font-weight:600 }
.peer-name[hidden],.bubble[hidden] { display:none }
/* What an orb has just said, over it. */
.bubble { position:absolute; left:0; top:0; z-index:1; width:max-content; max-width:min(240px,70vw); padding:6px 11px; border-radius:14px; background:#fffffff2; color:#0a0f22; font-size:13px; font-weight:600; line-height:1.3; overflow-wrap:anywhere; box-shadow:0 6px 20px #0008 }

/* An orb that has been tapped: a white ring, and beside it a menu of what may be done with it. */
.peer.is-chosen { box-shadow:0 0 0 2px hsl(var(--hue) 90% 76%),0 0 0 4px #ffffffd9,0 0 24px #fff9 }
/* A tour's guide (see Tours in go.js): its portrait in a ring of its subject's colour, with a thin
   gold ring outside it and a notch at the top, which no reader's orb has. The inner ring breathes
   while it talks. */
.peer.is-guide { background:radial-gradient(circle,hsl(var(--hue) 90% 80% / .3) 0%,transparent 72%); box-shadow:0 0 0 2px hsl(var(--hue) 90% 70%),0 0 0 4px #0a0f2299,0 0 0 5.5px #ffd9a0,0 0 22px hsl(var(--hue) 90% 70% / .55) }
.peer.is-guide img { width:40px; height:40px; border-radius:50%; object-fit:cover; object-position:50% 30%; filter:none; box-shadow:0 1px 6px #000a }
.peer.is-guide.is-followed { box-shadow:0 0 0 2px hsl(var(--hue) 90% 70%),0 0 0 4px #0a0f2299,0 0 0 5.5px #ffd9a0,0 0 0 8px #fff,0 0 26px #fffc }
.peer.is-guide.is-chosen { box-shadow:0 0 0 2px hsl(var(--hue) 90% 70%),0 0 0 4px #0a0f2299,0 0 0 5.5px #ffd9a0,0 0 0 8px #ffffffd9,0 0 24px #fff9 }
.guide-notch { position:absolute; left:50%; top:-9px; width:8px; height:8px; margin-left:-4px; background:#ffd9a0; clip-path:polygon(50% 0,100% 100%,0 100%) }
.peer.is-guide.is-talking { animation:guide-talks 1s ease-in-out infinite }
@keyframes guide-talks { 50% { box-shadow:0 0 0 3px hsl(var(--hue) 95% 82%),0 0 0 4px #0a0f2299,0 0 0 5.5px #ffd9a0,0 0 34px hsl(var(--hue) 95% 75% / .8) } }
.peer-name.is-guide { color:#ffd9a0 }
.bubble.is-guide { background:#fff8eaf2 }
/* A line from the article's summary wears the summary's mark, as the card's button does. */
.from-summary { display:inline-grid; vertical-align:-2px; margin-right:5px }
.from-summary svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round }
.bubble .from-summary { color:#7c3aed }
#talk-log .from-summary { color:#c4b5fd }
#talk-log li.is-guide { font-style:italic }
#peer-menu .guide-tagline { font-style:italic }
#peer-menu button.guide-tour { display:grid; gap:1px; padding:7px 14px; text-align:left; border-radius:14px }
#peer-menu button.guide-tour small { padding:0; font-weight:600 }
@media (hover:hover) { #peer-menu button.guide-tour:hover { background:#ffffff3a } }
@media (prefers-reduced-motion:reduce) { .peer.is-guide.is-talking,.tracker.is-tours.is-away .tracker-dot { animation:none } }
#peer-menu,.request { background:#101736f2; box-shadow:0 10px 30px #0008; color:#fff; font-size:13px; line-height:1.3 }
#peer-menu { z-index:2000002; position:fixed; left:0; top:0; display:grid; gap:7px; width:max-content; min-width:132px; max-width:210px; padding:10px; border-radius:16px }
#peer-menu[hidden],#requests[hidden] { display:none }
#peer-menu b { padding:0 4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px }
#peer-menu small { padding:0 4px; color:#ffffffb3; font-size:12px }
#peer-menu button,.request button { min-height:0; margin:0; padding:8px 14px; border:0; border-radius:999px; background:#ffffff24; color:#fff; font:inherit; font-weight:700; cursor:pointer }
#peer-menu button.is-main,.request button.is-main { background:#fff; color:#0a0f22 }
#peer-menu button:disabled { background:none; color:#ffffff8c; cursor:default }
#peer-menu button:focus-visible,.request button:focus-visible { outline:2px solid #fff; outline-offset:2px }
/* Readers who have asked to be friends: a card each, at the top of the scene, until answered. */
#requests { z-index:2000003; position:fixed; top:calc(var(--banner) + env(safe-area-inset-top,0px) + 76px); left:calc(50% - var(--panel-right,0px) / 2); transform:translateX(-50%); display:grid; gap:8px; width:min(360px,calc(100vw - var(--panel-right,0px) - 24px)); margin:0; padding:0; list-style:none }
.request { display:grid; grid-template-columns:30px 1fr auto auto; gap:8px; align-items:center; padding:9px 10px; border-radius:18px; animation:arrive .2s ease-out }
.request .face { grid-row:auto }
.request p { min-width:0; margin:0; overflow-wrap:anywhere }

/* Down the right, under the names of the part of the map (as far below them as they are below the
   top row), the friends on the map; down the left, at the head of the column, an article from
   each feed (see trackers in go.js). Folded, each is a pill only as wide as what it says;
   opened, a card. */
/* (The columns scroll, so each keeps room inside for a tracker's ring and glow, and is moved back by as much.) */
#trackers { z-index:2000001; position:fixed; top:calc(var(--banner) + 112px); right:calc(var(--panel-right,0px) + 16px); max-height:calc(100vh - var(--banner) - 292px + 24px); margin:-12px; padding:12px; display:flex; flex-direction:column; align-items:flex-end; gap:8px; overflow-y:auto; scrollbar-width:none; pointer-events:none }
#trackers > *,#feeds > * { pointer-events:auto }
#feeds { order:-1; display:flex; flex-direction:column; align-items:flex-start; gap:8px }
#feeds:empty { display:none }
.tracker { flex:none; width:max-content; max-width:240px; display:flex; flex-direction:column; padding:4px; border-radius:22px; overflow:hidden }
.tracker.is-open { width:240px; border-radius:18px }
.tracker[hidden],#friends-list[hidden],#friend-add[hidden],#friend-add-ways[hidden],#friend-invite-url[hidden],.tracker-body[hidden] { display:none }
:is(#trackers,#feeds) button { min-height:0; margin:0; border:0; background:none; color:#fff; font:inherit; cursor:pointer }
:is(#trackers,#feeds) .tracker-head { display:flex; align-items:center; gap:8px; min-width:0; padding:3px 10px 3px 3px; border-radius:999px; font-size:13px; font-weight:700; line-height:1.25; text-align:left }
.tracker-head::after { content:'›'; flex:none; margin-left:auto; font-size:17px; line-height:1; color:#ffffffa6; transition:transform .15s }
.tracker-head[aria-expanded="true"]::after { transform:rotate(90deg) }
@media (hover:hover) { :is(#trackers,#feeds) .tracker-head:hover { background:#ffffff1a } #feeds .tracker.is-open .tracker-title:hover { text-decoration:underline } }
:is(#trackers,#feeds) button:focus-visible { outline:2px solid #fff; outline-offset:-2px }
/* Its picture, or its sphere's colour shaded as its sphere is; ringed in the colour of its feed. */
.tracker-dot { flex:none; position:relative; width:26px; height:26px; display:grid; place-items:center; border-radius:50%; overflow:hidden; box-shadow:0 0 0 2px var(--feed,#ffffff59);
  background:radial-gradient(circle at 32% 28%,hsl(var(--hue,220) 95% 86%) 0%,hsl(var(--hue,220) 78% 58%) 34%,hsl(var(--hue,220) 70% 26%) 78%,hsl(var(--hue,220) 70% 12%) 100%) }
.tracker-dot img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover }
.tracker-dot.is-friends { background:#ffffff1f }
.tracker-dot svg { width:17px; height:17px; fill:none; stroke:#fff; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round }
/* The feed's own colours for its modes (see [data-feed-mode] in the app's styles). */
.is-for-you,.orb[data-tracked="for-you"] { --feed:#4ade80 }
.is-news,.orb[data-tracked="news"] { --feed:#ff8a1a }
.is-popular,.orb[data-tracked="popular"] { --feed:#60a5fa }
/* Tours (see Tours in go.js): gold, with the guide's portrait in the dot on a tour, and the dot
   pulsing while the guide waits for P to come back. */
.is-tours { --feed:#ffd9a0 }
.tracker.is-tours .tracker-dot { background:radial-gradient(circle at 32% 28%,#fff3dc 0%,#ffd9a0 40%,#9a6a2a 100%) }
.tracker.is-tours.is-away .tracker-dot { animation:sought 2.4s ease-in-out infinite }
.tracker-words { min-width:0; display:grid }
.tracker-kind { display:none; font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--feed) }
.tracker.is-open .tracker-kind { display:block }
.tracker.is-reached .tracker-kind::after { content:' · found'; color:#fff }
.tracker-title { max-width:180px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.tracker.is-open .tracker-title { cursor:pointer; max-width:none; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; white-space:normal; overflow-wrap:anywhere }
.tracker-body { display:grid; gap:8px; padding:4px 6px 6px }
.tracker-where { display:flex; align-items:center; gap:5px; padding-left:2px; font:600 12px/1 ui-monospace,SFMono-Regular,Menlo,monospace; color:#ffffffb3 }
.tracker-where canvas { flex:none; width:22px; height:22px; margin:-3px 0 -3px -4px }
.tracker-where em { font-style:normal; color:#fff }
.tracker-eta { font-family:Inter,ui-sans-serif,system-ui,sans-serif; font-weight:600 }
.tracker-actions { display:grid; grid-template-columns:repeat(3,1fr); gap:6px }
#feeds .tracker-actions button { padding:7px 0; border-radius:999px; background:#ffffff24; font-size:12px; font-weight:700; line-height:1 }
@media (hover:hover) { #feeds .tracker-actions button:hover { background:#ffffff40 } }
#feeds .tracker-actions button:disabled { opacity:.6; cursor:default }
/* Fetching the next: what is showing dims until it comes. */
.tracker.is-fetching :is(.tracker-dot,.tracker-words,.tracker-where) { opacity:.45; transition:opacity .2s }
#feeds .tracker-actions button.is-main { background:#fff; color:#0a0f22 }
/* Near enough to look out for: the pill is ringed in its feed's colour, and its picture glows
   in time with the brain. Its sphere wears a ring of the same colour while it is tracked. */
.tracker.is-near { box-shadow:0 0 0 2px var(--feed),0 10px 30px #0006 }
.tracker.is-near .tracker-dot { animation:sought 2.4s ease-in-out infinite }
@keyframes sought { 50% { box-shadow:0 0 0 2px var(--feed),0 0 14px var(--feed) } }
.orb[data-tracked] { outline:calc(var(--ring,1px)*2) dashed var(--feed); outline-offset:calc(var(--ring,1px)*6) }
/* The friends are one of them: their count beside the name, and each friend a row of the card. */
#friends-count { padding:1px 7px; border-radius:999px; background:#ffffff24; font-size:11px }
/* With no friends on the map, no count, and the card only as wide as its words until the ways to ask are open. */
#friends.is-empty #friends-count { display:none }
#friends.is-open.is-empty:has(#friend-add-ways[hidden]) { width:max-content }
#friends.is-empty #friend-add-open { grid-template-columns:26px 1fr; padding:4px 10px 4px 3px }
#friends.is-empty .face.is-add { width:26px; height:26px; font-size:16px }
#friends-list { margin:0; padding:0; list-style:none; overflow-y:auto; scrollbar-width:none }
#friends :is(.friend,#friend-add-open) { width:100%; display:grid; grid-template-columns:30px 1fr; grid-template-rows:auto auto; column-gap:9px; align-items:center; padding:6px 8px; border-radius:12px; text-align:left }
#friends :is(.friend,#friend-add-open):hover { background:#ffffff1f }
#friends :is(.friend,#friend-add-open) b { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px }
#friends .friend small { display:flex; align-items:center; gap:5px; font:600 12px/1 ui-monospace,SFMono-Regular,Menlo,monospace; color:#ffffffb3 }
#friends .friend small canvas { flex:none; width:22px; height:22px; margin:-3px 0 -3px -4px }
#friends .friend small em { font-style:normal }
/* The last friend is the way to ask for another: a (+), with no way to it or distance. */
#friends #friend-add-open { grid-template-rows:auto }
#friend-add-open b { color:#ffffffc7 }
.face.is-add { grid-row:auto; background:none; box-shadow:inset 0 0 0 1.5px #ffffff8c; font-size:18px; font-weight:500 }
#friend-add-ways { display:grid; gap:6px; padding:2px 6px 6px }
#trackers #friend-invite { padding:8px 12px; border-radius:999px; background:#fff; color:#0a0f22; font-size:12px; font-weight:700 }
#trackers #friend-invite:disabled { opacity:.5; cursor:default }
#friend-invite-url { width:100%; height:30px; margin:0; padding:0 10px; border:0; outline:0; border-radius:10px; background:#ffffff1a; color:#fff; font:600 11.5px ui-monospace,SFMono-Regular,Menlo,monospace; box-shadow:none }
#friend-add-form { display:flex; gap:6px }
#friend-add-email { flex:1; min-width:0; height:30px; margin:0; padding:0 10px; border:0; outline:0; border-radius:10px; background:#ffffff1a; color:#fff; font:inherit; font-size:12.5px; font-weight:600; box-shadow:none }
#friend-add-email::placeholder { color:#ffffffa6; font-weight:500 }
#friend-add-email:focus { background:#ffffff33 }
#trackers #friend-add-form button { flex:none; padding:0 12px; border-radius:999px; background:#ffffff24; color:#fff; font-size:12px; font-weight:700 }
#trackers #friend-add-form button:disabled { opacity:.5; cursor:default }

/* What the reader is asked to do: a line just over the chat bar, laid out the same whatever it
   holds (see render in objectives.mjs): its badge, its words (on a second line if they need it),
   and at the end a first step's XP and, once it has gone undone a while, "Hint". The badge is
   how far the goal has got: an outline, filled from the left as it gets on, full when it is done.
   Tapped, "Hint" opens the hint over the line, in a bubble that moves nothing. (The line has no
   backing: its words are shadowed to stand out from the scene.) */
@property --progress { syntax:'<number>'; inherits:true; initial-value:0 }
#objective { --progress:0; order:1; position:relative; display:flex; align-items:flex-start; transition:--progress .45s ease-out }
#objective[hidden] { display:none }
@keyframes rise { from { opacity:0; transform:translateY(6px) } }
.objective-line { flex:1; display:grid; grid-template-columns:auto minmax(0,1fr) auto auto; align-items:start; max-width:100%; margin:0; padding:1px 3px; border-radius:14px; font-size:14px; font-weight:650; line-height:20px; color:#fff; text-shadow:0 1px 5px #000,0 0 2px #000; pointer-events:auto; cursor:pointer }
#objective.is-new .objective-line { animation:rise .4s ease-out }
#objective button { min-height:0; margin:0; border:0; background:none; color:inherit; font:inherit; text-shadow:inherit; cursor:pointer }
/* The badge: a green outline, and green words, filled from the left in green, with its words
   white over the fill. (The fill is the outer box, the words the inner.) */
#objective-badge-fill { margin:3px 0 0 3px; border-radius:6px; background:linear-gradient(90deg,#16a34a calc(var(--progress) * 100%),#0a0b0d99 0); box-shadow:inset 0 0 0 1.5px #22c55e; text-shadow:none; white-space:nowrap }
#objective-badge { display:block; padding:2px 7px; font-size:12px; font-weight:750; line-height:16px; background:linear-gradient(90deg,#fff calc(var(--progress) * 100%),#4ade80 0); -webkit-background-clip:text; background-clip:text; color:transparent }
#objective-text { min-width:0; padding:3px 2px 3px 8px; text-align:left; overflow-wrap:anywhere }
#objective-xp { padding:3px 0 3px 10px; font-size:12px; font-weight:750; color:#4ade80; white-space:nowrap }
#objective-xp[hidden] { display:none }
/* (Its room is kept from the start, so that nothing moves when it comes.) */
#objective #objective-hint { margin:3px 0 0 8px; padding:1px 8px; border-radius:8px; background:#ffffff1f; font-size:12px; font-weight:700; line-height:18px; text-shadow:none; transition:opacity .6s,visibility .6s }
#objective #objective-hint[hidden] { display:none }
#objective #objective-hint.is-waiting { opacity:0; visibility:hidden }
#objective #objective-hint[aria-expanded="true"] { background:#fff; color:#0a0f22 }
/* The hint, over the line, its tail at "Hint". */
#objective-tip { position:absolute; left:0; right:0; bottom:calc(100% + 10px); margin:0; padding:9px 12px; border-radius:12px; background:#242830eb; box-shadow:0 8px 24px #0009; font-size:13px; font-weight:500; line-height:18px; color:#f8fafce6; pointer-events:auto; animation:rise .25s ease-out }
#objective-tip::after { content:''; position:absolute; top:100%; right:20px; border:7px solid transparent; border-top-color:#242830eb }
#objective-tip[hidden] { display:none }
/* What an open hint speaks of, pointed out with a ring that keeps going out from it. */
.is-pointed { animation:pointed 1.6s ease-out infinite }
@keyframes pointed { from { box-shadow:0 0 0 0 #4ade80b3 } to { box-shadow:0 0 0 12px #4ade8000 } }
/* What a first step brings (a feed's tracker, the friends) arriving: an orb of its colour that
   flies in from the goal and bursts (see fanfare in go.js), and a glow round it for a while. */
.arrival { z-index:2000005; position:fixed; left:-18px; top:-18px; width:36px; height:36px; border-radius:50%; pointer-events:none; background:radial-gradient(circle at 35% 35%,#fff 0 12%,var(--arrive) 45%,transparent 72%); box-shadow:0 0 26px 10px var(--arrive) }
.is-arrived { animation:arrived 1.5s ease-in-out 1.2s 2 }
@keyframes arrived { 50% { box-shadow:0 0 0 2px var(--arrive),0 0 22px var(--arrive) } }
.face { grid-row:1 / 3; position:relative; width:30px; height:30px; display:grid; place-items:center; border-radius:50%; overflow:hidden; background:hsl(var(--hue) 55% 38%); box-shadow:0 0 0 2px hsl(var(--hue) 90% 76% / .85); color:#fff; font-size:14px; font-weight:700 }
.face img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover }

/* The foot of the scene: from the top, what has been said nearby, the goal, and the chat bar.
   (The chat is laid out as part of the foot, so that the goal goes between what is said and
   the bar.) Lines go after a while; they are all there again while the bar is typed in. */
#foot { z-index:2000001; position:fixed; left:calc(50% - var(--panel-right,0px) / 2); bottom:16px; transform:translateX(-50%); width:min(420px,calc(100vw - var(--panel-right,0px) - 340px)); display:flex; flex-direction:column; gap:8px; pointer-events:none }
#talk { display:contents }
#talk[hidden] { display:none }
#say { order:2 }
#talk-log { order:0; margin:0; padding:0 14px; list-style:none; max-height:132px; overflow-y:auto; scrollbar-width:none; font-size:13px; line-height:1.35; color:#fff; text-shadow:0 1px 4px #000,0 0 2px #000 }
#talk-log li { padding:1px 0; overflow-wrap:anywhere }
#talk-log li.is-old { display:none }
#talk:focus-within #talk-log { max-height:40vh; pointer-events:auto }
#talk:focus-within #talk-log li.is-old { display:list-item; opacity:.7 }
#talk-log b { color:hsl(var(--hue) 95% 78%) }
#talk-log li.is-mine b { color:#ffd9a0 }
#say { display:flex; align-items:center; height:44px; padding:0 6px 0 18px; border-radius:999px; pointer-events:auto }
#say:focus-within { box-shadow:0 0 0 2px #ffffffcc,0 10px 30px #0006 }
/* Told across the top to a reader who has not signed in. Everything that hangs from the top of
   the page hangs from under it: --banner is how tall it stands (set by showMe). */
#guest-note { z-index:2000002; position:fixed; top:0; left:0; right:var(--panel-right,0px); margin:0; padding:calc(env(safe-area-inset-top,0px) + 7px) 16px 7px; background:#0c1230eb; color:#fff; font-size:13px; line-height:1.35; text-align:center }
#guest-note[hidden] { display:none }
body { --banner:0px; --edge-top:calc(env(safe-area-inset-top,0px) + var(--banner)) }
body.is-handheld.is-reading { --banner:0px !important }
/* (At the top of the options: who you are, with Log out beside it as quiet red words.) */
#account-group:has(#account[hidden]) { display:none }
#account { justify-content:flex-start }
#dev-group:has(#objectives-option[hidden]) { display:none }
#account-avatar { flex:none; display:grid; place-items:center; width:36px; height:36px; border-radius:50%; background:#4ade80; color:#0a0f22; font-size:15px; font-weight:800 }
#account-avatar:empty { display:none }
#account-name { flex:1; min-width:0; font-size:14px; font-weight:700; overflow-wrap:anywhere }
#below #sign-out { flex:none; padding:6px 0; background:none; color:#f87171; font-size:13px; font-weight:700 }
#below #sign-out:hover { color:#fca5a5 }
#sign-in { flex-basis:100%; display:grid; gap:6px }
#sign-in[hidden] { display:none }
#sign-in input { width:100%; height:34px; margin:0; padding:0 12px; border:0; outline:0; border-radius:10px; background:#ffffff1a; color:#fff; font:inherit; font-size:13px; font-weight:600; box-shadow:none }
#sign-in input::placeholder { color:#ffffffa6; font-weight:500 }
#sign-in input:focus { background:#ffffff33 }
#below #sign-in button { height:34px; border-radius:999px; background:#fff; color:#0a0f22; font-size:13px; font-weight:700 }
#below #sign-in button:disabled { opacity:.5; cursor:default }
#sign-in-more { display:flex; align-items:center; justify-content:center; gap:10px; margin:2px 0 0; font-size:12px; font-weight:700 }
#below #sign-in #sign-in-google { display:grid; place-items:center; width:34px; height:34px; padding:0; border-radius:50% }
#sign-in-google svg { width:18px; height:18px }
#sign-up { padding-left:10px; border-left:1px solid #ffffff40; color:#fff; text-decoration:none; line-height:20px }
#sign-up:hover { text-decoration:underline }
#say[hidden] { display:none }
#sign-in-note:not([hidden]) { color:#ffd9a0 }
#guest-note a { color:#ffd9a0; font-weight:700; text-decoration:underline }
/* Asking a guest for a name: the bar is ringed until one is given. */
#say.is-asking:not(:focus-within) { box-shadow:0 0 0 2px #ffd9a0cc,0 10px 30px #0006 }
#say input { flex:1; min-width:0; padding:8px 4px; border:0; outline:0; background:transparent; color:#fff; font:inherit; font-size:14px; font-weight:600; box-shadow:none }
#say input::placeholder { color:#ffffffa6; font-weight:500 }
#say button { min-height:0; margin:0; border:0; cursor:pointer }
#say:has(input:disabled) button { opacity:.35; cursor:default }

/* Controls laid over the scene share one look: strong white on blurred glass, with no tint and
   no edge drawn round it. (The blur is redone every frame the scene moves behind it, so these stay small.) */
.glass,.region-bar span { border:0; background:none; color:#fff }
/* (Blurring the scene behind them is costly, a phone's most of all: only when the Glass blur option is on, as it is to begin with on a desktop. See setBlurring in go.js.) */
body.is-blurring :is(.glass,.region-bar span) { -webkit-backdrop-filter:blur(18px) saturate(1.5); backdrop-filter:blur(18px) saturate(1.5) }
#hud button,#below button { min-height:0; margin:0; border:0; font:inherit; color:#fff; cursor:pointer }
#hud [hidden],#below [hidden] { display:none }

/* The top row spans the scene, left of the reading panel: options at one end, the axes at the
   other, and the two searches and the view's angles spaced evenly between, at their own widths. */
#hud { z-index:2000002; position:fixed; top:calc(var(--banner) + 16px); left:16px; right:calc(var(--panel-right,0px) + 16px); display:flex; gap:10px; justify-content:space-between; align-items:flex-start; pointer-events:none }
#hud > * { pointer-events:auto }
/* (Round and faintly lit, as the buttons down the edge of a phone are: see .pad.) */
#hud #menu { flex:none; display:grid; place-items:center; width:44px; height:44px; padding:0; border-radius:50%; background:#ffffff14 }
/* Back to the app's feed, before the menu (not on the viewer's copy, nor in the director). */
#hud #home { flex:none; display:grid; place-items:center; width:44px; height:44px; border-radius:50%; background:#ffffff14 }
#hud #home svg { width:22px; height:22px; fill:none; stroke:#fff; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round }
@media (hover:hover) { #hud #home:hover { background:#ffffff2e } }
#hud #home:focus-visible { outline:2px solid #fff; outline-offset:2px }
@media (hover:hover) { #hud #menu:hover { background:#ffffff2e } }
#hud #menu[aria-expanded="true"] { background:#fff }
#hud #menu[aria-expanded="true"] svg { stroke:#0a0f22 }

/* Search for an article. */
#go,#coordinates,#compass { display:flex; align-items:center; height:44px; border-radius:999px }
/* (The search has the room the readings of heading, tilt and zoom had: they are kept up, unseen.) */
#go { position:relative; flex:0 1 560px; min-width:120px; margin-right:auto; padding:0 6px 0 18px }
#hud #compass { display:none }
#go:focus-within,#coordinates:focus-within { box-shadow:0 0 0 2px #ffffffcc,0 10px 30px #0006 }
#go input { flex:1; min-width:0; width:auto; text-overflow:ellipsis; padding:8px 4px; border:0; outline:0; background:transparent; color:#fff; font:inherit; font-size:14px; font-weight:600; box-shadow:none }
#go input::placeholder { color:#ffffffa6; font-weight:500 }
#go input::-webkit-search-cancel-button { filter:invert(1) }
/* The arrow that sends a bar off, drawn the same wherever there is one. */
#hud form > button,#say button { flex:none; display:grid; place-items:center; width:32px; height:32px; padding:0; border-radius:50%; background:#fff }
:is(#hud form,#say) > button svg { width:18px; height:18px; fill:none; stroke:#0a0f22; stroke-width:2.6; stroke-linecap:round; stroke-linejoin:round; pointer-events:none }
#hud form > button:hover { background:#ffffffd9 }
/* One rule for every button: faint glass at rest, white once it is on or there is something for
   it to do. So a bar's arrow is glass while the bar is empty, and white once something is written. */
:is(#go,#say):has(input:placeholder-shown) > button { background:#ffffff14 }
:is(#go,#say):has(input:placeholder-shown) > button svg { stroke:#fff }
@media (hover:hover) { :is(#go,#say):has(input:placeholder-shown) > button:hover { background:#ffffff2e } }
#go.miss,#coordinates.miss { animation:shake .28s }
@keyframes shake { 25% { transform:translateX(-5px) } 75% { transform:translateX(5px) } }
#suggestions { position:absolute; top:calc(100% + 8px); left:0; right:0; margin:0; padding:6px; list-style:none; border-radius:18px; background:#101736e6 }
#suggestions li { padding:8px 12px; border-radius:12px; font-size:13px; font-weight:600; color:#fff; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; cursor:pointer }
#suggestions li[aria-selected="true"],#suggestions li:hover { background:#ffffff26 }

/* Where you are, a box for each axis: the numbers showing are P's own until one is typed over. */
#coordinates { flex:none; gap:6px; padding:0 6px 0 16px }
#coordinates label,#compass .reading { display:flex; align-items:center; gap:1px; font-size:12px; font-weight:700; color:#ffffff8c }
#coordinates input { width:54px; height:30px; margin:0; padding:0 5px; border:0; outline:0; border-radius:9px; background:transparent; color:#fff; font:600 13px ui-monospace,SFMono-Regular,Menlo,monospace; text-align:left; box-shadow:none }
#coordinates input::placeholder { color:#fff }
#coordinates input:focus { background:#ffffff24 }
#coordinates input:focus::placeholder { color:#ffffff73 }
#coordinates > button { margin-left:0 }

/* Which way you are facing, set out as the coordinates are, each value hard against its letter. */
#compass { flex:none; gap:6px; padding:0 11px 0 16px; pointer-events:none }
#compass output { padding:0 5px; color:#fff; font:600 13px ui-monospace,SFMono-Regular,Menlo,monospace }
#theta,#phi { min-width:calc(4ch + 10px) }
#zoom { min-width:calc(5ch + 10px) }
/* The world's axes as the camera sees them, on their own in the corner. */
#compass-axes { flex:none; width:56px; height:56px; pointer-events:none }

/* The frame rate, when it is asked for (the Frame rate option): small, under the last thing in
   the top row. (Plain letters, not the controls' glass: it is not to slow what it measures.) */
#fps { z-index:2000001; position:fixed; top:calc(var(--banner) + 78px); right:calc(var(--panel-right,0px) + 16px); font:600 11px/1 ui-monospace,SFMono-Regular,Menlo,monospace; font-variant-numeric:tabular-nums; white-space:nowrap; color:#ffffffd9; text-shadow:0 1px 3px #000,0 0 2px #000; pointer-events:none }
#fps[hidden] { display:none }
#fps.is-slow { color:#ffb86b }

/* Under the top row and the names of this part of the map, from the left: the options drawer
   when it is open, then what you have asked to go to. */
#below { z-index:2000001; position:fixed; top:calc(var(--banner) + 112px); left:16px; bottom:16px; max-width:calc(100vw - var(--panel-right,0px) - 32px); display:flex; gap:10px; align-items:flex-start; pointer-events:none }
#stack { align-self:stretch; display:flex; flex-direction:column; align-items:flex-start; gap:10px; min-width:0 }
/* On a desktop the destination card stands beside the feeds, at the top, rather than under them
   where it would run off the foot of the screen. (Long, it scrolls.) A phone goes straight there. */
body:not(.is-handheld) #stack { position:relative }
body:not(.is-handheld) #trip { position:absolute; top:0; left:calc(100% + 10px); max-height:100%; overflow-y:auto; scrollbar-width:none }
/* Two small round maps at the foot of the scene: on the left the articles round P, and on the
   right, against the reading panel when that is out, P in the whole map. */
.map { display:block; width:132px; height:132px; border-radius:50%; background:#070b1cd9; box-shadow:0 10px 30px #0006; pointer-events:none }
#map-local { margin-top:auto }
#map-global { z-index:2000001; position:fixed; right:calc(var(--panel-right,0px) + 16px); bottom:16px }
#drawer,#trip { pointer-events:auto; animation:arrive .2s ease-out }
@keyframes arrive { from { opacity:0; transform:translateX(-14px) } }

/* The options: few, with the keys listed faintly beneath them and the credits at the foot. */
#drawer { align-self:stretch; flex:none; width:252px; max-width:100%; display:flex; flex-direction:column; gap:18px; padding:18px 18px 14px; border-radius:24px; overflow-y:auto; scrollbar-width:none }
/* Grouped, a thin line between groups: the group's name in green, then its options in white,
   then what they mean in grey. */
.group { display:flex; flex-direction:column; gap:14px }
.group + .group { padding-top:18px; border-top:1px solid #ffffff1f }
.group h2 { display:flex; align-items:center; gap:8px; margin:0; font-size:14px; font-weight:750; line-height:18px; color:#4ade80 }
.option { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 12px }
.option-name { font-size:13px; font-weight:700 }
.note { flex-basis:100%; margin:0; font-size:11.5px; line-height:1.4; color:#ffffffa6 }
/* One fewer, how many, one more, across. */
#stepper { display:flex; align-items:center; gap:2px; padding:3px; border-radius:999px; background:#ffffff1a }
#stepper output { min-width:3ch; text-align:center; font-size:15px; font-weight:750; line-height:1; font-variant-numeric:tabular-nums }
#below #stepper button { width:32px; height:28px; padding:0; border-radius:999px; background:none; font-size:17px; font-weight:700; line-height:1 }
#below #stepper button:hover:not(:disabled) { background:#ffffff26 }
#below #stepper button:disabled { opacity:.3; cursor:default }
#braking,#handed { display:flex; gap:2px; padding:3px; border-radius:999px; background:#ffffff1a }
#below :is(#braking,#handed) button { padding:7px 11px; border-radius:999px; background:none; font-size:12px; font-weight:700; line-height:1 }
#below :is(#braking,#handed) button:hover { background:#ffffff26 }
#below :is(#braking,#handed) button[aria-checked="true"] { background:#fff; color:#0a0f22 }
/* An On and Off pair is a switch: both buttons cover the track, the one not chosen on top, so a
   tap anywhere on it changes it. (On is always the first.) */
.switch { position:relative; flex:none; width:46px; height:28px; border-radius:999px; background:#ffffff2e; transition:background .15s }
.switch::after { content:''; position:absolute; top:3px; left:3px; width:22px; height:22px; border-radius:50%; background:#fff; box-shadow:0 1px 3px #0006; transition:transform .15s; pointer-events:none }
.switch:has(button:first-child[aria-checked="true"]) { background:#4ade80 }
.switch:has(button:first-child[aria-checked="true"])::after { transform:translateX(18px) }
#below .switch button { position:absolute; inset:0; padding:0; border-radius:999px; background:none; color:transparent; font-size:0 }
#below .switch button[aria-checked="false"] { z-index:1 }
#below .switch button:focus-visible { outline:2px solid #fff; outline-offset:2px }

/* The places kept: one quiet line each, the five most recent until all are asked for. */
#bookmarks-group header { display:flex; align-items:center; justify-content:space-between; gap:8px }
#bookmarks-count { padding:1px 7px; border-radius:999px; background:#ffffff1a; color:#d1d5db; font-size:11px; font-weight:700; line-height:1.4; font-variant-numeric:tabular-nums }
#bookmarks-count:empty { display:none }
#below :is(#bookmarks-edit,#bookmarks-all) { padding:4px 0; background:none; color:#9ca3af; font-size:12.5px; font-weight:700; line-height:1 }
#below :is(#bookmarks-edit,#bookmarks-all):hover { color:#fff }
#below #bookmarks-all { align-self:flex-start }
#bookmarks { display:grid; gap:2px; margin:-6px -8px; padding:0; list-style:none }
#bookmarks:empty { display:none }
#bookmarks li { display:flex; align-items:center; min-width:0 }
#below #bookmarks .mark { flex:1; min-width:0; display:flex; align-items:center; gap:10px; padding:9px 8px; border-radius:12px; background:none; text-align:left }
#below #bookmarks .mark:hover { background:#ffffff12 }
#bookmarks .mark canvas { flex:none; width:24px; height:24px; margin:-2px 0 }
#bookmarks .mark b { flex:1; min-width:0; font-size:13px; font-weight:600; line-height:1.3; overflow-wrap:anywhere }
#kept-map-note { font:600 11.5px ui-monospace,SFMono-Regular,Menlo,monospace; color:#9ca3af }
#bookmarks .mark em { flex:none; font:600 11.5px ui-monospace,SFMono-Regular,Menlo,monospace; font-style:normal; color:#9ca3af }
#below #bookmarks .forget { flex:none; display:grid; place-items:center; width:22px; height:22px; margin-left:6px; padding:0; border-radius:50%; background:#ef4444; font-size:16px; font-weight:800; line-height:1 }
#bookmarks button:focus-visible { outline:2px solid #fff; outline-offset:-2px }
#below #bookmarks:not(.is-editing) .forget { display:none }
#keys { display:grid; grid-template-columns:auto 1fr; align-items:center; gap:7px 12px; margin:auto 0 0; padding-top:8px; font-size:11.5px; color:#ffffff80 }
#keys dt { display:flex; gap:3px; justify-content:flex-end }
#keys dd { margin:0 }
#keys kbd { min-width:20px; padding:3px 5px; border-radius:6px; background:#ffffff17; color:#ffffffb3; font:600 10.5px ui-monospace,SFMono-Regular,Menlo,monospace; text-align:center }
#credits { margin:0; font-size:11px; line-height:1.5; color:#ffffffb8 }
#drawer-foot { display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:12px; font-weight:700 }
#below #credits-toggle,#drawer-foot a { padding:7px 12px; border-radius:999px; background:#ffffff1a; color:#fff; text-decoration:none; line-height:1 }
#drawer-foot a { margin-left:auto }
#below #credits-toggle:hover,#drawer-foot a:hover { background:#ffffff33 }
#below #credits-toggle[aria-expanded="true"] { background:#fff; color:#0a0f22 }

/* Somewhere you have asked for: what is there, and the two ways to get to it. */
#trip { width:300px; max-width:100%; display:grid; gap:10px; padding:14px; border-radius:22px }
#trip header { display:flex; align-items:flex-start; justify-content:space-between; gap:8px }
#trip-name { min-width:0; padding:2px 0 0 4px; font-size:15px; font-weight:750; line-height:1.25; overflow-wrap:anywhere }
#below #trip-close { flex:none; width:26px; height:26px; padding:0; border-radius:50%; background:#ffffff1f; font-size:16px; line-height:1 }
#below #trip-close:hover { background:#ffffff3d }
#trip-where { margin:0; padding:0 4px; font-size:12px; line-height:1.45; color:#ffffffc7 }
#trip-where b { color:#fff; font-weight:700; text-transform:capitalize }
#trip-map { display:block; width:100%; height:132px; border-radius:14px; background:#00000038 }
#trip-near { display:grid; gap:5px; margin:0; padding:0 4px; list-style:none; font-size:12.5px; font-weight:600 }
#trip-near li { display:flex; align-items:center; gap:8px; min-width:0 }
#trip-near li::before { content:''; flex:none; width:8px; height:8px; border-radius:50%; background:hsl(var(--hue,0) 85% 66%) }
#trip-near span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
#trip .actions { display:grid; grid-template-columns:1fr 1fr; gap:8px }
#below #trip .actions button { min-height:46px; padding:6px 10px; border-radius:14px; background:#ffffff24; font-size:13px; font-weight:750; line-height:1.25 }
#below #trip .actions button:hover { background:#ffffff40 }
#below #trip #teleport { background:#fff; color:#0a0f22 }
#below #trip #teleport:hover { background:#ffffffd9 }
#below #trip .actions button:focus-visible { outline:2px solid #fff; outline-offset:2px }
#fly small { display:block; font-size:11px; font-weight:500; opacity:.8 }

/* Where P is, in a row under the top row: the part of the map P is in, its beacon's names, a
   pill each, in the middle of the row. The pills are the controls' glass, tinted with its cloud's colour. They fly
   up from the name in the scene, or arrive with a small flourish (see nameBar), and go when
   there is no such part. A last pill points the way to the middle of the part P is in and says
   how far off it is. */
.region-bar { z-index:2000001; position:fixed; left:16px; right:calc(var(--panel-right,0px) + 16px); display:flex; flex-wrap:wrap; justify-content:center; gap:8px 10px; font-size:13px; font-weight:700; line-height:18px; text-transform:capitalize; white-space:nowrap; color:#f6f7fdf2; text-shadow:0 1px 5px #0009; transition:opacity .35s; pointer-events:none }
#here-region { top:calc(var(--banner) + 70px) }
.region-bar.is-empty { opacity:0 }
.region-bar .way { display:flex; align-items:center; gap:7px; font:600 13px/18px ui-monospace,SFMono-Regular,Menlo,monospace; text-transform:none }
.region-bar .way em { font-style:normal }
.region-bar .way canvas { flex:none; width:28px; height:28px; margin:-5px -2px -5px -7px }
.region-bar span { padding:7px 15px; border-radius:999px; background:hsl(var(--hue,220) 85% 56% / .3); box-shadow:0 0 22px hsl(var(--hue,220) 90% 60% / .22) }

#status { z-index:2000003; position:fixed; left:50%; top:50%; transform:translate(-50%,-50%); padding:12px 20px; border-radius:999px; background:#101736f2; box-shadow:0 10px 30px #0006; color:#fff; font-size:14px; font-weight:600 }
#status[hidden] { display:none }
#status.is-loading { background:linear-gradient(90deg,#3350c4 var(--done,0%),#101736f2 var(--done,0%)); font-variant-numeric:tabular-nums; white-space:nowrap }
/* A passing word (see note): under the names of the part of the map, the foot having the goal and the chat. */
#status.is-note { top:calc(var(--banner) + 112px); bottom:auto; left:calc(50% - var(--panel-right,0px) / 2); transform:translateX(-50%); max-width:calc(100vw - var(--panel-right,0px) - 340px); text-align:center; pointer-events:none }

/* The feed's own sheets and toasts, opened from the article card (see js/infinity-actions.js),
   go over everything here. */
#share-sheet { z-index:2000005 }
body .lm-player { z-index:2000004 }
body .social-toast { z-index:2000006 }

/* A phone. `is-handheld` is put on the body by go.js (see handheld) for a screen worked by touch,
   or a window too small for the layout above: there is one button to fly with, one small map,
   and the article comes as a card over the whole screen. Upright or on its side, the controls
   keep to the same corners, clear of the notch and the home bar. */
:root { --edge-top:env(safe-area-inset-top,0px); --edge-right:env(safe-area-inset-right,0px); --edge-bottom:env(safe-area-inset-bottom,0px); --edge-left:env(safe-area-inset-left,0px) }
#map-switch,#ring,.pad,#tilt-option,#hand-option { display:none }
body.is-handheld { --map:clamp(84px,24vmin,132px); touch-action:manipulation; -webkit-tap-highlight-color:transparent }
body.is-handheld.map-wide { --map:min(76vmin,340px) }
body.is-handheld #hud { justify-content:flex-start; top:calc(var(--edge-top) + 4px); left:calc(var(--edge-left) + 12px); right:calc(var(--edge-right) + 12px) }
/* The top row keeps the options, the article search, and where you are. */
body.is-handheld #keys { display:none }
body.is-handheld #hud { gap:8px }
/* (The search is shorter, to leave the coordinates room beside it.) */
body.is-handheld #go { flex:1 1 0; min-width:84px; max-width:240px; margin-right:0; padding:0 6px 0 14px }
/* Where you are, compact: each letter small and lit over its number, both in the axes' colours
   (see COMPASS_AXES in go.js). No pill behind them, as the search has none: a dark shadow keeps
   them clear of the spheres. Each box is as wide as its number (--chars: see showHere), and wider
   while typed in; the arrow only comes once something is typed. */
body.is-handheld #coordinates { gap:1px; padding:0 2px }
body.is-handheld #coordinates label { --axis:#ff8a1a; flex-direction:column; gap:1px; font:800 9px/1 Inter,ui-sans-serif,system-ui,sans-serif; letter-spacing:.06em; color:var(--axis); text-shadow:0 1px 3px #000,0 0 6px var(--axis) }
body.is-handheld #coordinates label:nth-of-type(2) { --axis:#4ade80 }
body.is-handheld #coordinates label:nth-of-type(3) { --axis:#60a5fa }
body.is-handheld #coordinates input { width:calc(max(var(--chars,4),3) * 1ch + 6px); height:18px; padding:0 3px; border-radius:6px; font-size:12px; text-align:center; color:var(--axis); text-shadow:0 1px 2px #000,0 0 4px #000 }
body.is-handheld #coordinates input::placeholder { color:var(--axis) }
body.is-handheld #coordinates input:focus { width:calc(7ch + 6px); height:24px; font-size:16px }
/* iPhone focus zoom can persist after the keyboard closes, misaligning the scene layers. */
body.is-handheld :is(#go,#say,#sign-in,#friends) input { font-size:16px }
body.is-handheld #coordinates:not(:has(input:not(:placeholder-shown))) > button { display:none }
body.is-handheld #coordinates > button { width:28px; height:28px; margin-left:3px }
/* (Dropped a little in the row, so that it sits with the menu and the search rather than above them.) */
body.is-handheld #compass-axes { width:44px; height:44px; margin:8px 0 -8px auto }
body.is-handheld #fps { top:calc(var(--edge-top) + 64px); right:calc(var(--edge-right) + 14px); font-size:10px }
body.is-handheld .region-bar { left:calc(var(--edge-left) + 12px); right:calc(var(--edge-right) + 12px); gap:6px; font-size:12px; line-height:16px }
body.is-handheld .region-bar span { padding:5px 12px }
body.is-handheld #here-region { top:calc(var(--edge-top) + 58px) }
body.is-handheld .objective-line { font-size:13px }
body.is-handheld #below { top:calc(var(--edge-top) + 58px); left:calc(var(--edge-left) + 12px); bottom:calc(var(--edge-bottom) + 12px); max-width:calc(100vw - var(--edge-left) - var(--edge-right) - 24px) }
/* (They lie over the names of the part of the map, so they are not see-through.) */
body.is-handheld #trip { background:#0c1230eb }
/* The options are a sheet across the screen, under the top row: solid, over a wash that dims
   the scene (a tap on it shuts them). Rows are a thumb high, a hairline between them. */
#wash { display:none }
body.is-handheld:has(#drawer:not([hidden])) #wash { display:block; position:fixed; inset:0; background:#05081ab3; pointer-events:auto; z-index:2000002; animation:wash .2s ease-out }
@keyframes wash { from { opacity:0 } }
body.is-handheld:has(#drawer:not([hidden])) :is(#foot,.pad,#map-switch,#map-global) { visibility:hidden }
body.is-handheld { --sheet:min(320px,calc(100vw - var(--edge-left) - var(--edge-right) - 32px)) }
body.is-handheld #drawer { z-index:2000003; position:fixed; top:calc(var(--edge-top) + 58px); left:calc(var(--edge-left) + 16px); bottom:calc(var(--edge-bottom) + 16px); width:var(--sheet); padding:10px 20px 18px; background:#242830; box-shadow:0 20px 50px #000a; -webkit-backdrop-filter:none; backdrop-filter:none; animation-name:rise }
@keyframes rise { from { opacity:0; transform:translateY(-10px) } }
body.is-handheld .group { gap:0 }
body.is-handheld .group h2,body.is-handheld #bookmarks-group header { margin:2px 0 4px }
body.is-handheld #bookmarks-group header h2 { margin:0 }
body.is-handheld .group > .option { min-height:56px; padding:10px 0 }
body.is-handheld .group > .option ~ .option { border-top:1px solid #ffffff14 }
body.is-handheld #stepper button { width:40px; height:34px }
body.is-handheld #bookmarks { margin:4px -8px }
body.is-handheld #below #bookmarks .mark { min-height:48px }
body.is-handheld #below #bookmarks-all { padding:12px 0 }
/* A bookmark's card lies over the sheet it was opened from, as wide, and goes when it does. */
body.is-handheld #drawer:not([hidden]) ~ #stack #trip { z-index:2000004; position:fixed; top:calc(var(--edge-top) + 70px); left:calc(var(--edge-left) + 28px); width:calc(var(--sheet) - 24px); max-height:calc(100% - var(--edge-top) - var(--edge-bottom) - 98px); overflow-y:auto; scrollbar-width:none; background:#2e333d; box-shadow:0 16px 40px #000c }
body.is-handheld #stack { align-self:auto; max-height:calc(100% + 24px); margin:-12px; padding:12px; overflow-y:auto; scrollbar-width:none }
/* (A passing word goes under the top row, out of the thumb's way and the column's.) */
body.is-handheld #status.is-note { left:50%; max-width:calc(100vw - 32px); top:calc(var(--edge-top) + 132px); bottom:auto }

/* The thumb that flies has its side of the screen to itself (see TAP in go.js): everything laid
   over the foot of the scene stands in one column at the other side. From the foot up: the one
   map, whichever of the two the button over it says (a tap on the map makes it large, and
   another small again); then the buttons that stand in for keys, R to centre and B to
   bookmark. A new one goes on top. Right-handed, the column is on the left; `data-hand` on
   the body (the Hand option) puts it on the right. */
/* The map and the buttons over it sit in a corner, clear of an iPhone's home bar in the middle: they go to the foot of the screen, as on Android. */
body.is-handheld { --column:calc(var(--edge-left) + 12px); --foot:12px }
body.is-handheld[data-hand="left"] { --column:calc(var(--edge-right) + 12px) }
/* It keeps to the edges, as far in from them as the options button at the top is: the map in
   the corner, its switch tucked in beside it along the foot, the buttons up the edge over it. */
body.is-handheld :is(.map,#map-global) { z-index:2000000; position:fixed; left:var(--column); right:auto; bottom:var(--foot); width:var(--map); height:var(--map); margin:0; pointer-events:auto; cursor:pointer }
body.is-handheld[data-map="local"] #map-global,body.is-handheld[data-map="global"] #map-local { display:none }
/* The switch is a band round the map's rim at 45°, up and in towards the middle of the screen:
   the button is a square round the map (only the band takes a touch), and the band and its
   words are drawn to the map's size (see bendSwitch in go.js). */
#map-switch { --rim:24px; z-index:2000000; position:fixed; left:calc(var(--column) - var(--rim)); bottom:calc(var(--foot) - var(--rim)); width:calc(var(--map) + var(--rim) * 2); height:calc(var(--map) + var(--rim) * 2); min-height:0; margin:0; padding:0; border:0; background:none; box-shadow:none; pointer-events:none; font:700 12px/1 Inter,ui-sans-serif,system-ui,sans-serif }
#map-switch svg { display:block; width:100%; height:100%; overflow:visible }
#map-switch path { fill:none; stroke:transparent; stroke-width:20px; stroke-linecap:round; pointer-events:stroke; cursor:pointer }
#map-switch:active path { stroke:#ffffff40 }
#map-switch text { fill:#fff; text-shadow:0 1px 5px #000,0 0 2px #000; pointer-events:none }
body.is-handheld #map-switch { display:block }
.pad { --step:0; z-index:2000000; position:fixed; left:var(--column); bottom:calc(var(--foot) + var(--map) + 10px + var(--step) * 54px); width:44px; height:44px; min-height:0; margin:0; padding:0; place-items:center; border-radius:50%; background:#ffffff14; cursor:pointer; touch-action:manipulation; -webkit-user-select:none; user-select:none }
#keep { --step:1 }
#speak { --step:4 }
/* The music's button stands over the one for speaking, and on a desktop too, over the map
   at the foot of the left edge. Lit while the music is on; crossed out while it is off. */
#sound { --step:5 }
#sound[aria-pressed="true"] .off,#sound[aria-pressed="false"] .on { display:none }
#sound[aria-pressed="false"] { opacity:.6 }
body:not(.is-handheld) #sound:not([hidden]) { display:grid; left:16px; bottom:158px; cursor:pointer }
body:not(.is-handheld) #sound:hover { background:#ffffff2e }
#tilt { --step:2 }
#collide { --step:3 }
/* (Tilting is on: the button is lit.) */
.pad.is-on { background:#fff }
.pad.is-on svg { stroke:#0a0f22 }
.pad[hidden] { display:none !important }
body.is-handheld .pad { display:grid }
/* (Made large, the map has the column to itself, its switch still on its rim.) */
body.is-handheld.map-wide .pad { display:none }
body.is-handheld[data-hand="left"] :is(.map,#map-switch,.pad) { left:auto }
body.is-handheld[data-hand="left"] :is(.map,#map-global,.pad) { right:var(--column) }
body.is-handheld[data-hand="left"] #map-switch { right:calc(var(--column) - var(--rim)) }
body.is-handheld :is(#tilt-option,#hand-option):not([hidden]) { display:flex }
/* How tilting feels, set by hand while good values are being found: each slider says its value. */
#tilt-tuning,#camera-tuning { flex-basis:100%; display:grid; gap:9px; font-size:12px; font-weight:600 }
#tilt-tuning label,#camera-tuning label { display:grid; grid-template-columns:1fr auto; align-items:center; gap:2px 8px; margin:0; color:#fff }
#tilt-tuning output,#camera-tuning output { font:600 12px ui-monospace,SFMono-Regular,Menlo,monospace; color:#ffffffc7 }
#tilt-tuning input[type="range"],#camera-tuning input[type="range"] { grid-column:1 / -1; width:100%; height:26px; margin:0; padding:0; accent-color:#fff }
#tilt-tuning .tick { grid-template-columns:auto 1fr; justify-items:start; gap:8px }
#tilt-tuning .tick input { width:18px; height:18px; margin:0; accent-color:#fff }
#below :is(#tilt-reset,#camera-reset,#camera-edit,#discovery-reset,#objectives-reset) { justify-self:start; padding:7px 12px; border-radius:999px; background:#ffffff1a; font-size:12px; font-weight:700; line-height:1 }
.pad svg,#menu svg { width:24px; height:24px; fill:none; stroke:#fff; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; pointer-events:none }
.pad:active { background:#fff }
.pad:active svg { stroke:#0a0f22 }

/* While an article is up (the app's card, or the viewer's reading panel over the whole screen,
   with its close button at its foot) the flight controls are away. */
body.is-handheld #hud,body.is-handheld #below,body.is-handheld .pad,body.is-handheld #map-switch,body.is-handheld #map-global,body.is-handheld #fps { transition:opacity .25s,visibility .25s }
body.is-handheld.is-reading :is(#hud,.region-bar,#below,.pad,#map-switch,#map-global,#status.is-note,#foot,#trackers,#fps,#guest-note) { opacity:0; visibility:hidden; pointer-events:none }
/* On a phone the foot (the goal, and the chat bar while chat is on: its button in the column,
   see setChatting in go.js) lies beside the map, along the foot of the screen. Tapped, the bar goes the
   width of the screen and sits on the keyboard (--keyboard: see fitKeyboard), and the goal,
   the friends and the feeds give way; said or left, it slides back. Made large, the map has
   the foot to itself. */
body.is-handheld #trackers { top:calc(var(--edge-top) + 94px); right:calc(var(--edge-right) + 12px); max-height:calc(46vh + 24px) }
/* (The feeds on the left and the friends on the right share the width, half each.) */
body.is-handheld .tracker { max-width:min(240px,calc(50vw - var(--edge-left) - 18px)) }
body.is-handheld .tracker.is-open { width:min(240px,calc(50vw - var(--edge-left) - 18px)) }
body.is-handheld .tracker-title { max-width:min(180px,calc(50vw - 80px)) }
body.is-handheld #foot { --beside:calc(var(--column) + var(--map) + 28px); left:var(--beside); bottom:max(var(--foot),var(--edge-bottom)); transform:none; width:min(420px,calc(100vw - var(--beside) - var(--edge-right) - 12px)); transition:left .25s ease,right .25s ease,width .25s ease,bottom .2s ease-out }
/* Beside the minimap, give the goal's words the space until its hint is offered. */
body.is-handheld #objective #objective-hint.is-waiting { display:none }
body.is-handheld[data-hand="left"] #foot { left:auto; right:var(--beside); width:min(420px,calc(100vw - var(--beside) - var(--edge-left) - 12px)) }
body.is-handheld #foot:has(#say:focus-within) { z-index:2000003; left:calc(var(--edge-left) + 8px); width:calc(100vw - var(--edge-left) - var(--edge-right) - 16px); bottom:calc(var(--keyboard,0px) + 8px) }
body.is-handheld[data-hand="left"] #foot:has(#say:focus-within) { right:calc(var(--edge-right) + 8px); width:calc(100vw - var(--edge-left) - var(--edge-right) - 16px) }
body.is-handheld #talk:focus-within #talk-log { max-height:min(40vh,calc(var(--room,100vh) - var(--edge-top) - 76px)) }
body.is-handheld #foot:has(#say-text:focus) #objective { display:none }
body.is-handheld.chat-off:not(.is-talking) #talk:not(:focus-within),body.is-handheld.map-wide #foot:not(:focus-within) { display:none }
body.is-handheld:has(#talk:focus-within) :is(#trackers,#feeds) { display:none }
/* The feeds keep to the left under the names of the part of the map, as the friends do on the right. The
   destination card, which lies over the names of the part of the map, comes before them; the
   options drawer has the column to itself. */
body.is-handheld #feeds { order:0 }
body.is-handheld #trip[hidden] + #feeds { margin-top:36px }
body.is-handheld #drawer:not([hidden]) ~ #stack #feeds { display:none }
body.is-handheld #talk-log { background:#0c1230eb }
body.is-handheld #talk-log { padding:8px 14px; border-radius:16px }
body.is-handheld #talk-log:empty { display:none }
body.is-handheld #reader { inset:0; width:auto; flex-direction:column; padding:var(--edge-top) var(--edge-right) 0 var(--edge-left); background:linear-gradient(#000000c7,#000000eb 34%) }
body.is-handheld #reader .card.reader-card { flex:1 1 0; height:auto }
body.is-handheld #reader .reader-media { height:clamp(120px,24vh,240px) }
body.is-handheld.is-overlaid #reader .reader-media::before,body.is-handheld.is-overlaid #reader .reader-media img { -webkit-mask-image:var(--fade); -webkit-mask-composite:source-over; mask-image:var(--fade); mask-composite:add }
body.is-handheld #reader .reader-media .title { padding:0 20px 10px; font-size:24px }
body.is-handheld #reader .reader-content { padding:12px 20px 8px }
/* Every category shows, however many rows that takes: it is the text over them that gives way. */
body.is-handheld #reader .reader-pills { padding:8px 16px 2px; max-height:none; overflow:visible }
body.is-handheld #reader .reader-content { min-height:72px }
body.is-handheld #ring:not([hidden]) { display:block; position:relative; flex:none; width:176px; height:176px; margin:8px auto calc(var(--edge-bottom) + 14px) }
#ring > * { position:absolute; left:calc(50% + var(--x,0px)); top:calc(50% + var(--y,0px)); min-height:0; padding:0; border:0; border-radius:50%; cursor:pointer; will-change:transform }
#ring-close { width:50px; height:50px; margin:-25px; background:#fff; color:#0a0f22; font:400 28px/1 Inter,ui-sans-serif,system-ui,sans-serif; box-shadow:0 8px 24px #0009 }
#ring .ring-action { display:grid; place-items:center; box-sizing:border-box; width:46px; min-width:46px; height:46px; min-height:46px; margin:-23px; gap:0; overflow:visible; background:#ffffff24; -webkit-backdrop-filter:blur(14px) saturate(1.4); backdrop-filter:blur(14px) saturate(1.4); box-shadow:0 8px 22px #0007; color:#fff; font:600 18px/1 Inter,ui-sans-serif,system-ui,sans-serif; text-decoration:none; text-shadow:none }
@media (orientation:landscape) {
  /* On its side the ring stands at the left, over the scene, and the card has the rest. */
  body.is-handheld #reader { flex-direction:row-reverse; padding-bottom:var(--edge-bottom); background:linear-gradient(90deg,#00000080 0,#000000e0 200px,#000000ed 100%) }
  body.is-handheld #reader .card.reader-card { width:auto; min-width:0; height:100% }
  body.is-handheld #reader .reader-media { height:clamp(84px,30vh,220px) }
  body.is-handheld #ring:not([hidden]) { margin:auto 18px auto 22px }
}
@media (prefers-reduced-motion:reduce) { .is-pointed { box-shadow:0 0 0 3px #4ade80b3 } } 
@media (prefers-reduced-motion:reduce) { .orb.is-lighting,#avatar::after,#drawer,#trip,#wash,.request,.orb.is-near::before,#objective.is-new .objective-line,.tracker.is-near .tracker-dot,#objective-tip,.is-pointed,.is-arrived { animation:none } body.is-handheld :is(#hud,#below,.pad,#map-switch,#map-global,#foot) { transition:none } }


/* The director (see startDirector in go.js): the map alone, under black bars and darkened corners, with the name of each stop as the camera holds there. */
body.is-director > :not(#sky,#space,#horizon,#beacons,#orbs,#labels,.director-fx,.director-guides,.director-review), body.is-director #avatar { display:none !important }
.director-fx { position:fixed; inset:0; z-index:2000002; pointer-events:none; background:radial-gradient(ellipse at center, transparent 45%, rgb(0 0 0 / calc(var(--vignette) * .45)) 75%, rgb(0 0 0 / var(--vignette)) 100%) }
.director-fx::before,.director-fx::after { content:""; position:absolute; left:0; right:0; height:var(--bars,0px); background:#000 }
.director-fx::before { top:0 }
.director-fx::after { bottom:0 }
.director-caption { position:absolute; left:6vw; right:6vw; bottom:calc(var(--bars,0px) + 6vh); margin:0; text-align:center; font-size:clamp(18px,3vw,38px); font-weight:650; letter-spacing:.08em; text-transform:uppercase; color:#fff; text-shadow:0 2px 18px #000c; opacity:0 }

/* The director's review bar and crops (see buildReview and GUIDES in go.js): over the picture, never part of it. */
.director-guides { position:fixed; inset:0; z-index:2000003; pointer-events:none; overflow:hidden }
.director-guides[hidden],.director-review[hidden],.director-review [hidden] { display:none }
.director-crop { position:absolute; outline:2px dashed #ffffffd9; box-shadow:0 0 0 100vmax #000000a6 }
.director-crop-name { position:absolute; left:0; bottom:100%; padding:0 0 4px; font-size:12px; color:#fffc; white-space:nowrap }
.director-zone { position:absolute; display:flex; align-items:center; justify-content:center; font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:#ffd0d0; background:repeating-linear-gradient(135deg,#ff505038 0 8px,#ff505014 8px 16px); outline:1px solid #ff6b6b80 }
.director-review { position:fixed; left:12px; right:12px; bottom:12px; z-index:2000004; display:flex; flex-direction:column; align-items:center; gap:8px; pointer-events:none; font-size:13px; color:#fff }
.director-review > * { pointer-events:auto }
.director-bar { display:flex; align-items:center; gap:6px; width:min(1100px,100%); padding:6px 10px; border-radius:12px }
.director-review button { padding:6px 10px; border:0; border-radius:8px; background:none; color:#fff; font:inherit; cursor:pointer; white-space:nowrap }
.director-review button:hover { background:#ffffff1f }
.director-bar > button:first-child { width:38px; font-size:15px }
.director-clock { min-width:9.5em; font-variant-numeric:tabular-nums; color:#fffd }
.director-track { position:relative; flex:1; height:26px; cursor:pointer; touch-action:none }
.director-track::before { content:""; position:absolute; left:0; right:0; top:11px; height:4px; border-radius:2px; background:#ffffff33 }
.director-fill { position:absolute; left:0; top:11px; height:4px; border-radius:2px; background:#fff }
.director-tick { position:absolute; top:6px; width:1px; height:14px; background:#ffffff80 }
.director-marks { position:absolute; inset:0; pointer-events:none }
.director-mark { position:absolute; top:8px; width:10px; height:10px; margin-left:-5px; border-radius:50%; background:#ffb020; box-shadow:0 0 0 2px #0008 }
.director-comment { width:min(640px,100%); padding:6px; border-radius:12px }
.director-comment input { width:100%; box-sizing:border-box; padding:8px 10px; border:0; border-radius:8px; background:#0006; color:#fff; font:inherit; outline:none }
.director-notes { align-self:flex-end; width:min(460px,100%); max-height:50vh; overflow:auto; padding:10px 12px; border-radius:12px }
.director-notes h2 { margin:0 0 6px; font-size:14px }
.director-notes ol { margin:0; padding:0; list-style:none }
.director-notes li { display:grid; grid-template-columns:auto 1fr auto; align-items:baseline; gap:0 6px; padding:4px 0; border-top:1px solid #ffffff1a }
.director-notes li small { grid-column:2; color:#fff9; font-size:11px }
.director-notes .director-note-time { padding:2px 6px; font-variant-numeric:tabular-nums; color:#ffb020 }
.director-notes .director-note-gone { grid-column:3; grid-row:1; padding:0 6px; color:#fff9 }
.director-notes .director-note-text { white-space:pre-wrap; overflow-wrap:anywhere }
.director-notes .director-note-none { display:block; color:#fff9 }
.director-notes-foot { display:flex; flex-wrap:wrap; align-items:center; gap:4px; margin:8px 0 0 }
.director-done { color:#9fe39f }
.director-caption-name { display:block }
.director-caption-under { display:block; margin-top:.35em; font-size:.42em; font-weight:500; letter-spacing:.14em; color:#fffc }
