/* Layout: a full-screen LittleJS canvas with a thin HTML layer on top: corner HUD, centered prompts and toasts,
   a bottom dialog sheet, modal cards for the journal, menu and catches, and the cutscene layer. Single dark look by design.
   Type: Fraunces (soft, a little wonky, storybook) for names, titles and anything read like a story; Nunito (rounded)
   for the interface. Both ship in fonts/ so the desktop app looks the same offline.
   The look: every panel is night glass with a faint speckle of stars, framed like a book plate (a hairline, a dark gap,
   a second fainter rule) and warmed along its top edge as if by the lantern; the storybook page set the language.
   Buttons are soft-cornered and lit from above, the primary one glows amber. Key and button glyphs (ui/glyphs.js)
   are masks, so they take the colour of the text they sit in. */
@font-face { font-family: "Fraunces"; src: url("fonts/fraunces.woff2") format("woff2"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Fraunces"; src: url("fonts/fraunces-italic.woff2") format("woff2"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Nunito"; src: url("fonts/nunito.woff2") format("woff2"); font-weight: 200 1000; font-style: normal; font-display: swap; }
:root {
  --void: #07051a;
  --ink: #f1ecff;
  --ink-dim: #b6add8;
  --panel: rgba(17, 11, 42, .86);
  --panel-2: rgba(32, 22, 72, .9);
  --line: rgba(190, 170, 255, .24);
  --amber: #ffcd78;
  --violet: #b097ff;
  --teal: #7fe3e0;
  --rose: #ff9ec7;
  --font-display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --font-ui: "Nunito", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  --soft: "SOFT" 100, "WONK" 1;      /* Fraunces at its roundest, with the wonky italic letters */
  --bar: 11vh;                       /* cutscene letterbox */
  --glass: linear-gradient(180deg, rgba(38, 26, 84, .92), rgba(15, 9, 38, .92));
  --speckle: radial-gradient(circle at 30% 40%, rgba(255, 255, 255, .07) 0 .7px, transparent 1.2px) 0 0 / 37px 41px,
    radial-gradient(circle at 70% 65%, rgba(255, 220, 160, .06) 0 .7px, transparent 1.2px) 0 0 / 53px 47px;
  --plate: inset 0 0 0 3px rgba(9, 6, 26, .55), inset 0 0 0 4px rgba(190, 170, 255, .1),
    inset 0 18px 26px -22px rgba(255, 205, 120, .3), 0 14px 40px rgba(3, 1, 16, .5);
  color-scheme: dark;
}
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; padding: 0; }
/* The engine sizes its canvases from innerWidth and innerHeight and centres them in the body. Opened from an iPhone
   home screen those disagree with the screen, and the engine's black body showed as a band across the top, so the
   page is pinned to the screen and the canvases fill it whatever the window reports (input follows the canvas's
   real box, so taps still land where they look) */
body { position: fixed; inset: 0; }
body > canvas { top: 0 !important; left: 0 !important; transform: none !important; width: 100% !important; height: 100% !important; }
body { background: var(--void); color: var(--ink); font-family: var(--font-ui); font-weight: 550; -webkit-font-smoothing: antialiased; }
h1, h2, #place, #dialog .who, #dialog .text, .cine-line, .cine-big, .cap-title { font-variation-settings: var(--soft); }
.ui { position: fixed; z-index: 10; pointer-events: none; }
.ui button, .ui input, .ui .tap { pointer-events: auto; }
button { font: inherit; color: inherit; }
kbd {
  font-family: var(--font-ui); font-size: .78em; font-weight: 800;
  padding: 2px 7px; border-radius: 5px; border: 1px solid var(--line); border-bottom-width: 2px;
  background: rgba(255, 255, 255, .06); color: var(--ink);
}
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid rgba(190, 170, 255, .3); color: var(--ink); border-radius: 11px; padding: 9px 16px; cursor: pointer;
  letter-spacing: .01em; font-weight: 750; background: linear-gradient(180deg, rgba(60, 44, 122, .95), rgba(30, 20, 70, .95));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .09), inset 0 -2px 0 rgba(0, 0, 0, .25), 0 2px 8px rgba(3, 1, 16, .35);
  transition: border-color .2s, box-shadow .2s, transform .1s;
}
.btn:hover { border-color: rgba(255, 205, 120, .55); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .09), inset 0 -2px 0 rgba(0, 0, 0, .25), 0 0 14px rgba(255, 205, 120, .2); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.tabs button:focus-visible, .item:focus-visible, input[type=range]:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.btn.primary { background: linear-gradient(180deg, #ffe3a8, #f2b45c); color: #3a2208; border-color: rgba(255, 228, 175, .9); font-weight: 800;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .35);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6), inset 0 -2px 0 rgba(150, 90, 20, .35), 0 0 20px rgba(255, 205, 120, .35); }
.btn.primary:hover { filter: brightness(1.06); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6), inset 0 -2px 0 rgba(150, 90, 20, .35), 0 0 26px rgba(255, 205, 120, .5); }

/* key and button glyphs, and the on-screen buttons named in words on a touch screen */
.glyph { display: inline-block; width: 1.6em; height: 1.6em; vertical-align: -.45em; flex: none; background: currentColor;
  -webkit-mask: var(--glyph) center / contain no-repeat; mask: var(--glyph) center / contain no-repeat; }
.glyphs { display: inline-flex; gap: 0; vertical-align: -.45em; }
.glyphs .glyph { width: 1.35em; height: 1.35em; vertical-align: 0; }
.btn .glyph { width: 1.4em; height: 1.4em; margin: -.2em -.25em -.2em 0; opacity: .75; }
.glyph.wide { width: 2.4em; -webkit-mask-size: 100% auto; mask-size: 100% auto; }
.btn .glyph.wide { width: 2.1em; }
.glyph-word { font: 800 .7em var(--font-ui); letter-spacing: .08em; text-transform: uppercase; padding: 2px 7px; border-radius: 6px;
  border: 1px solid var(--line); background: rgba(255, 255, 255, .06); }
.pad-only { display: none !important; }
body[data-input="pad"] .pad-only { display: revert !important; }
body[data-input="pad"] .keys-only { display: none !important; }
/* the mouse pointer hides with a gamepad, and while playing (ui/cursor.js); with a pad whatever has focus is ringed, since A presses it */
body[data-input="pad"], body[data-input="pad"] *, body.no-cursor, body.no-cursor * { cursor: none !important; }
body[data-input="pad"] .ui :focus { outline: 2px solid var(--amber); outline-offset: 2px; box-shadow: 0 0 16px rgba(255, 205, 120, .35); }

/* title */
#title {
  inset: 0; display: grid; place-items: center; padding: 24px 16px; z-index: 30; pointer-events: auto; overflow: auto;
  background: radial-gradient(ellipse at 50% 60%, rgba(7, 5, 26, .15), rgba(7, 5, 26, .78));
}
#title .card { width: min(520px, 100%); display: grid; gap: 18px; text-align: center; }
#title h1 {
  margin: 0; font-family: var(--font-display); font-weight: 300; font-style: italic;
  font-size: clamp(2.4rem, min(11vw, 15vh), 5.6rem); letter-spacing: -.01em; line-height: 1;
  text-shadow: 0 0 34px rgba(176, 151, 255, .65);
}
#title h1 .k-drift .kc { color: var(--ink); }
#title h1 .k-drift .kc.on { animation-duration: 4.5s; }
#title .tag { margin: 0; color: var(--ink-dim); font-family: var(--font-display); font-variation-settings: var(--soft); font-size: 1.08rem; line-height: 1.6; text-wrap: balance; }
#title .keys {
  display: grid; grid-template-columns: auto 1fr; gap: 9px 14px; align-items: center; text-align: left; padding: 14px 18px; font-size: .9rem; color: var(--ink-dim);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: linear-gradient(180deg, rgba(255, 255, 255, .03), transparent);
}
#title .keys > span:nth-child(odd) { justify-self: end; white-space: nowrap; color: var(--ink); }
#title .tag::before { content: "✦"; display: block; margin-bottom: 12px; font-size: .8rem; color: var(--amber); text-shadow: 0 0 12px rgba(255, 205, 120, .8); }
#title .row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
#title .note { font-size: .78rem; color: var(--ink-dim); margin: 0; }
.touch-only { display: none !important; }
body.touch .touch-only { display: revert !important; }
body.touch .desk-only { display: none !important; }
body.touch .keys.touch-only, body.touch .keys-small.touch-only { display: grid !important; }     /* revert would make them blocks */
/* a phone or tablet: no text selection, long-press menus, tap flashes, double-tap zoom or pull to refresh; only
   cards scroll */
body.touch { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none; }
/* the engine sets touch-action:none inline on the body, which a scrolling card inside it inherits the effect of; pan
   (no pinch or double-tap zoom) lets cards scroll, and the canvas below stays none */
body.touch { touch-action: pan-x pan-y !important; }
/* The touch layout: one set of sizes, scaled to the screen's short side and clamped, that every touch control and
   everything that must clear them is placed from, so no element carries a pixel position tuned to one phone. On a
   390 px wide phone they come to the sizes the controls were tuned at: stick 120, Use 74, Jump 86, Back 58 */
body.touch {
  --gap: clamp(8px, 3vmin, 14px);
  --edge-x: calc(var(--gap) * 1.4 + env(safe-area-inset-right, 0px));
  --edge-y: calc(var(--gap) * 2 + env(safe-area-inset-bottom, 0px));
  --btn: clamp(60px, 19vmin, 88px);                 /* Use */
  --btn-big: calc(var(--btn) * 1.16);               /* Jump */
  --btn-small: calc(var(--btn) * .78);              /* Back */
  /* the engine's stick size (ui/touch.js measures this and passes it on): its ring is half of it across, centred one
     size in from the corner, so it needs 1.5 x this of height, which the bottom-left quarter always has */
  --stick: clamp(88px, 31vmin, 136px);
  --controls-top: calc(var(--edge-y) + var(--btn) + var(--gap) + var(--btn-small));     /* the button column, Back on Use */
  --hud-bottom: calc(env(safe-area-inset-top, 0px) + 3.6rem);
}
body.touch canvas { touch-action: none; }
body.touch .card, body.touch #title { touch-action: pan-y; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

/* HUD */
#hud { top: 0; left: 0; right: 0; display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: calc(12px + env(safe-area-inset-top, 0px)) 16px 0; }
.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip { background: var(--speckle), var(--glass); border: 1px solid var(--line); border-radius: 10px; padding: 5px 12px; font-size: .85rem;
  font-variant-numeric: tabular-nums; display: flex; gap: 6px; align-items: center; box-shadow: inset 0 1px 0 rgba(255, 220, 160, .1), 0 4px 14px rgba(3, 1, 16, .35); }
.chip b { color: var(--amber); font-weight: 800; text-shadow: 0 0 10px rgba(255, 205, 120, .45); }
.hud-btns { display: flex; gap: 8px; }
.hud-btns .btn { padding: 6px 12px; font-size: .85rem; border-radius: 10px; background: var(--speckle), var(--glass); }
#place { top: calc(64px + env(safe-area-inset-top, 0px)); left: 0; right: 0; text-align: center; padding: 0 16px;
  font-family: var(--font-display); font-style: italic; font-size: clamp(1.5rem, 4vw, 2.3rem);
  text-shadow: 0 0 24px rgba(176, 151, 255, .8); opacity: 0; transition: opacity 1.2s ease; }
#place.on { opacity: 1; }
#place small { display: block; font-family: var(--font-ui); font-style: normal; font-size: .8rem; color: var(--ink-dim); letter-spacing: .12em; text-transform: uppercase; margin-top: 4px; }
#prompt { left: 0; right: 0; bottom: calc(150px + env(safe-area-inset-bottom, 0px)); display: flex; justify-content: center; padding: 0 16px; }
#prompt div { background: var(--speckle), var(--glass); border: 1px solid rgba(255, 205, 120, .3); border-radius: 12px; padding: 6px 16px 6px 9px; font-size: .95rem;
  display: flex; gap: 9px; align-items: center; box-shadow: var(--plate), 0 0 22px rgba(255, 205, 120, .12); }
.prompt-key { color: var(--amber); display: inline-flex; filter: drop-shadow(0 0 6px rgba(255, 205, 120, .45)); }
.prompt-key .glyph { width: 1.9em; height: 1.9em; vertical-align: 0; }
#promptText .glyph { color: var(--amber); }
#toasts { left: 0; right: 0; bottom: calc(200px + env(safe-area-inset-bottom, 0px)); display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 0 16px; }
.toast { background: var(--speckle), var(--glass); border: 1px solid var(--line); border-radius: 12px; padding: 8px 16px; font-size: 1rem; line-height: 1.4;
  font-family: var(--font-display); font-variation-settings: var(--soft); max-width: 520px; text-align: center; animation: toastIn .35s ease; box-shadow: var(--plate); }
.toast.out { opacity: 0; transition: opacity .6s; }
@keyframes toastIn { from { opacity: 0; transform: translateY(8px); } }

/* dialog sheet */
#dialog { left: 0; right: 0; bottom: 0; display: flex; justify-content: center; padding: 0 16px calc(16px + env(safe-area-inset-bottom, 0px)); }
#dialog .sheet { position: relative; width: min(640px, 100%); background: var(--speckle), var(--glass); border: 1px solid var(--line); border-radius: 16px;
  padding: 20px 20px 14px; display: grid; gap: 8px; pointer-events: auto; box-shadow: var(--plate); }
/* the speaker's nameplate, sitting on the top edge */
#dialog .who { position: absolute; top: -14px; left: 18px; padding: 2px 13px 4px; border-radius: 9px; font-family: var(--font-display); font-style: italic;
  font-weight: 500; color: var(--amber); font-size: 1.02rem; background: linear-gradient(180deg, #33246e, #1c1344);
  border: 1px solid rgba(255, 205, 120, .45); box-shadow: 0 0 14px rgba(255, 205, 120, .15), 0 4px 10px rgba(3, 1, 16, .4); }
#dialog .who:empty { display: none; }
#dialog .text { font-family: var(--font-display); font-weight: 400; font-size: 1.12rem; line-height: 1.55; max-width: 60ch; min-height: 3.1em; }
#dialog .opts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
#dialog .hint { font-size: .8rem; color: var(--ink-dim); justify-self: end; display: flex; align-items: center; gap: 6px; }
#dialog .hint .glyph { color: var(--amber); animation: nudge 1.6s ease-in-out infinite; }
@keyframes nudge { 50% { transform: translateY(2px); opacity: .7; } }

/* fishing and swing meters */
#meter { left: 0; right: 0; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); display: flex; justify-content: center; padding: 0 16px; }
/* on a touch screen the bottom is the stick and the buttons, so the meter goes under the HUD, and the prompt and
   toasts sit above the button column */
body.touch #meter { bottom: auto; top: var(--hud-bottom); }
body.touch #prompt { bottom: calc(var(--controls-top) + var(--gap)); }
body.touch #toasts { bottom: calc(var(--controls-top) + var(--gap) + 3.2rem); }
#meter .box { width: min(440px, 100%); background: var(--speckle), var(--glass); border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; display: grid; gap: 8px; box-shadow: var(--plate); }
#meter .label { font-size: .85rem; color: var(--ink-dim); display: flex; justify-content: space-between; gap: 10px; }
.track { position: relative; height: 22px; border-radius: 999px; background: rgba(255, 255, 255, .07); overflow: hidden; border: 1px solid var(--line); }
.fill { position: absolute; inset: 0 auto 0 0; background: linear-gradient(90deg, var(--violet), var(--amber)); border-radius: 999px; }
.zone { position: absolute; top: 2px; bottom: 2px; border-radius: 999px; background: rgba(127, 227, 224, .35); border: 1px solid var(--teal); }
.zone.hit { background: rgba(127, 227, 224, .6); }
.fishmark { position: absolute; top: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px; border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg); background: var(--rose); box-shadow: 0 0 10px var(--rose); }
.track.race { height: 14px; overflow: visible; }
.track.race .turn { position: absolute; left: 50%; top: -4px; bottom: -4px; width: 2px; margin-left: -1px; background: var(--amber); box-shadow: 0 0 8px var(--amber); }
.track.race b { position: absolute; top: 50%; width: 16px; height: 16px; margin: -8px 0 0 -8px; border-radius: 50%; transition: left .1s linear; }
.track.race .me { background: var(--amber); box-shadow: 0 0 10px var(--amber); }
.track.race .oswin { background: var(--teal); box-shadow: 0 0 10px var(--teal); }
.progress { height: 6px; border-radius: 99px; background: rgba(255, 255, 255, .08); overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--teal); width: 0; }

/* modal cards */
.modal { inset: 0; display: grid; place-items: center; padding: 20px 16px; background: rgba(7, 5, 26, .55); z-index: 20; pointer-events: auto; }
.card { width: min(560px, 100%); max-height: min(84vh, 760px); max-height: min(84dvh, 760px); overflow: auto; background: var(--speckle), var(--glass); border: 1px solid var(--line);
  border-radius: 16px; padding: clamp(14px, 3.6vmin, 22px) clamp(14px, 3.6vmin, 22px) clamp(12px, 3vmin, 18px); display: grid; gap: clamp(10px, 2.6vmin, 14px); box-shadow: var(--plate);
  scrollbar-width: thin; scrollbar-color: rgba(176, 151, 255, .35) transparent; }
/* a heading has a little star before it and a rule that fades out after it */
.card h2 { margin: 0; font-family: var(--font-display); font-weight: 400; font-style: italic; font-size: clamp(1.4rem, 5.5vmin, 1.9rem); text-wrap: balance;
  display: flex; align-items: center; gap: .4em; }
.card h2::before { content: "✦"; font-style: normal; font-size: .45em; color: var(--amber); text-shadow: 0 0 10px rgba(255, 205, 120, .8); }
.card h2::after { content: ""; flex: 1; min-width: 1em; height: 1px; margin-left: .2em;
  background: linear-gradient(90deg, rgba(255, 205, 120, .45), rgba(190, 170, 255, .12) 45%, transparent); }
.end-card h2 { justify-content: center; }
.end-card h2::before, .end-card h2::after { display: none; }
.card p { margin: 0; line-height: 1.6; color: var(--ink-dim); }
.card .row { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.catch-art { height: 150px; border-radius: 12px; background: radial-gradient(ellipse at 50% 60%, rgba(176, 151, 255, .25), transparent 70%); }
.catch-art canvas { width: 100%; height: 100%; display: block; }
.stars { color: var(--amber); letter-spacing: .15em; }
.meta { display: flex; gap: 14px; flex-wrap: wrap; font-size: .85rem; color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.tabs { display: flex; gap: 2px; flex-wrap: wrap; border-bottom: 1px solid var(--line); }
.tabs button { position: relative; border: 0; background: transparent; border-radius: 8px 8px 0 0; padding: 7px 13px 9px; cursor: pointer; color: var(--ink-dim); font-weight: 700; }
.tabs button:hover { color: var(--ink); }
.tabs button[aria-selected="true"] { color: var(--ink); background: linear-gradient(180deg, rgba(255, 205, 120, .08), transparent); }
.tabs button[aria-selected="true"]::after { content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 2px; border-radius: 2px;
  background: var(--amber); box-shadow: 0 0 8px rgba(255, 205, 120, .8); }
.list { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); align-content: start; }
.item { display: grid; grid-template-columns: 34px 1fr auto; gap: 10px; align-items: center; padding: 8px 10px; border-radius: 10px;
  background: linear-gradient(90deg, rgba(255, 255, 255, .055), rgba(255, 255, 255, .015)); border: 1px solid rgba(190, 170, 255, .08); min-width: 0; }
.item.missing { opacity: .55; }
.item .dot { width: 26px; height: 26px; border-radius: 50%; }
.item .nm { font-weight: 800; }
.item .ds { font-size: .82rem; color: var(--ink-dim); line-height: 1.45; }
.item .ct { font-size: .85rem; color: var(--amber); font-variant-numeric: tabular-nums; white-space: nowrap; }
.check { width: 22px; height: 22px; border-radius: 6px; border: 1.5px solid var(--line); display: grid; place-items: center; font-size: .85rem; }
.check.done { background: var(--teal); border-color: var(--teal); color: #08202a; font-weight: 700; }
.menu-grid { display: grid; gap: 12px; }
.menu-grid label { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.menu-grid input[type=range] { width: 180px; height: 6px; -webkit-appearance: none; appearance: none; border-radius: 6px;
  background: linear-gradient(90deg, rgba(176, 151, 255, .7), rgba(255, 205, 120, .8)); }
.menu-grid input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%; border: 0;
  background: radial-gradient(circle at 35% 35%, #fff8e6, #ffcd78 60%, #c98a2e); box-shadow: 0 0 10px rgba(255, 205, 120, .7); }
.menu-grid input[type=range]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; border: 0;
  background: radial-gradient(circle at 35% 35%, #fff8e6, #ffcd78 60%, #c98a2e); box-shadow: 0 0 10px rgba(255, 205, 120, .7); }
.keys-small { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; font-size: .85rem; color: var(--ink-dim); }
.keys-small > [data-glyph] { justify-self: end; color: var(--ink); }
.slider-row { display: flex; align-items: center; gap: 10px; }
.slider-row output { font-size: .85rem; color: var(--amber); font-variant-numeric: tabular-nums; min-width: 2.6em; text-align: right; }

#fade { inset: 0; background: #05030f; opacity: 0; transition: opacity .6s ease; z-index: 25; }
#fade.on { opacity: 1; }
#scope { inset: 0; z-index: 9; background: radial-gradient(circle at 50% 50%, transparent 0 34vmin, rgba(5, 3, 15, .96) 36vmin); }
/* the telescope: arrows on the rim toward constellations, a ring that fills as one comes into focus, its name when found */
.scope-mark { position: absolute; left: 50%; top: 50%; width: 0; height: 0; transition: opacity .3s; }
.scope-mark i { position: absolute; left: -9px; top: -9px; width: 18px; height: 18px;
  clip-path: polygon(100% 50%, 15% 0, 38% 50%, 15% 100%); background: var(--amber); filter: drop-shadow(0 0 6px var(--amber)); }
.scope-mark.found i { background: var(--ink-dim); filter: none; width: 12px; height: 12px; left: -6px; top: -6px; }
.scope-mark span { position: absolute; left: 50%; top: 12px; transform: translateX(-50%); white-space: nowrap; font-size: .72rem; color: var(--ink-dim); }
.scope-ring { position: absolute; left: 50%; top: 50%; width: 9vmin; height: 9vmin; margin: -4.5vmin; border-radius: 50%; --p: 0;
  background: conic-gradient(var(--amber) calc(var(--p) * 1turn), transparent 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2px)); mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2px));
  opacity: min(1, calc(var(--p) * 4)); filter: drop-shadow(0 0 6px var(--amber)); }
.scope-cap { position: absolute; left: 50%; top: calc(50% + 20vmin); transform: translate(-50%, 8px); width: min(60vmin, 90vw); text-align: center;
  opacity: 0; transition: opacity 1.2s, transform 1.2s; pointer-events: none; }
.scope-cap.show { opacity: 1; transform: translate(-50%, 0); }
.scope-cap .cap-kicker { font-size: .72rem; letter-spacing: .3em; text-transform: uppercase; color: var(--amber); }
.scope-cap .cap-name { font-family: var(--font-display); font-style: italic; font-size: clamp(1.6rem, 4.5vmin, 2.6rem); color: var(--ink); text-shadow: 0 0 18px rgba(255, 205, 120, .45); }
.scope-cap .cap-desc { font-size: .95rem; color: var(--ink-dim); line-height: 1.5; margin-top: 4px; }
#scope .hint { position: absolute; left: 0; right: 0; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); text-align: center; color: var(--ink-dim); font-size: .9rem; padding: 0 16px; }
/* above the engine's touch stick overlay (z-index 50), so a tap on a button always reaches it */
#touch { z-index: 60; right: 0; bottom: 0; padding: 0 var(--edge-x) var(--edge-y) 0;
  display: grid; grid-template-columns: auto auto; gap: var(--gap); align-items: end; justify-items: center; }
/* The engine's touch stick listens on an invisible 3 x size square in the bottom-left corner, which on an upright
   phone reaches across to the right side. Its hit test only takes the left half, so the square becomes exactly the
   bottom-left quarter: the stick works there, and a drag anywhere in the other three quarters turns the camera.
   The overlay is the engine's own element (a div holding a div holding an svg, with no class); its first div is the
   left zone. !important wins over the inline style the engine rewrites on every relayout */
.stick-zone, body > div:not(.ui):has(> div > svg) > div > div:first-of-type { width: 50% !important; height: 50% !important; }
/* the engine means to hide the right side's zone when it has no controls (it has none here), but then rewrites the
   zone's whole inline style, display included, so an invisible 3 x size square covers the bottom-right corner and takes
   the drags meant for the camera (LittleJS 1.21.0, touchGamepadRelayout) */
.stick-zone-unused, body > div:not(.ui):has(> div > svg) > div > div:nth-of-type(2) { display: none !important; }
#tBack { grid-area: 1 / 1; } #tAct { grid-area: 2 / 1; } #tJump { grid-area: 1 / 2 / 3 / 3; }
#touch .tap { width: var(--btn); height: var(--btn); border-radius: 50%; border: 1px solid var(--line); background: rgba(32, 22, 72, .55);
  color: var(--ink); font-size: calc(var(--btn) * .175); font-weight: 700; touch-action: none; }
#touch .tap.big { width: var(--btn-big); height: var(--btn-big); background: rgba(255, 205, 120, .25); }
#touch .tap.small { width: var(--btn-small); height: var(--btn-small); font-size: calc(var(--btn-small) * .2); }

/* kinetic text: letters are typed in by ui/kinetic.js, the words move here */
.kw { display: inline-block; white-space: nowrap; }
.kc { display: inline-block; white-space: pre; opacity: 0; transform: translateY(.3em) scale(.7);
  transition: opacity .16s ease, transform .34s cubic-bezier(.3, 1.6, .5, 1); }
.kc.on { opacity: 1; transform: none; }
.k-glow .kc { color: var(--amber); text-shadow: 0 0 14px rgba(255, 205, 120, .65); font-weight: 600; }
.k-glow.on { animation: swell 1.8s ease-in-out .3s infinite alternate; }
.k-drift .kc { color: var(--teal); font-style: italic; }
.k-drift .kc.on { animation: drift 2.6s ease-in-out infinite; animation-delay: calc(var(--i) * -.18s); }
.k-hush .kc { color: var(--ink-dim); font-size: .88em; font-style: italic; }
.k-hush .kc.on { animation: tremble .22s steps(2) infinite; animation-delay: calc(var(--i) * -.07s); }
.k-big .kc { color: var(--rose); font-weight: 700; font-size: 1.3em; }
.k-big .kc.on { animation: slam .55s cubic-bezier(.2, 1.3, .4, 1) both; }
.k-joy .kc { color: var(--amber); font-weight: 700; text-shadow: 0 0 12px rgba(255, 205, 120, .5); }
/* the bob waits for the hop to land (both move the letter), then runs as a wave along the word */
.k-joy .kc.on { animation: hop .5s cubic-bezier(.3, 1.6, .5, 1) both, bob 1.4s ease-in-out infinite; animation-delay: 0s, calc(.5s + var(--i) * .1s); }
@keyframes swell { to { transform: scale(1.07); } }
@keyframes hop { 0% { transform: translateY(.5em) scale(.6) rotate(-8deg); opacity: 0; } 60% { transform: translateY(-.35em) scale(1.15) rotate(4deg); opacity: 1; } 100% { transform: none; } }
@keyframes bob { 0%, 100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-.12em) rotate(var(--tilt, 3deg)); } }
@keyframes drift { 0%, 100% { transform: translateY(.04em) rotate(-3deg); } 50% { transform: translateY(-.2em) rotate(3deg); } }
@keyframes tremble { 0% { transform: translate(.02em, -.02em); } 50% { transform: translate(-.025em, .02em); } 100% { transform: translate(.01em, .025em); } }
@keyframes slam { 0% { transform: scale(2.4); opacity: 0; filter: blur(3px); } 55% { transform: scale(.94); opacity: 1; filter: none; } 100% { transform: scale(1); } }

/* cutscenes */
#cine { inset: 0; z-index: 15; }
#cine .bar { position: absolute; left: 0; right: 0; height: 0; background: #030110; transition: height .8s cubic-bezier(.6, 0, .3, 1); }
#cine .bar.top { top: 0; }
#cine .bar.bottom { bottom: 0; }
#cine.on .bar { height: var(--bar); }
body.cine #hud, body.cine #prompt, body.cine #touch, body.cine #place, body.cine #toasts, body.cine #meter { visibility: hidden; }
.cine-sub { position: absolute; left: 0; right: 0; bottom: calc(var(--bar) + 22px); display: grid; justify-items: center; gap: 10px;
  padding: 0 24px; text-align: center; }
.cine-who { font: 800 .74rem var(--font-ui); letter-spacing: .2em; text-transform: uppercase; color: #1d1236; background: var(--amber);
  padding: 4px 13px; border-radius: 999px; opacity: 0; transform: translateY(8px); transition: opacity .3s, transform .4s cubic-bezier(.3, 1.6, .5, 1); }
.cine-who.on { opacity: 1; transform: none; }
.cine-line { font-family: var(--font-display); font-weight: 450; font-size: clamp(1.25rem, 2.7vw, 2.1rem); line-height: 1.3; max-width: 34ch;
  text-wrap: balance; text-shadow: 0 2px 14px rgba(3, 1, 16, .9), 0 0 3px rgba(3, 1, 16, .9); }
.narrator .cine-line { font-style: italic; font-weight: 350; color: #efe8ff; }
.cine-big { position: absolute; inset: 0; display: flex; flex-wrap: wrap; align-content: center; justify-content: center; column-gap: .28em; padding: 0 16px; text-align: center;
  font-family: var(--font-display); font-style: italic; font-weight: 300; font-size: clamp(3rem, 11vw, 8rem); line-height: 1;
  text-shadow: 0 0 44px rgba(176, 151, 255, .85), 0 2px 18px rgba(3, 1, 16, .7); }
.cine-big .k-big .kc { font-size: 1em; color: var(--ink); }
.cine-big .k-joy .kc { color: var(--amber); }
.cine-cap { position: absolute; left: clamp(16px, 5vw, 72px); top: calc(var(--bar) + 26px); opacity: 0; }
.cine-cap.on { animation: capLife 5.4s ease forwards; }
.cap-title { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.8rem, 4.6vw, 3.3rem); line-height: 1.05;
  text-shadow: 0 2px 16px rgba(3, 1, 16, .85); }
.cap-rule { height: 3px; width: 0; margin: 8px 0 9px; border-radius: 3px; background: linear-gradient(90deg, var(--amber), rgba(255, 205, 120, 0)); }
.cine-cap.on .cap-rule { animation: rule .9s .7s cubic-bezier(.3, 0, .2, 1) forwards; }
.cap-sub { font: 700 .8rem var(--font-ui); letter-spacing: .24em; text-transform: uppercase; color: var(--ink-dim); opacity: 0; transform: translateX(18px); }
.cine-cap.on .cap-sub { animation: subIn .7s 1.2s ease forwards; }
@keyframes capLife { 0% { opacity: 0; } 6%, 86% { opacity: 1; } 100% { opacity: 0; } }
@keyframes rule { to { width: min(440px, 70vw); } }
@keyframes subIn { to { opacity: 1; transform: none; } }
.cine-skip { position: absolute; right: 16px; bottom: calc(var(--bar) / 2 - 14px); display: flex; gap: 8px; align-items: center;
  border: 0; background: none; padding: 4px 6px; cursor: pointer; pointer-events: auto;
  font: 700 .74rem var(--font-ui); letter-spacing: .08em; color: rgba(241, 236, 255, .42); transition: color .2s; }
.cine-skip.on, .cine-skip:hover { color: var(--ink); }
.cine-skip > i { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid currentColor;
  background: conic-gradient(var(--amber) calc(var(--hold, 0) * 360deg), transparent 0); }

@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; } #place, #fade { transition: none; }
  .kc, .kc.on, .k-glow.on { animation: none !important; transition: opacity .1s; transform: none; }
}

/* the storybook open beside the reader */
#storybook { inset: 0; display: flex; align-items: center; justify-content: flex-end; padding: 24px clamp(16px, 5vw, 72px); z-index: 12; pointer-events: none;
  --cover: 270; opacity: 0; transition: opacity .6s; }
#storybook.on { opacity: 1; }
.sb-page { width: min(470px, 46vw); min-height: min(440px, 70vh); display: grid; grid-template-rows: auto 1fr auto auto; gap: 14px; padding: 28px 30px 20px;
  border-radius: 6px 16px 16px 6px; color: var(--ink);
  background: radial-gradient(ellipse at 30% 20%, hsl(var(--cover) 40% 22% / .96), hsl(var(--cover) 45% 12% / .97));
  border: 1px solid hsl(var(--cover) 50% 60% / .5); border-left: 10px solid hsl(var(--cover) 45% 35%);
  box-shadow: inset 0 0 0 6px hsl(var(--cover) 40% 18%), inset 0 0 0 7px hsl(var(--cover) 50% 60% / .35), 0 18px 50px rgba(0, 0, 0, .55);
  transform: translateX(24px) rotate(1.2deg); transition: transform .8s cubic-bezier(.2, .8, .2, 1); }
#storybook.on .sb-page { transform: none; }
.sb-title { font-family: var(--font-display); font-style: italic; font-size: .95rem; letter-spacing: .04em; color: hsl(var(--cover) 60% 78%); text-align: center;
  border-bottom: 1px solid hsl(var(--cover) 50% 60% / .3); padding-bottom: 10px; }
.sb-text { font-family: var(--font-display); font-size: clamp(1.1rem, 2.1vmin, 1.4rem); line-height: 1.7; align-self: center; text-wrap: pretty; }
.sb-text.turn { animation: sbTurn .5s ease-out; }
@keyframes sbTurn { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
.sb-text.first > .kw:first-child .kc:first-child { float: left; font-size: 3.4em; line-height: .9; margin: .06em .12em 0 0; color: hsl(var(--cover) 70% 75%);
  text-shadow: 0 0 18px hsl(var(--cover) 80% 60% / .5); }
.sb-foot { display: flex; justify-content: space-between; align-items: center; color: hsl(var(--cover) 50% 70%); font-size: .85rem; }
.sb-motif { font-size: 1.2rem; letter-spacing: .6em; animation: swell 2.4s ease-in-out infinite alternate; }
.sb-num { font-variant-numeric: tabular-nums; color: var(--ink-dim); }
.sb-keys { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: .8rem; color: var(--ink-dim); opacity: .45; transition: opacity .4s; }
#storybook.typed .sb-keys { opacity: 1; }
@media (max-width: 700px) { #storybook { align-items: flex-end; justify-content: center; } .sb-page { width: 100%; min-height: 0; } }
/* on a touch screen the page is tapped to turn it; it sits above the button column, where Back stops reading */
body.touch .sb-page { pointer-events: auto; }
body.touch #storybook { padding-bottom: calc(var(--controls-top) + var(--gap)); }

/* a phone held upright: smaller sliders, the HUD's buttons and counters a little tighter */
@media (max-width: 480px) {
  .menu-grid input[type=range] { width: 130px; }
  .menu-grid label { gap: 8px; }
  #hud { padding-left: 12px; padding-right: 12px; }
  .chip, .hud-btns .btn { font-size: .8rem; }
}
/* wide and short (a phone on its side, a short window): the cards spread out across the width in columns instead of
   stacking one tall column, so they fit without scrolling and without empty space either side */
@media (orientation: landscape) and (max-height: 540px) {
  .modal, #title { padding: max(8px, env(safe-area-inset-top, 0px)) max(16px, env(safe-area-inset-right, 0px)) max(8px, env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px)); }
  .card { width: min(880px, 100%); max-height: 100%; }
  #prompt { bottom: calc(110px + env(safe-area-inset-bottom, 0px)); }
  #toasts { bottom: calc(150px + env(safe-area-inset-bottom, 0px)); }
  /* title: the name and the story on the left, the controls and the way in on the right */
  #title .card { width: min(880px, 100%); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 28px; row-gap: 12px;
    align-items: center; grid-template-areas: "name keys" "tag keys" "tag start" "tag note"; }
  #title h1 { grid-area: name; }
  #title .tag { grid-area: tag; font-size: 1rem; }
  #title .keys { grid-area: keys; }
  #title .row { grid-area: start; }
  #title .note { grid-area: note; }
  /* menu: the settings on the left, how to play on the right, the ways out along the bottom */
  .menu-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 28px; align-items: start; }
  .menu-grid > label, #resetRow { grid-column: 1; }
  .menu-grid > .keys-small { grid-column: 2; grid-row: 1 / span 5; align-self: center; }
  /* journal: the heading and its tabs share a row; the list below flows into columns */
  #journal .card { grid-template-columns: auto minmax(0, 1fr); align-items: end; column-gap: 20px; }
  #jBody, #journal .row { grid-column: 1 / -1; }
  /* catch: the fish beside what it is */
  #catch .card { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); column-gap: 20px; align-items: start; }
  #catch .catch-art { grid-row: 1 / span 4; height: 100%; min-height: 120px; }
  #catch .card > :not(.catch-art) { grid-column: 2; }
  /* the storybook: between the stick and the buttons, the full height; the buttons sit beside it, not below */
  #storybook, body.touch #storybook { justify-content: center; align-items: center; padding: max(8px, env(safe-area-inset-top, 0px)) 0 8px; }
  .sb-page { width: min(470px, 56vw); min-height: 0; max-height: 100%; overflow: auto; gap: 8px; padding: 16px 22px 12px; }
}

/* the aquarium: the fish nearest the middle of the view, named at the top */
.tank-name { left: 0; right: 0; top: calc(70px + env(safe-area-inset-top, 0px)); text-align: center; opacity: 0; transform: translateY(-6px);
  transition: opacity .6s, transform .6s; }
.tank-name.show { opacity: 1; transform: none; }
.tank-name .cap-kicker { font-size: .72rem; letter-spacing: .3em; text-transform: uppercase; color: var(--amber); }
.tank-name .cap-name { font-family: var(--font-display); font-variation-settings: var(--soft); font-style: italic; font-size: clamp(1.6rem, 4vw, 2.4rem);
  text-shadow: 0 0 18px rgba(255, 205, 120, .45), 0 2px 14px rgba(3, 1, 16, .8); }
.tank-name .stars { font-size: .9rem; margin-top: 2px; text-shadow: 0 0 10px rgba(255, 205, 120, .6); }

/* the end card */
.end-card { text-align: center; width: min(520px, 100%); gap: 16px; padding: 30px 26px 22px; box-shadow: 0 0 80px rgba(255, 205, 120, .18); }
.end-card h2 { font-size: clamp(2.6rem, 8vmin, 3.6rem); }
.end-card .row { justify-content: center; }
.end-kicker { font-size: .75rem; letter-spacing: .35em; text-transform: uppercase; color: var(--amber); }
.end-stats { display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; }
.end-stats div { display: grid; gap: 2px; padding: 10px 14px; min-width: 110px; border-radius: 12px; background: rgba(255, 255, 255, .05); border: 1px solid var(--line); }
.end-stats b { font-size: 1.5rem; color: var(--amber); font-variant-numeric: tabular-nums; }
.end-stats span { font-size: .8rem; color: var(--ink-dim); }
