/* Savage Science Tools — shared design tokens and site bar.
   Every page links this file. Tools map their own custom properties onto the
   --sst-* tokens below, so the whole site shifts together from one place. */
@import url('fonts.css');   /* vendored: works where fonts.googleapis.com is blocked */

:root {
  --sst-bg: oklch(0.16 0.03 255);
  --sst-bg-deep: oklch(0.14 0.03 255);
  --sst-panel: oklch(0.185 0.032 255);
  --sst-card: oklch(0.21 0.035 255);
  --sst-raised: oklch(0.245 0.038 255);
  --sst-input: oklch(0.15 0.03 255);
  --sst-line: oklch(0.26 0.035 255);
  --sst-line-strong: oklch(0.32 0.04 255);
  --sst-text: oklch(0.96 0.01 250);
  --sst-text-body: oklch(0.82 0.02 250);
  --sst-text-muted: oklch(0.66 0.03 255);
  --sst-blue: oklch(0.74 0.14 240);
  --sst-blue-btn: oklch(0.6 0.17 245);
  --sst-blue-soft: oklch(0.3 0.07 245);
  --sst-violet: oklch(0.74 0.13 295);
  --sst-violet-btn: oklch(0.52 0.17 295);
  --sst-violet-soft: oklch(0.3 0.08 295);
  /* Coral: the accent of the sister site, Savage Language Tools (languages/). */
  --sst-coral: oklch(0.76 0.13 32);
  --sst-coral-btn: oklch(0.6 0.17 32);
  --sst-coral-soft: oklch(0.3 0.07 32);
  --sst-green: oklch(0.78 0.14 155);
  --sst-amber: oklch(0.82 0.14 80);
  --sst-red: oklch(0.7 0.17 25);
  /* Subject hues, matching the homepage pills. */
  --sst-chem: oklch(0.8 0.11 185);
  --sst-phys: oklch(0.8 0.11 295);
  --sst-bio: oklch(0.8 0.12 145);
  --sst-geog: oklch(0.8 0.11 45);   /* Geography: terracotta, the colour of earth */
  /* Behind a canvas, scene or diagram (hex: three.js reads it), and the
     tinted backgrounds of right / caution / wrong feedback. */
  --sst-stage: #091321;
  --sst-good-bg: oklch(0.25 0.05 155);
  --sst-warn-bg: oklch(0.26 0.05 80);
  --sst-bad-bg: oklch(0.24 0.05 25);

  --sst-font: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* One typeface everywhere, counters included: no monospace faces (their dotted or
     slashed zero reads badly). --sst-mono is kept as an alias so older rules still resolve. */
  --sst-mono: var(--sst-font);
  --sst-bar-h: 52px;

  /* Presenter-mode type scale, for reading from the back of a classroom. It is
     measured against the viewport, like text on a PowerPoint slide: on a
     1920×1080 board, text is about 46px (24pt on a slide), labels 33px (18pt)
     and titles 65px. The vh term holds it on very wide screens and the px term
     sets a floor on small ones. Anything pupils read uses these. Controls
     only the teacher reads are exempt, and they use --sst-pr-control.
     Where there's too much text to fit at this size, split it into slides
     (.sst-deck, below). Never shrink the text to make it fit. */
  --sst-pr-title:   max(28px, min(3.4vw, 6vh));
  --sst-pr-text:    max(22px, min(2.4vw, 4.3vh));
  --sst-pr-label:   max(18px, min(1.7vw, 3vh));
  --sst-pr-figure:  max(32px, min(4.4vw, 7.8vh));
  --sst-pr-control: max(15px, min(1.1vw, 2vh));
}

/* ---------- Light theme ----------
   Dark is the default. Light is the viewer's choice from the Light / Dark
   button in the site bar (sst.js), remembered across the whole site. sst.js
   puts .theme-light or .theme-dark on both <html> and <body>: on <html> so a
   tool's own :root variables written as var(--sst-*) resolve to these values,
   and on <body> as Time of Flight first did. Anything a tool colours itself
   gets a .theme-light block after its :root block, and canvases or three.js
   scenes repaint on the 'sst-theme' event. Hex equivalents for canvas use are
   in CLAUDE.md. */
.theme-light {
  color-scheme: light;
  --sst-bg: oklch(0.968 0.006 250);
  --sst-bg-deep: oklch(0.945 0.009 250);
  --sst-panel: oklch(0.985 0.004 250);
  --sst-card: oklch(1 0 0);
  --sst-raised: oklch(0.95 0.008 250);
  --sst-input: oklch(1 0 0);
  --sst-line: oklch(0.89 0.012 250);
  --sst-line-strong: oklch(0.8 0.018 250);
  --sst-text: oklch(0.24 0.035 255);
  --sst-text-body: oklch(0.37 0.03 255);
  --sst-text-muted: oklch(0.5 0.028 255);
  --sst-blue: oklch(0.5 0.15 245);
  --sst-blue-btn: oklch(0.55 0.17 245);
  --sst-blue-soft: oklch(0.93 0.04 240);
  --sst-violet: oklch(0.5 0.16 295);
  --sst-violet-btn: oklch(0.52 0.17 295);
  --sst-violet-soft: oklch(0.93 0.04 295);
  --sst-coral: oklch(0.56 0.16 32);
  --sst-coral-btn: oklch(0.58 0.17 32);
  --sst-coral-soft: oklch(0.94 0.035 32);
  --sst-green: oklch(0.52 0.13 155);
  --sst-amber: oklch(0.53 0.12 70);
  --sst-red: oklch(0.55 0.19 25);
  --sst-chem: oklch(0.5 0.09 185);
  --sst-phys: oklch(0.5 0.15 295);
  --sst-bio: oklch(0.5 0.12 145);
  --sst-geog: oklch(0.52 0.13 45);
  --sst-stage: #f8fafd;
  --sst-good-bg: oklch(0.95 0.04 155);
  --sst-warn-bg: oklch(0.95 0.045 80);
  --sst-bad-bg: oklch(0.95 0.035 25);
}

/* Tailwind's font-mono and the browser's monospace defaults for code, kbd, pre and
   textarea all fall back to the page font. Tabular figures keep counters from jittering. */
.font-mono { font-family: var(--sst-font) !important; font-variant-numeric: tabular-nums; }
:where(code, kbd, samp, pre, textarea) { font-family: var(--sst-font); font-variant-numeric: tabular-nums; }

/* ---------- Site bar ---------- */
.sst-bar, .sst-bar * { box-sizing: border-box; }
.sst-bar {
  position: relative; z-index: 2147483000;
  display: flex; align-items: center; justify-content: flex-start; flex-wrap: nowrap; gap: 16px;
  /* Tools style bare header/nav elements and lay body out as flex or grid;
     pin everything that could leak in so the bar looks the same everywhere. */
  flex: none; align-self: stretch; width: 100%; max-width: none; margin: 0; box-shadow: none;
  text-align: left; grid-column: 1 / -1;
  height: var(--sst-bar-h); padding: 0 clamp(12px, 2.4vw, 24px);
  background: var(--sst-bg-deep); border-bottom: 1px solid var(--sst-line);
  color: var(--sst-text); font: 500 14px/1 var(--sst-font);
  -webkit-font-smoothing: antialiased; letter-spacing: normal; text-transform: none;
}
.sst-bar a { color: var(--sst-text); text-decoration: none; transition: color 150ms ease, box-shadow 150ms ease; }
.sst-bar a:hover { color: var(--sst-blue); }
.sst-bar a:focus-visible { outline: 2px solid var(--sst-blue); outline-offset: 2px; border-radius: 4px; }

.sst-brand { display: flex; align-items: center; gap: 10px; flex: none; }
.sst-atom { position: relative; width: 30px; height: 30px; flex: none; }
.sst-atom i { position: absolute; inset: 9px 1px; border: 1.5px solid var(--sst-blue); border-radius: 50%; }
.sst-atom i:nth-child(2) { transform: rotate(60deg); }
.sst-atom i:nth-child(3) { transform: rotate(-60deg); }
.sst-atom i:nth-child(4) { inset: 12.5px; border: 0; background: var(--sst-blue); }
.sst-word { display: flex; flex-direction: column; line-height: 1.05; letter-spacing: 0.08em; font-size: 12px; font-weight: 700; }
.sst-word span:last-child { font-weight: 500; color: var(--sst-blue); }

.sst-crumb {
  display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1;
  color: var(--sst-text-body); font-size: 14px; font-weight: 600;
}
.sst-crumb::before { content: ""; width: 1px; height: 22px; background: var(--sst-line-strong); flex: none; }
.sst-crumb span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.sst-kind {
  flex: none; font-size: 11px; font-weight: 600; padding: 4px 9px; border-radius: 999px;
  background: var(--sst-blue-soft); color: oklch(0.88 0.08 240);
}
.sst-kind--play { background: var(--sst-violet-soft); color: oklch(0.88 0.08 295); }
.theme-light .sst-kind { color: var(--sst-blue); }
.theme-light .sst-kind--play { color: var(--sst-violet); }
.theme-light .sst-bar--lang .sst-kind { color: var(--sst-coral); }

/* Light / Dark: the last item in the bar, kept on phones as an icon. */
.sst-bar .sst-theme-nav {
  display: flex; align-items: center; gap: 6px; height: var(--sst-bar-h); padding: 0 12px; border: 0; background: none;
  color: var(--sst-text); font: inherit; cursor: pointer;
}
.sst-theme-icon { display: inline-flex; font-style: normal; flex: none; }
.sst-theme-icon svg { width: 1.15em; height: 1.15em; }
.sst-bar .sst-theme-icon svg { width: 16px; height: 16px; }
.sst-bar .sst-theme-nav:hover { color: var(--sst-blue); box-shadow: inset 0 -2px 0 var(--sst-blue); }
.sst-bar .sst-theme-nav:focus-visible { outline: 2px solid var(--sst-blue); outline-offset: -2px; border-radius: 4px; }
.sst-bar--lang .sst-theme-nav:hover { color: var(--sst-coral); box-shadow: inset 0 -2px 0 var(--sst-coral); }

.sst-nav { display: flex; align-items: center; gap: 2px; flex: none; margin-left: auto; }
.sst-nav a { display: flex; align-items: center; height: var(--sst-bar-h); padding: 0 12px; }
.sst-nav a:hover { box-shadow: inset 0 -2px 0 var(--sst-blue); }

/* Savage Language Tools: the same bar, coral where science is blue, with two
   speech bubbles for the atom. */
.sst-bubbles { width: 30px; height: 30px; flex: none; overflow: visible; }
.sst-bubbles path:first-child { fill: none; stroke: var(--sst-coral); stroke-width: 1.5; stroke-linejoin: round; }
.sst-bubbles path:last-child { fill: var(--sst-coral); stroke: var(--sst-bg-deep); stroke-width: 2; stroke-linejoin: round; }
.sst-bar--lang .sst-word span:last-child { color: var(--sst-coral); }
.sst-bar--lang a:hover { color: var(--sst-coral); }
.sst-bar--lang a:focus-visible { outline-color: var(--sst-coral); }
.sst-bar--lang .sst-nav a:hover { box-shadow: inset 0 -2px 0 var(--sst-coral); }
.sst-bar--lang .sst-kind { background: var(--sst-coral-soft); color: oklch(0.88 0.07 32); }

@media (max-width: 720px) {
  .sst-word, .sst-kind { display: none; }
  .sst-nav a:not(.sst-keep) { display: none; }
  .sst-nav a { padding: 0 9px; }
  .sst-bar .sst-theme-nav { padding: 0 9px; }
  .sst-bar .sst-theme-nav span { display: none; }
}
@media print { .sst-bar { display: none; } }

/* Presenter mode: tools that go full screen hide the bar with it. */
:fullscreen .sst-bar { display: none; }
body.presenting .sst-bar { display: none; }

/* ---------- Presenter slides ----------
   A deck of slides for presenter mode, wired up by present.js:
     <div class="sst-deck"><section class="sst-slide"><h3>…</h3><p>…</p></section>…</div>
   One slide shows at a time, at the --sst-pr-* sizes. Next and Back sit
   under it, and → / PageDown / ← / PageUp (what a presentation clicker sends)
   turn the page. .sst-deck--strip is a caption band under a model: a short
   heading and a line or two. A full-size deck takes a whole panel. */
.sst-deck {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  color: var(--sst-text); font-family: var(--sst-font);
}
.sst-deck > .sst-slides { flex: 1 1 auto; min-height: 0; overflow: auto; overflow-wrap: break-word; }
.sst-deck:not(.sst-deck--pr) .sst-slide:not(.is-on), body.presenting .sst-deck--pr .sst-slide:not(.is-on) { display: none; }
/* Slide typography, for decks written for the board (not --pr decks, which keep the tool's styles). */
.sst-deck:not(.sst-deck--pr) .sst-slide { font-size: var(--sst-pr-text); line-height: 1.3; }
.sst-deck:not(.sst-deck--pr) .sst-slide > :first-child { margin-top: 0; }
.sst-deck:not(.sst-deck--pr) .sst-slide > :last-child { margin-bottom: 0; }
.sst-deck:not(.sst-deck--pr) .sst-slide h3 { font-size: var(--sst-pr-title); line-height: 1.1; letter-spacing: -.01em; margin: 0 0 .4em; font-weight: 800; }
.sst-deck:not(.sst-deck--pr) .sst-slide p, .sst-deck:not(.sst-deck--pr) .sst-slide li { margin: .3em 0; color: var(--sst-text-body); }
.sst-deck:not(.sst-deck--pr) .sst-slide ul, .sst-deck:not(.sst-deck--pr) .sst-slide ol { margin: .2em 0; padding-left: 1.2em; }
.sst-deck:not(.sst-deck--pr) .sst-slide b, .sst-deck:not(.sst-deck--pr) .sst-slide strong { color: var(--sst-text); }
.sst-deck:not(.sst-deck--pr) .sst-slide .sst-kicker { display: block; font-size: var(--sst-pr-label); font-weight: 700; color: var(--sst-blue); letter-spacing: .02em; margin-bottom: .15em; }
.sst-deck:not(.sst-deck--pr) .sst-slide .sst-small { font-size: var(--sst-pr-label); }
.sst-deck:not(.sst-deck--pr) .sst-slide table { border-collapse: collapse; font-size: var(--sst-pr-label); }
.sst-deck:not(.sst-deck--pr) .sst-slide th, .sst-deck:not(.sst-deck--pr) .sst-slide td { padding: .25em .6em; border-bottom: 1px solid var(--sst-line); text-align: left; vertical-align: top; }

.sst-deck-nav {
  flex: none; display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  padding-top: 10px; font-size: var(--sst-pr-control);
}
.sst-deck-nav button {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font: 600 1em/1 var(--sst-font);
  padding: .5em .9em; border-radius: 9px; border: 1px solid var(--sst-line-strong); background: var(--sst-card); color: var(--sst-text);
}
.sst-deck-nav button:hover:not(:disabled) { border-color: var(--sst-text-muted); }
.sst-deck-nav button:disabled { opacity: .4; cursor: default; }
.sst-deck-nav button:focus-visible { outline: 3px solid var(--sst-blue); outline-offset: 2px; }
.sst-deck-count { color: var(--sst-text-muted); font-variant-numeric: tabular-nums; min-width: 3.2em; text-align: center; }
.sst-deck-dots { display: flex; gap: 6px; margin-right: auto; }
.sst-deck-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--sst-line-strong); }
.sst-deck-dots i.is-on { background: var(--sst-blue); }
.sst-deck[data-count="1"] .sst-deck-nav { display: none; }

/* .sst-deck--pr: an ordinary page section that becomes slides only in
   presenter mode. Outside it the deck, its slides and its nav drop out of the
   layout (display: contents) and every slide shows, so the page reads as
   before. Slides marked .sst-pr-slide, written only for the board, are hidden. Its slides keep the
   tool's own styles: the tool sizes them for presenting with the tokens. */
body:not(.presenting) .sst-deck--pr, body:not(.presenting) .sst-deck--pr > .sst-slides { display: contents; }
body:not(.presenting) .sst-deck--pr .sst-pr-slide, body:not(.presenting) .sst-deck--pr > .sst-deck-nav { display: none; }

/* Caption band under a model: a small heading over a line or two of text. */
.sst-deck.sst-deck--strip { flex-direction: row; align-items: stretch; gap: 16px; }
/* Room for a heading and two lines, so the model above doesn't jump as the slides change. */
.sst-deck.sst-deck--strip > .sst-slides { height: calc(var(--sst-pr-label) * 1.35 + var(--sst-pr-text) * 2.6); }
.sst-deck.sst-deck--strip .sst-slide h3 { font-size: var(--sst-pr-label); line-height: 1.25; margin: 0 0 .1em; color: var(--sst-blue); }
.sst-deck.sst-deck--strip .sst-slide p { margin: 0; }
.sst-deck.sst-deck--strip .sst-deck-nav { flex-direction: column-reverse; justify-content: center; padding-top: 0; }
.sst-deck.sst-deck--strip .sst-deck-dots { display: none; }

/* ---------- Annotation layer (annotate.js) ----------
   Drawn over everything, presenter overlays included. The toolbar keeps the
   site's dark surface in every theme so the swatches read the same. */
.sst-ink { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 2147483640; pointer-events: none; touch-action: none; }
body.sst-inking .sst-ink { pointer-events: auto; cursor: crosshair; }
body.sst-inking.sst-ink-erase .sst-ink { cursor: cell; }
.sst-inkbar {
  position: fixed; left: 0; right: 0; bottom: 16px; width: max-content; max-width: calc(100vw - 24px); margin: 0 auto;
  z-index: 2147483646; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px;
  padding: 6px; background: #0d1928; border: 1px solid #2c3d52; border-radius: 14px; color: #edf2f8; font: 600 11px/1.2 var(--sst-font);
}
.sst-inkbar[hidden], .sst-ink-fab[hidden] { display: none; }
.sst-inkbar button {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px; min-width: 54px; padding: 5px 6px;
  border: 1px solid transparent; border-radius: 9px; background: none; color: #edf2f8; cursor: pointer; font: inherit;
}
.sst-inkbar button svg { width: 20px; height: 20px; }
.sst-inkbar button:hover { background: #182535; }
.sst-inkbar button[aria-pressed="true"] { background: #13324d; border-color: #47b5fa; }
.sst-ink-sep { width: 1px; align-self: stretch; margin: 4px; background: #2c3d52; }
.sst-ink-sw { display: flex; gap: 4px; }
.sst-inkbar .sst-ink-sw button { min-width: 0; width: 28px; height: 28px; padding: 0; border-radius: 50%; border: 2px solid #2c3d52; }
.sst-inkbar .sst-ink-sw button[aria-pressed="true"] { border-color: #fff; box-shadow: 0 0 0 2px #0d1928 inset; background-clip: padding-box; }
.sst-ink-pick input { width: 32px; height: 32px; padding: 0; border: 0; background: none; cursor: pointer; }
.sst-ink-size input { width: 90px; accent-color: #47b5fa; }
.sst-inkbar button:focus-visible, .sst-ink-fab:focus-visible, .sst-ink-nav:focus-visible { outline: 2px solid #47b5fa; outline-offset: 2px; }
@media (max-width: 640px) { .sst-inkbar button span { display: none; } .sst-inkbar button { min-width: 38px; } .sst-ink-size input { width: 64px; } }
/* Stand-in for the site bar's Annotate button when the bar is hidden. */
.sst-ink-fab {
  position: fixed; left: 14px; bottom: 14px; z-index: 2147483645; width: 46px; height: 46px; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid #2c3d52; background: #0d1928; color: #edf2f8; cursor: pointer; padding: 0;
}
.sst-ink-fab svg { width: 22px; height: 22px; }
.sst-ink-fab:hover, .sst-ink-fab.is-on { border-color: #47b5fa; }
.sst-ink-fab.is-on { background: #13324d; }
.sst-bar .sst-ink-nav {
  display: flex; align-items: center; gap: 6px; height: var(--sst-bar-h); padding: 0 12px; border: 0; background: none;
  color: var(--sst-text); font: inherit; cursor: pointer;
}
.sst-bar .sst-ink-nav svg { width: 16px; height: 16px; }
.sst-bar .sst-ink-nav:hover, .sst-bar .sst-ink-nav.is-on { color: var(--sst-blue); box-shadow: inset 0 -2px 0 var(--sst-blue); }
@media (max-width: 720px) { .sst-bar .sst-ink-nav { display: none; } }
@media print { .sst-ink, .sst-inkbar, .sst-ink-fab { display: none !important; } }

/* ---------- Shared presenter mode (presenter.js) ----------
   The tool's model, controls and notes are pinned over the board; the rest
   of the page is hidden, not moved, so the app underneath keeps working. */
body.sst-pres { overflow: hidden !important; visibility: hidden; }
body.sst-pres .sst-pres-pin, .sst-pres-top, .sst-pres-deck, .sst-ink, .sst-inkbar, .sst-ink-fab { visibility: visible; }
body.sst-pres .sst-pres-off { display: none !important; }
.sst-pres-top[hidden], .sst-pres-deck[hidden], .sst-pres-deck:not(.has-slides) { display: none !important; }
.sst-pres-top {
  position: fixed; top: 0; left: 0; right: 0; z-index: 2147482600; box-sizing: border-box;
  display: flex; align-items: center; gap: 12px; padding: 8px clamp(12px, 2vw, 24px);
  background: var(--sst-bg-deep); border-bottom: 1px solid var(--sst-line); color: var(--sst-text);
  font: 500 var(--sst-pr-control)/1.2 var(--sst-font);
}
.sst-pres-title { flex: 1; min-width: 0; font-weight: 700; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.sst-pres-keys { color: var(--sst-text-muted); white-space: nowrap; }
@media (max-width: 900px) { .sst-pres-keys { display: none; } }
.sst-pres-top button {
  font: 600 1em/1 var(--sst-font); padding: .5em .9em; border-radius: 9px; cursor: pointer;
  border: 1px solid var(--sst-line-strong); background: var(--sst-card); color: var(--sst-text);
}
.sst-pres-top button:hover { border-color: var(--sst-text-muted); }
.sst-pres-top .sst-theme-btn { display: inline-flex; align-items: center; gap: .45em; }
.sst-pres-top button:focus-visible { outline: 3px solid var(--sst-blue); outline-offset: 2px; }
.sst-pres-deck {
  position: fixed; z-index: 2147482600; box-sizing: border-box;
  background: var(--sst-panel); border: 1px solid var(--sst-line); border-radius: 12px; padding: 10px 14px 12px 20px;
}
/* A pinned card grows the part that holds its canvas to fill the board. */
body.sst-pres .sst-pres-pin:has(> * canvas) { display: flex !important; flex-direction: column; }
body.sst-pres .sst-pres-pin > :has(canvas) { flex: 1 1 auto; min-height: 0; height: auto !important; max-height: none !important; }
