/* rbook — a notebook for R that never leaves the browser
   A lab notebook: warm grained paper (graphite at night), one loud typeface (Bricolage Grotesque,
   self-hosted), mono code. Persimmon is kept for one meaning, "run"; everything else is ink.
   Cells sit in a soft bezel tray instead of a bare hairline box.
   Motion follows transitions.dev: short, eased out, and always with a reduced-motion twin. */

/* ── fonts ──────────────────────────────────────────────────────────── */

@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/bricolage-grotesque-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/bricolage-grotesque-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── tokens ─────────────────────────────────────────────────────────── */

:root {
  color-scheme: light;

  --font-ui: "Bricolage Grotesque", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-prose: var(--font-ui);
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --fs-xs: 0.75rem;      /* 12 */
  --fs-sm: 0.8125rem;    /* 13 */
  --fs-md: 0.875rem;     /* 14 */
  --fs-lg: 1.0625rem;    /* 17 */
  --fs-prose: 0.96875rem;/* 15.5 */
  --fs-code: 0.8125rem;  /* 13 */
  --fs-out: 0.78125rem;  /* 12.5 */

  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-swap: cubic-bezier(0.2, 0, 0, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  /* durations read by ui.js to time removal after the exit transition */
  --dropdown-open-dur: 150ms;
  --dropdown-close-dur: 150ms;
  --modal-open-dur: 200ms;
  --modal-close-dur: 150ms;
  --toast-open: 300ms;
  --toast-close: 250ms;

  --r-sm: 7px;
  --r-md: 10px;
  --r-lg: 14px;

  --rail-w: 256px;
  --gutter: 34px;
  --status-h: 32px;

  --z-bar: 20;
  --z-menu: 60;
  --z-tip: 100;
  --z-scrim: 110;
  --z-rail: 120;
  --z-drop: 150;
  --z-toast: 200;

  /* Every text colour below was measured against --surface, --bg, --bg-sunken and --output-bg (WCAG 2.2 AA). */
  --bg: #f4f0e8;
  --bg-sunken: #ece7dc;
  --surface: #fffdf9;
  --surface-2: #f3eee4;
  --output-bg: #f8f5ef;
  --ink: #1c1915;
  --ink-soft: #3d3832;
  --muted: #5e574e;
  --faint: #6e675d;
  --line: #e4ddd0;
  --line-strong: #d3cab9;
  --edge: #8f877a;
  --hover: rgb(28 25 21 / 0.055);
  --scrim: rgb(28 22 16 / 0.34);
  --dot: rgb(28 25 21 / 0.09);          /* the canvas's dot grid */
  --tray: rgb(60 44 24 / 0.045);        /* the bezel a code cell sits in */
  --tray-line: rgb(60 44 24 / 0.07);
  --highlight: rgb(255 255 255 / 0.9);  /* top inner edge of raised surfaces */
  --grain-opacity: 0.05;

  --accent: #a8543a;
  --accent-ink: #8a4630;
  --on-accent: #ffffff;
  --accent-soft: rgb(168 84 58 / 0.08);
  --accent-ring: rgb(168 84 58 / 0.24);
  --ok: #2f6b45;
  --warn: #8a5a0f;
  --warn-soft: #fbf3e2;
  --err: #b0261b;
  --err-soft: #fcefea;
  --on-err: #ffffff;

  /* the secondary "ink" button (Share) */
  --solid: #1c1915;
  --solid-hover: #38322b;
  --on-solid: #fffdf9;

  --toast-bg: #1f1b17;
  --toast-ink: #f5f0e7;

  --syn-comment: #7a7064;
  --syn-string: #3b7535;
  --syn-number: #b04f16;
  --syn-keyword: #9c2c6c;
  --syn-const: #1d6b75;
  --syn-fn: #1c1915;

  --shadow-cell: 0 1px 2px rgb(60 40 20 / 0.05), 0 8px 20px -12px rgb(60 40 20 / 0.16);
  --shadow-pop: 0 1px 2px rgb(60 40 20 / 0.06), 0 8px 24px -6px rgb(60 40 20 / 0.14), 0 24px 48px -24px rgb(60 40 20 / 0.2);
  --shadow-chip: 0 1px 2px rgb(60 40 20 / 0.08), 0 4px 10px -4px rgb(60 40 20 / 0.14);
  --shadow-toast: 0 2px 6px rgb(0 0 0 / 0.18), 0 12px 32px -8px rgb(0 0 0 / 0.32);
}

html[data-theme="dark"] {
  color-scheme: dark;

  --bg: #12110f;
  --bg-sunken: #0e0d0b;
  --surface: #1c1a17;
  --surface-2: #25221e;
  --output-bg: #181613;
  --ink: #f0ebe2;
  --ink-soft: #cec7bb;
  --muted: #a39b8e;
  --faint: #8d8579;
  --line: #2b2723;
  --line-strong: #3e3934;
  --edge: #6f685e;
  --hover: rgb(255 245 230 / 0.06);
  --scrim: rgb(0 0 0 / 0.58);
  --dot: rgb(255 245 230 / 0.055);
  --tray: rgb(255 245 230 / 0.03);
  --tray-line: rgb(255 245 230 / 0.05);
  --highlight: rgb(255 245 230 / 0.06);
  --grain-opacity: 0.07;

  --accent: #d4906f;
  --accent-ink: #e6ab90;
  --on-accent: #1d0d05;
  --accent-soft: rgb(212 144 111 / 0.1);
  --accent-ring: rgb(212 144 111 / 0.3);
  --ok: #74c98f;
  --warn: #e0b35a;
  --warn-soft: #231c0f;
  --err: #ff9d8f;
  --err-soft: #261310;
  --on-err: #2a0e0b;

  --solid: #f0ebe2;
  --solid-hover: #ffffff;
  --on-solid: #1c1a17;

  --toast-bg: #f3eee4;
  --toast-ink: #1c1915;

  --syn-comment: #958c7f;
  --syn-string: #a8cc82;
  --syn-number: #f2a56b;
  --syn-keyword: #ea8fc3;
  --syn-const: #72c6cf;
  --syn-fn: #f0ebe2;

  --shadow-cell: 0 1px 2px rgb(0 0 0 / 0.4), 0 10px 24px -14px rgb(0 0 0 / 0.7);
  --shadow-pop: 0 1px 2px rgb(0 0 0 / 0.5), 0 12px 32px -8px rgb(0 0 0 / 0.6);
  --shadow-chip: 0 1px 2px rgb(0 0 0 / 0.5), 0 4px 10px -4px rgb(0 0 0 / 0.6);
}

/* ── base ───────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html {
  height: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 var(--fs-md)/1.5 var(--font-ui);
  text-rendering: optimizeLegibility;
  overscroll-behavior: none;
}

/* Paper grain: one fixed layer over the whole app, so nothing that scrolls has to repaint it.
   Dialogs live in the top layer, above it, and stay clean. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: var(--z-toast);
  pointer-events: none;
  opacity: var(--grain-opacity);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.4 0 0 0 0 0.3 0 0 0 1.4 -0.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (forced-colors: active) { body::after { display: none; } }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

svg.ic {
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
button:disabled { cursor: default; }
input, textarea { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

::selection { background: var(--accent-ring); }

.skip {
  position: fixed;
  top: 8px;
  inset-inline-start: 8px;
  z-index: var(--z-toast);
  padding: 8px 12px;
  border-radius: var(--r-sm);
  background: var(--ink);
  color: var(--bg);
  font-size: var(--fs-sm);
  font-weight: 500;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

.noscript { margin: 24px; color: var(--ink-soft); }

/* ── app frame ──────────────────────────────────────────────────────── */

.app {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  height: 100dvh;
  overflow: hidden;
}
.app.rail-hidden { grid-template-columns: minmax(0, 1fr); }
.app.rail-hidden .rail { display: none; }

.main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--bg);
}
.main:focus { outline: none; }

/* ── rail ───────────────────────────────────────────────────────────── */

.rail {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg-sunken);
  border-inline-end: 1px solid var(--line);
  padding: 12px 10px 10px max(10px, env(safe-area-inset-left));
}

.rail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 2px 10px 4px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--ink);
  border-radius: var(--r-sm);
}

.brand-mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: linear-gradient(160deg, color-mix(in srgb, var(--accent) 88%, #fff) 0%, var(--accent) 60%);
  color: #fff;
  font: 800 1rem/1 var(--font-ui);
  letter-spacing: -0.03em;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.35), inset 0 -1px 0 rgb(0 0 0 / 0.12), 0 1px 2px rgb(90 40 20 / 0.2), 0 3px 8px -4px rgb(168 84 58 / 0.35);
  transform: rotate(-4deg);
}

.brand-name {
  font-size: 1.125rem;
  font-weight: 750;
  letter-spacing: -0.04em;
}

.rail-actions { padding: 0 2px 8px; }

.btn-new { width: 100%; justify-content: flex-start; }

.rail-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 2px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  scrollbar-width: thin;
}

.nb-item {
  position: relative;
  display: block;
  width: 100%;
  text-align: start;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  transition: background-color 120ms ease-out;
}
.nb-item[aria-current="page"] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 0 0 1px var(--line), inset 0 1px 0 var(--highlight), 0 1px 2px rgb(60 40 20 / 0.06);
}
.nb-item[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset-block: 10px;
  inset-inline-start: 0;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}
.nb-item-title {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 560;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nb-item-meta {
  display: block;
  margin-top: 1px;
  font-size: var(--fs-xs);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nb-item[aria-current="page"] .nb-item-meta { color: var(--muted); }

.rail-foot {
  border-top: 1px solid var(--line);
  padding: 8px 2px 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.rail-link {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--muted);
  transition: color 120ms ease-out, background-color 120ms ease-out;
}
.rail-link .ic { width: 14px; height: 14px; }

.rail-note {
  margin: 0;
  padding: 0 8px 4px;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--faint);
  text-wrap: balance;
}

.rail-scrim { display: none; }

/* ── top bar ────────────────────────────────────────────────────────── */

.topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 56px;
  padding: 0 max(12px, env(safe-area-inset-right)) 0 max(16px, env(safe-area-inset-left));
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  position: relative;
  z-index: var(--z-bar);
  flex: none;
}

.title-wrap { flex: 1; min-width: 0; }

.nb-title {
  display: block;
  width: 100%;
  max-width: 440px;
  min-width: 0;
  margin-inline-start: -8px;
  padding: 5px 8px;
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  font-size: var(--fs-lg);
  font-weight: 650;
  letter-spacing: -0.02em;
  text-overflow: ellipsis;
  transition: background-color 120ms ease-out;
}
.nb-title:focus { background: var(--surface); outline: 2px solid var(--accent); outline-offset: 0; }

.topbar-actions { display: flex; align-items: center; gap: 6px; flex: none; }
.topbar-actions .icon-btn:last-child { margin-inline-start: 2px; }

/* ── buttons ────────────────────────────────────────────────────────── */

.icon-btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: var(--muted);
  transition: color 120ms ease-out, background-color 120ms ease-out, scale 150ms ease-out;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 32px;
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: var(--fs-sm);
  font-weight: 560;
  letter-spacing: -0.005em;
  white-space: nowrap;
  transition: color 120ms ease-out, background-color 120ms ease-out, border-color 120ms ease-out, scale 150ms ease-out;
}
.btn .ic { width: 15px; height: 15px; }

.btn-quiet { color: var(--ink-soft); border-color: var(--line-strong); background: var(--surface); }
.btn-quiet .ic { color: var(--muted); }
.btn-plain { color: var(--ink-soft); border-color: var(--line-strong); background: var(--surface); }
.btn-new { color: var(--ink); border-color: var(--line-strong); background: var(--surface); }
.btn-new .ic { color: var(--muted); }

/* Two filled buttons, two meanings: persimmon runs code, ink sends the notebook somewhere. */
.btn-accent {
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.22), 0 1px 2px rgb(90 40 20 / 0.16);
}
.btn-accent .ic { color: inherit; }
.btn-share {
  background: var(--solid);
  color: var(--on-solid);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.12), 0 1px 2px rgb(0 0 0 / 0.16);
}
.btn-share .ic { color: inherit; }
.btn-danger { background: var(--err); color: var(--on-err); }

.btn[aria-disabled="true"], .btn:disabled { opacity: 0.55; }

/* A pressed control gives way a little (never the disabled ones). The scale is gated below with the other
   movement; reduced motion gets a dimmer press instead. */

.only-narrow { display: none; }
.app.rail-hidden .only-narrow { display: grid; }

/* ── icon and text swaps (transitions.dev) ──────────────────────────── */

.t-icon-swap {
  display: grid;
  width: 16px;
  height: 16px;
}
.t-icon-swap > .ic {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  transition: opacity 300ms var(--ease-swap);
}
.t-icon-swap[data-state="a"] > .ic-b,
.t-icon-swap[data-state="b"] > .ic-a { opacity: 0; }

.t-text-swap { display: inline-grid; }
.t-text-swap > span {
  grid-area: 1 / 1;
  transition: opacity 300ms var(--ease-swap);
}
.t-text-swap[data-state="a"] > .swap-b,
.t-text-swap[data-state="b"] > .swap-a { opacity: 0; }

/* ── canvas ─────────────────────────────────────────────────────────── */

.canvas {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-behavior: smooth;
  padding: 0 max(24px, env(safe-area-inset-right)) 0 max(24px, env(safe-area-inset-left));
  /* graph-paper dots; `local` so they travel with the notebook rather than sliding under it */
  background: radial-gradient(circle at 1px 1px, var(--dot) 1px, transparent 1.2px) 0 0 / 22px 22px local;
}

.notebook {
  width: 100%;
  max-width: 812px;
  margin: 0 auto;
  padding: 34px 0 6px;
}

.add-row {
  display: flex;
  gap: 8px;
  width: 100%;
  max-width: 812px;
  margin: 0 auto;
  padding: 0 0 96px calc(var(--gutter) + 10px);
}

.add-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 11px;
  border-radius: 999px;
  border: 1px dashed var(--edge);
  background: var(--bg);
  color: var(--muted);
  font-size: var(--fs-sm);
  font-weight: 560;
  transition: color 120ms ease-out, border-color 120ms ease-out, background-color 120ms ease-out, scale 150ms ease-out;
}
.add-btn .ic { width: 13px; height: 13px; }

/* ── cell ───────────────────────────────────────────────────────────── */

.cell {
  position: relative;
  display: grid;
  grid-template-columns: var(--gutter) minmax(0, 1fr);
  column-gap: 10px;
  padding-bottom: 18px;
}

.cell-gutter {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding-top: 8px;
}

.run-btn {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--muted);
  box-shadow: inset 0 1px 0 var(--highlight), 0 1px 2px rgb(60 40 20 / 0.06);
  transition: color 120ms ease-out, border-color 120ms ease-out, background-color 120ms ease-out, box-shadow 160ms ease-out, scale 150ms ease-out;
}
.run-btn .ic { width: 11px; height: 11px; margin-inline-start: 1px; }
/* The focused cell's run button turns into the same persimmon as Run all: this is what ⌘↵ will run. */
.cell:focus-within .run-btn,
.cell[data-run="running"] .run-btn {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.22), 0 0 0 4px var(--accent-soft);
}
.cell[data-run="running"] .run-btn .ic { margin: 0; }
.cell[data-run="queued"] .run-btn,
.cell[data-run="waiting"] .run-btn { opacity: 0.55; cursor: default; }

.cell-count {
  min-height: 1.2em;
  font: 400 var(--fs-xs)/1.2 var(--font-mono);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.cell.is-error .cell-count { color: var(--err); }

.cell-body { min-width: 0; position: relative; }

/* code cells */

/* The bezel: the cell is a sheet resting in a faint tray (two outer rings), lit from above
   (inner top highlight), with a soft diffused shadow. All box-shadow, so the layout does not move. */
.cell[data-type="code"] .cell-body {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: 0 0 0 4px var(--tray), 0 0 0 5px var(--tray-line), inset 0 1px 0 var(--highlight), var(--shadow-cell);
  transition: border-color 160ms var(--ease-out), box-shadow 160ms var(--ease-out);
}
.cell[data-type="code"] .cell-body:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft), 0 0 0 5px color-mix(in srgb, var(--accent) 14%, transparent), inset 0 1px 0 var(--highlight), var(--shadow-cell);
}
.cell[data-run="running"] .cell-body { border-color: var(--accent-ring); }

/* Running: a persimmon light travels along the cell's top edge. Static bar under reduced motion. */
.cell[data-type="code"] .cell-body::before {
  content: "";
  position: absolute;
  inset: -1px -1px auto;
  height: 2px;
  border-radius: var(--r-md) var(--r-md) 0 0;
  background: linear-gradient(90deg, transparent, var(--accent) 50%, transparent) 0 0 / 40% 100% no-repeat;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity 200ms ease-out;
}
.cell[data-run="running"] .cell-body::before { opacity: 1; }

/* The highlighted <pre> is in flow and sets the cell's height; the textarea lies on top of it.
   Same font, padding and wrapping on both, so the two always line up and no JS measures anything. */
.editor {
  position: relative;
  border-radius: calc(var(--r-md) - 1px);
}

.editor pre,
.editor textarea {
  margin: 0;
  padding: 11px 13px 12px;
  border: 0;
  font: 400 var(--code-size, var(--fs-code))/1.62 var(--font-mono);
  letter-spacing: 0;
  tab-size: 2;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  word-break: normal;
  font-variant-ligatures: none;
}

.editor pre {
  position: relative;
  min-height: calc(1.62em + 23px);
  pointer-events: none;
  color: var(--ink);
  overflow: hidden;
}
/* <code> would otherwise fall back to the UA monospace size and drift from the textarea */
.editor pre code { font: inherit; letter-spacing: inherit; }

.editor textarea {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  resize: none;
  overflow: hidden;
  background: transparent;
  color: transparent;
  caret-color: var(--accent);
  outline: none;
  z-index: 1;
}
.editor textarea::selection { background: var(--accent-ring); }
.editor textarea::placeholder { color: var(--faint); }

.tok-com { color: var(--syn-comment); font-style: italic; }
.tok-str { color: var(--syn-string); }
.tok-num { color: var(--syn-number); }
.tok-kw  { color: var(--syn-keyword); }
.tok-con { color: var(--syn-const); }
.tok-fn  { color: var(--syn-fn); }
.tok-op  { color: var(--muted); }

/* text cells */

.cell[data-type="markdown"] .cell-body {
  border: 1px solid transparent;
  border-radius: var(--r-md);
  padding: 2px 13px;
  transition: border-color 140ms ease-out, background-color 140ms ease-out;
}
.cell[data-type="markdown"].is-editing .cell-body {
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.md-view {
  font-family: var(--font-prose);
  font-size: var(--fs-prose);
  line-height: 1.62;
  color: var(--ink-soft);
  padding: 6px 0;
  cursor: text;
  overflow-wrap: break-word;
}
.md-view:empty { min-height: 2em; }
.md-view:empty::before { content: attr(data-empty); color: var(--faint); }
.md-view > :first-child { margin-top: 0; }
.md-view > :last-child { margin-bottom: 0; }
.md-view p { margin: 0 0 0.75em; text-wrap: pretty; }
.md-view p, .md-view ul, .md-view ol, .md-view blockquote { max-width: 72ch; }
.md-view h1, .md-view h2, .md-view h3 {
  color: var(--ink);
  line-height: 1.15;
  margin: 1.2em 0 0.45em;
  font-weight: 700;
  text-wrap: balance;
}
.md-view h1 { font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.25rem); font-weight: 780; letter-spacing: -0.045em; line-height: 1.05; margin-top: 0.3em; }
.md-view h2 { font-size: 1.3rem; font-weight: 740; letter-spacing: -0.03em; }
/* a short persimmon rule under the notebook's opening heading, like an underlined title in a lab book */
.md-view h1::after {
  content: "";
  display: block;
  width: 2.25rem;
  height: 3px;
  margin-top: 0.4em;
  border-radius: 3px;
  background: var(--accent);
}
.md-view h3 { font-size: 1rem; letter-spacing: -0.012em; }
.md-view strong { color: var(--ink); font-weight: 650; }
.md-view a { color: var(--accent-ink); text-decoration-color: var(--accent-ring); text-decoration-thickness: from-font; text-underline-offset: 0.18em; }
.md-view code {
  font: 400 0.87em/1.4 var(--font-mono);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  padding: 0.1em 0.34em;
  color: var(--ink);
}
.md-view pre {
  background: var(--output-bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  overflow-x: auto;
  margin: 0 0 0.8em;
}
.md-view pre code { background: none; border: 0; padding: 0; font-size: var(--fs-out); }
.md-view ul, .md-view ol { margin: 0 0 0.75em; padding-inline-start: 1.3em; }
.md-view li { margin: 0.2em 0; }
.md-view li::marker { color: var(--faint); }
.md-view .task { display: inline-block; width: 1.2em; margin-inline-start: -1.3em; }
.md-view blockquote {
  margin: 0 0 0.8em;
  padding: 0.1em 0 0.1em 0.9em;
  border-inline-start: 2px solid var(--line-strong);
  color: var(--muted);
}
.md-view hr { border: 0; border-top: 1px solid var(--line); margin: 1.3em 0; }
.md-view table { border-collapse: collapse; width: 100%; font-size: var(--fs-sm); margin: 0 0 0.9em; display: block; overflow-x: auto; }
.md-view th, .md-view td { border-bottom: 1px solid var(--line); padding: 5px 10px 5px 0; text-align: start; }
.md-view th { font-weight: 650; color: var(--ink); }
.md-view img { max-width: 100%; height: auto; border-radius: var(--r-sm); }
.md-view .math-display { display: block; margin: 0 0 0.8em; overflow-x: auto; overflow-y: hidden; }
.md-view .math-display .katex-display { margin: 0; }
.md-view .katex { font-size: 1.12em; color: var(--ink); }
.md-view .katex-error { color: var(--err) !important; }

/* Auto-growing textarea: an invisible copy of the text (::after) sizes the grid cell the textarea fills. */
.md-edit { display: none; min-height: 3.4em; }
.cell.is-editing .md-edit { display: grid; }
.cell.is-editing .md-view { display: none; }
.md-edit::after,
.md-edit textarea {
  grid-area: 1 / 1;
  margin: 0;
  padding: 6px 0;
  border: 0;
  font: 400 var(--code-size, var(--fs-code))/1.66 var(--font-mono);
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
.md-edit::after { content: attr(data-value) " "; visibility: hidden; pointer-events: none; }
.md-edit textarea {
  width: 100%;
  min-width: 0;
  resize: none;
  overflow: hidden;
  background: none;
  outline: none;
  color: var(--ink);
  caret-color: var(--accent);
}
.md-edit textarea::placeholder { color: var(--faint); }

/* cell tools: a chip that floats on the cell's top edge */

.cell-tools {
  position: absolute;
  top: -14px;
  inset-inline-end: 10px;
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 2px;
  border-radius: 9px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-chip);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease-out;
  z-index: 5;
}
.cell:focus-within .cell-tools { opacity: 1; pointer-events: auto; }

.tool-btn {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  color: var(--muted);
  transition: color 110ms ease-out, background-color 110ms ease-out, scale 150ms ease-out;
}
.tool-btn .ic { width: 14px; height: 14px; }
.tool-btn[aria-disabled="true"] { opacity: 0.4; cursor: default; }

/* ── shake: a refused action ────────────────────────────────────────── */

.is-shake { animation: shake 320ms var(--ease-out); }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  45% { transform: translateX(4px); }
  70% { transform: translateX(-2px); }
}

/* ── outputs ────────────────────────────────────────────────────────── */

.run-status {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 13px;
  border-top: 1px solid var(--line);
  background: var(--output-bg);
  color: var(--muted);
  font-size: var(--fs-xs);
}
.cell:not(.has-output) .run-status { border-radius: 0 0 calc(var(--r-md) - 1px) calc(var(--r-md) - 1px); }
.dots { display: inline-flex; gap: 3px; }
.dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }

.outputs {
  border-top: 1px solid var(--line);
  padding: 11px 13px 12px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  background: var(--output-bg);
  border-radius: 0 0 calc(var(--r-md) - 1px) calc(var(--r-md) - 1px);
  font: 400 var(--fs-out)/1.58 var(--font-mono);
  color: var(--ink-soft);
  overscroll-behavior-x: contain;
  transition: opacity 150ms ease-out;
}
.outputs:empty { display: none; }
.outputs.is-stale { opacity: 0.75; } /* 0.5 left ink-soft at 2.6:1 in light; 0.75 keeps it above 4.5:1 in both themes */
.run-status:not([hidden]) + .outputs { border-radius: 0 0 calc(var(--r-md) - 1px) calc(var(--r-md) - 1px); }
.cell.is-error .outputs { box-shadow: inset 3px 0 0 var(--err); }

.out {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  word-break: normal;
  font: inherit;
  color: var(--ink-soft);
}
.out.is-muted { color: var(--muted); }

/* A long printout scrolls inside its own box, so one cell cannot push the rest of the notebook out of reach.
   The shadows (cover gradients scroll with the text, shadow gradients stay put) show there is more above or below. */
.out, .out-pre {
  max-height: min(30rem, 70dvh);
  overflow: auto;
}
.out {
  background:
    linear-gradient(var(--output-bg) 30%, transparent) top / 100% 18px no-repeat local,
    linear-gradient(transparent, var(--output-bg) 70%) bottom / 100% 18px no-repeat local,
    radial-gradient(farthest-side at 50% 0, color-mix(in srgb, var(--ink) 18%, transparent), transparent) top / 100% 7px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, color-mix(in srgb, var(--ink) 18%, transparent), transparent) bottom / 100% 7px no-repeat scroll;
}

.out-pre {
  margin: 0;
  padding: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font: inherit;
  color: inherit;
  background: none;
}

.out-head {
  display: block;
  margin-bottom: 3px;
  font: 650 var(--fs-xs)/1.3 var(--font-ui);
  letter-spacing: 0.02em;
  overflow-wrap: anywhere;
}

.out-warn {
  padding: 8px 11px;
  border-radius: 7px;
  background: var(--warn-soft);
  color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 24%, transparent);
}
.out-error {
  padding: 9px 11px;
  border-radius: 7px;
  background: var(--err-soft);
  color: var(--err);
  border: 1px solid color-mix(in srgb, var(--err) 26%, transparent);
}

.out-note {
  margin: 0;
  font: 400 var(--fs-xs)/1.5 var(--font-ui);
  color: var(--muted);
  text-wrap: pretty;
}
.out-note.is-stopped { color: var(--warn); }

.plot {
  position: relative;
  margin: 0;
  width: fit-content;
  max-width: 100%;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px;
  box-shadow: 0 1px 2px rgb(60 40 20 / 0.06), 0 6px 16px -10px rgb(60 40 20 / 0.2);
}
.plot img {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: 3px;
  outline: 1px solid rgb(0 0 0 / 0.1);
  outline-offset: -1px;
}
.plot-save {
  position: absolute;
  top: 10px;
  inset-inline-end: 10px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: rgb(255 255 255 / 0.92);
  border: 1px solid #d2cec3;
  color: #3b3e44;
  opacity: 0;
  transition: opacity 120ms ease-out, scale 150ms ease-out;
}
.plot-save .ic { width: 14px; height: 14px; }
.plot:focus-within .plot-save { opacity: 1; }

.run-meta {
  align-self: flex-end;
  font: 400 var(--fs-xs)/1.2 var(--font-mono);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ── status bar ─────────────────────────────────────────────────────── */

.statusbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--status-h);
  padding: 0 max(10px, env(safe-area-inset-right)) env(safe-area-inset-bottom) max(14px, env(safe-area-inset-left));
  border-top: 1px solid var(--line);
  background: var(--bg-sunken);
  font-size: var(--fs-xs);
  color: var(--muted);
  flex: none;
}

/* The bar wraps onto a second row before anything can overlap or truncate. Translated and failure
   messages are long, and the two failure messages carry instructions the user must be able to read. */
.statusbar { flex-wrap: wrap; row-gap: 2px; }
.status-left, .status-right { display: flex; align-items: center; gap: 10px; min-width: 0; }
.status-left { flex: 1 1 auto; }
.status-right { flex: 0 1 auto; margin-inline-start: auto; }
.status-sep { width: 1px; height: 12px; background: var(--line-strong); flex: none; }

.engine {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  color: inherit;
  border-radius: 5px;
  flex: none;
}
.engine:disabled { color: inherit; }
.engine[data-state="error"] { flex: 0 1 auto; min-width: 0; white-space: normal; text-align: start; color: var(--err); font-weight: 560; text-decoration: underline; text-underline-offset: 0.2em; }
.engine-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--faint);
  transition: background-color 200ms ease-out;
}
.engine[data-state="ready"] .engine-dot { background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent); }
.engine[data-state="booting"] .engine-dot { background: var(--warn); }
.engine[data-state="error"] .engine-dot { background: var(--err); }

.engine-bar {
  display: none;
  width: 52px;
  height: 3px;
  border-radius: 2px;
  background: var(--line-strong);
  overflow: hidden;
}
.engine-bar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width 200ms ease-out; }
.engine[data-state="booting"] .engine-bar { display: block; }

.status-item {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
}

.status-save {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--faint);
  border-radius: 4px;
  transition: color 200ms ease-out;
}
.status-save:disabled { color: var(--faint); }
.status-save.is-saving:disabled { color: var(--muted); }
.status-save.is-error, .status-save.is-volatile { white-space: normal; text-align: end; color: var(--err); font-weight: 560; text-decoration: underline; text-underline-offset: 0.2em; }

.status-btn {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  color: var(--muted);
  flex: none;
  transition: color 120ms ease-out, background-color 120ms ease-out;
}
.status-btn .ic { width: 14px; height: 14px; }

/* ── menu ───────────────────────────────────────────────────────────── */

.menu-root { position: relative; }

.menu {
  position: absolute;
  top: calc(100% + 6px);
  inset-inline-end: 0;
  min-width: 264px;
  max-width: calc(100vw - 24px);
  padding: 5px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  box-shadow: var(--shadow-pop);
  z-index: var(--z-menu);
  transform-origin: top right;
  overscroll-behavior: contain;
  opacity: 0;
  transition: opacity var(--dropdown-close-dur) ease-out;
}
.menu.is-open { opacity: 1; transition-duration: var(--dropdown-open-dur); }

.menu-group + .menu-group { margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--line); }

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border-radius: 7px;
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  text-align: start;
  white-space: nowrap;
}
.menu-item .ic { width: 15px; height: 15px; color: var(--muted); }
.menu-item:focus-visible { background: var(--hover); color: var(--ink); outline: none; }
.menu-item.is-danger, .menu-item.is-danger .ic { color: var(--err); }
.menu-check { display: grid; place-items: center; width: 15px; height: 15px; flex: none; }
.menu-check .ic { opacity: 0; }
.menu-item[aria-checked="true"] .menu-check .ic { opacity: 1; color: var(--accent); }

/* ── toasts ─────────────────────────────────────────────────────────── */

.toasts {
  position: fixed;
  inset-inline: 0;
  bottom: calc(var(--status-h) + 14px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding-inline: 16px;
  z-index: var(--z-toast);
  pointer-events: none;
}

.t-toast {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(520px, 100%);
  padding: 9px 10px 9px 14px;
  border-radius: 11px;
  background: var(--toast-bg);
  color: var(--toast-ink);
  font-size: var(--fs-sm);
  line-height: 1.4;
  box-shadow: var(--shadow-toast);
  pointer-events: auto;
  opacity: 0;
  transition: opacity var(--toast-close) ease-out;
}
.t-toast.is-open { opacity: 1; transition-duration: var(--toast-open); }
.t-toast > span { text-wrap: pretty; }
.t-toast button {
  flex: none;
  padding: 4px 9px;
  border-radius: 6px;
  font-size: var(--fs-xs);
  font-weight: 650;
  color: inherit;
  background: color-mix(in srgb, var(--toast-ink) 16%, transparent);
  transition: background-color 120ms ease-out, scale 150ms ease-out;
}

/* ── dialogs ────────────────────────────────────────────────────────── */

.sheet {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--ink);
  padding: 20px 22px 22px;
  width: min(440px, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: var(--shadow-pop);
  opacity: 0;
  transition: opacity var(--modal-close-dur) ease-out;
}
.sheet.is-open { opacity: 1; transition-duration: var(--modal-open-dur); }
.sheet::backdrop {
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--modal-close-dur) ease-out;
}
.sheet.is-open::backdrop { opacity: 1; transition-duration: var(--modal-open-dur); }

.sheet-sm { width: min(380px, calc(100vw - 32px)); }
.sheet h2 {
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 6px;
  text-wrap: balance;
}
.sheet p { font-size: var(--fs-sm); color: var(--muted); margin: 0 0 16px; line-height: 1.55; text-wrap: pretty; }

.sheet-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.sheet-head h2 { margin: 0; }

.keys { margin: 0 0 14px; display: flex; flex-direction: column; }
.keys > div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
}
.keys > div:last-child { border-bottom: 0; }
.keys dt { display: flex; flex-wrap: wrap; gap: 3px; flex: none; }
.keys dd { margin: 0; font-size: var(--fs-sm); color: var(--muted); text-align: end; }

kbd {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 5px;
  font: 560 var(--fs-xs)/1 var(--font-ui);
  color: var(--ink-soft);
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 5px;
}

.sheet .sheet-foot { font-size: var(--fs-xs); color: var(--faint); margin: 0; line-height: 1.5; }
.sheet-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 8px; }

.field-label { display: block; margin: 0 0 6px; font-size: var(--fs-xs); font-weight: 650; color: var(--ink-soft); }
.field {
  display: block;
  width: 100%;
  margin: 0 0 16px;
  padding: 8px 10px;
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
  background: var(--bg);
  font: 400 var(--fs-sm)/1.4 var(--font-mono);
  text-overflow: ellipsis;
}
.field:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── drop zone ──────────────────────────────────────────────────────── */

.dropzone {
  position: fixed;
  inset: 0;
  z-index: var(--z-drop);
  display: grid;
  place-items: center;
  padding: 24px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  pointer-events: none;
}
.dropzone::before {
  content: "";
  position: absolute;
  inset: 14px;
  border: 2px dashed var(--accent);
  border-radius: var(--r-lg);
  background: var(--accent-soft);
}
.dropzone p {
  position: relative;
  margin: 0;
  font-size: var(--fs-lg);
  font-weight: 650;
  letter-spacing: -0.015em;
  color: var(--accent-ink);
}

/* ── tooltips ───────────────────────────────────────────────────────── */

/* Tooltip = ::after bubble + ::before bridge over the gap, so the pointer can travel
   onto the bubble without it vanishing (WCAG 1.4.13: hoverable). Opacity only. */
:where([data-tip]) { position: relative; } /* zero specificity: .plot-save and friends stay absolute */
[data-tip]:not([data-tip=""])::after,
[data-tip]:not([data-tip=""])::before {
  position: absolute;
  top: 100%;
  inset-inline-start: 50%;
  translate: -50% 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms ease-out, visibility 0s linear 120ms;
}
[data-tip]:not([data-tip=""])::before { content: ""; width: 100%; height: 8px; }
[data-tip]:not([data-tip=""])::after {
  content: attr(data-tip);
  margin-top: 8px;
  padding: 5px 8px;
  border-radius: 6px;
  background: var(--ink);
  color: var(--bg);
  font: 500 var(--fs-xs)/1.3 var(--font-ui);
  white-space: nowrap;
  z-index: var(--z-tip);
}
[data-tip-end]:not([data-tip=""])::after { inset-inline-start: auto; inset-inline-end: 0; translate: none; }
[data-tip-up]:not([data-tip=""])::before { top: auto; bottom: 100%; }
[data-tip-up]:not([data-tip=""])::after { top: auto; bottom: 100%; margin-top: 0; margin-bottom: 8px; }
[data-tip]:not([data-tip=""]):focus-visible::after,
[data-tip]:not([data-tip=""]):focus-visible::before { opacity: 1; visibility: visible; transition-delay: 0s; }
[data-tip][aria-expanded="true"]::after,
[data-tip][aria-expanded="true"]::before,
html[data-tips-off] [data-tip]::after,
html[data-tips-off] [data-tip]::before { display: none; }

/* ── responsive ─────────────────────────────────────────────────────── */

@media (max-width: 860px) {
  .app { grid-template-columns: minmax(0, 1fr); }

  .rail {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(300px, 86vw);
    z-index: var(--z-rail);
    box-shadow: 20px 0 48px -24px rgb(0 0 0 / 0.3);
    opacity: 0;
    visibility: hidden;
    transition: opacity 150ms ease-out, visibility 0s linear 150ms;
  }
  .app[data-rail="open"] .rail { opacity: 1; visibility: visible; transition-delay: 0s; }

  .rail-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: var(--z-scrim);
    background: var(--scrim);
    opacity: 0;
    visibility: hidden;
    transition: opacity 200ms ease-out, visibility 0s linear 200ms;
  }
  .app[data-rail="open"] .rail-scrim { opacity: 1; visibility: visible; transition-delay: 0s; }

  .only-narrow { display: grid; }

  .canvas { padding-inline: max(12px, env(safe-area-inset-left)) max(12px, env(safe-area-inset-right)); }
  .notebook { padding-top: 26px; }
  .nb-title { max-width: none; }
}

@media (max-width: 720px) {
  .btn-run .btn-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .btn-run { width: 32px; padding: 0; }
}

@media (max-width: 600px) {
  #runInfo, .status-sep { display: none; }
}

@media (max-width: 640px) {
  .outputs { overflow-x: auto; }
  .out, .out-pre { white-space: pre; }
  .out-error .out-pre, .out-warn .out-pre, .out-note { white-space: pre-wrap; }
}

@media (max-width: 520px) {
  :root { --gutter: 26px; }
  .cell { column-gap: 6px; }
  .cell-gutter { padding-top: 7px; }
  .run-btn { width: 24px; height: 24px; }
  .add-row { padding-inline-start: calc(var(--gutter) + 6px); }
  .editor pre, .editor textarea { padding: 10px 11px 11px; }
  .topbar { gap: 4px; padding-inline: 8px; }
  .topbar-actions { gap: 4px; }
  .statusbar { padding-inline: 10px 6px; gap: 8px; }
}

@media (max-width: 440px) {
  .btn-share .btn-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .btn-share { width: 32px; padding: 0; }
  .nb-title { font-size: var(--fs-md); }
}

/* touch: bigger targets, and 16px fields so iOS does not zoom the page on focus */
@media (pointer: coarse) {
  :root { --code-size: 1rem; }
  .icon-btn { width: 40px; height: 40px; }
  .btn { height: 40px; }
  .btn-run, .btn-share { min-width: 40px; }
  .tool-btn { width: 36px; height: 36px; }
  .run-btn { width: 32px; height: 32px; }
  .status-btn { width: 36px; height: 36px; }
  .add-btn { height: 38px; }
  .nb-item { padding-block: 11px; }
  .menu-item { padding-block: 11px; }
  .rail-link { padding-block: 11px; }
  .nb-title, .field { font-size: 1rem; }
  .cell-tools { top: -20px; }
  .plot-save { opacity: 1; width: 36px; height: 36px; }
}
@media (pointer: coarse) and (max-width: 520px) {
  :root { --gutter: 34px; }
  .btn-run, .btn-share { width: 40px; }
  .topbar-actions { gap: 2px; }
}

/* ── hover (only where hover exists; on touch it would stick after a tap) ── */

@media (hover: hover) {
  [data-tip]:not([data-tip=""]):hover::after,
  [data-tip]:not([data-tip=""]):hover::before { opacity: 1; visibility: visible; transition-delay: 350ms, 350ms; }
  .btn-new:hover, .btn-plain:hover, .btn-quiet:hover { border-color: var(--edge); }
  .btn-share:hover { background: var(--solid-hover); }
  .btn-accent:hover:not([aria-disabled="true"]) { background: color-mix(in srgb, var(--accent) 88%, var(--ink)); }
  .btn-danger:hover { filter: brightness(1.07); }
  .icon-btn:hover, .status-btn:hover { color: var(--ink); background: var(--hover); }
  .nb-title:hover:not(:focus) { background: var(--hover); }
  .nb-item:hover:not([aria-current="page"]) { background: var(--hover); }
  .rail-link:hover { color: var(--ink); background: var(--hover); }
  .add-btn:hover { color: var(--ink); border-color: var(--ink-soft); background: var(--surface); }
  .cell:not(:focus-within, [data-run="running"]) .run-btn:hover:not([aria-disabled="true"]) { color: var(--accent-ink); border-color: var(--accent); background: var(--accent-soft); }
  .cell:focus-within .run-btn:hover:not([aria-disabled="true"]) { background: color-mix(in srgb, var(--accent) 88%, var(--ink)); }
  .cell:hover .cell-tools { opacity: 1; pointer-events: auto; }
  .tool-btn:hover:not([aria-disabled="true"]) { color: var(--ink); background: var(--hover); }
  .tool-btn.is-danger:hover { color: var(--err); }
  .cell[data-type="code"]:hover .cell-body { border-color: var(--edge); }
  .cell[data-type="code"]:hover .cell-body:focus-within { border-color: var(--accent); }
  .cell[data-type="markdown"]:hover .cell-body { border-color: var(--line); }
  .cell[data-type="markdown"].is-editing:hover .cell-body { border-color: var(--accent); }
  .menu-item:hover { background: var(--hover); color: var(--ink); }
  .t-toast button:hover { background: color-mix(in srgb, var(--toast-ink) 28%, transparent); }
  .plot:hover .plot-save { opacity: 1; }
  .md-view a:hover { text-decoration-thickness: 2px; }
  .status-save.is-error:hover, .status-save.is-volatile:hover, .engine[data-state="error"]:hover { text-decoration-thickness: 2px; }
}

/* ── theme switch: hold every colour transition for a frame ─────────── */

html.theme-switching *, html.theme-switching *::before, html.theme-switching *::after { transition: none !important; }

/* ── motion (full) ──────────────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
  :is(.btn, .icon-btn, .tool-btn, .run-btn, .add-btn, .plot-save):not(:disabled, [aria-disabled="true"]):active,
  .t-toast button:active { scale: 0.96; }

  .t-icon-swap > .ic { transition-property: opacity, scale, filter; }
  .t-icon-swap[data-state="a"] > .ic-b,
  .t-icon-swap[data-state="b"] > .ic-a { scale: 0.25; filter: blur(4px); }

  .t-text-swap > span { transition-property: opacity, translate, filter; }
  .t-text-swap[data-state="a"] > .swap-b { translate: 0 6px; filter: blur(3px); }
  .t-text-swap[data-state="b"] > .swap-a { translate: 0 -6px; filter: blur(3px); }

  .menu { transform: translateY(-4px) scale(0.96); transition-property: opacity, transform; }
  .menu.is-open { transform: none; }

  .sheet { transform: translateY(8px) scale(0.96); transition-property: opacity, transform; }
  .sheet.is-open { transform: none; }

  .t-toast { transform: translateY(12px); filter: blur(4px); transition-property: opacity, transform, filter; }
  .t-toast.is-open { transform: none; filter: none; }

  /* the drawer only exists on narrow screens; on desktop the rail is a plain grid column */
  @media (max-width: 860px) {
    .rail {
      transform: translateX(-100%);
      transition-property: opacity, transform, visibility;
      transition-duration: 280ms, 280ms, 0s;
      transition-timing-function: var(--ease-drawer), var(--ease-drawer), linear;
      transition-delay: 0s, 0s, 280ms;
    }
    .app[data-rail="open"] .rail { transform: none; transition-delay: 0s; }
  }

  .cell[data-run="running"] .cell-body::before { animation: sweep 1.4s var(--ease-in-out) infinite; }

  .dots i { animation: pulse 1.1s var(--ease-in-out) infinite; }
  .dots i:nth-child(2) { animation-delay: 160ms; }
  .dots i:nth-child(3) { animation-delay: 320ms; }
  .engine[data-state="booting"] .engine-dot,
  .engine[data-busy] .engine-dot { animation: pulse 1.2s var(--ease-in-out) infinite; }
}

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
@keyframes sweep { from { background-position: -70% 0; } to { background-position: 170% 0; } }

/* ── motion (reduced): keep the cross-fades, drop movement ──────────── */

@media (prefers-reduced-motion: reduce) {
  :root {
    --dropdown-open-dur: 100ms;
    --dropdown-close-dur: 100ms;
    --modal-open-dur: 120ms;
    --modal-close-dur: 100ms;
    --toast-open: 150ms;
    --toast-close: 120ms;
  }
  .canvas { scroll-behavior: auto; }
  :is(.btn, .icon-btn, .tool-btn, .run-btn, .add-btn, .plot-save):not(:disabled, [aria-disabled="true"]):active,
  .t-toast button:active { opacity: 0.7; }
  .is-shake { animation: none; box-shadow: inset 0 0 0 2px var(--err); }
  .engine[data-busy] .engine-dot { background: var(--accent); }
  .cell[data-run="running"] .cell-body::before { background: var(--accent); }
}

/* ── forced colours ─────────────────────────────────────────────────── */

/* Windows high contrast drops box-shadows and background tints and swaps border colours for system ones,
   so each state that was shown with those needs an outline, a border or a system colour of its own. */
@media (forced-colors: active) {
  .cell[data-type="code"] .cell-body:focus-within { outline: 2px solid Highlight; outline-offset: 2px; }
  .menu-item:focus-visible { outline: 2px solid Highlight; outline-offset: -2px; }
  .nb-item[aria-current="page"] { outline: 2px solid Highlight; outline-offset: -2px; }
  .btn-share, .btn-accent { forced-color-adjust: none; background: Highlight; color: HighlightText; border-color: Highlight; }
  .cell:focus-within .run-btn { forced-color-adjust: none; background: Highlight; color: HighlightText; border-color: Highlight; }
  .t-toast { border: 1px solid CanvasText; }
}
