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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;

  /* Fill the viewport so the footer sits on the bottom edge instead of
     floating halfway up a short page — on the sign-in and error pages there
     is not enough content to push it down on its own. */
  min-height: 100svh;
  display: flex;
  flex-direction: column;

  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;              /* 16px floor: stops iOS zooming on focus */
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;           /* nothing may scroll the page sideways */

  /* Cross-platform touch behaviour. Android Chrome and iOS Safari each need
     their own line here; neither inherits the other's default. */
  -webkit-tap-highlight-color: rgba(127, 178, 221, .22);  /* Android's grey flash */
  -webkit-touch-callout: none;                            /* iOS long-press menu */
  touch-action: manipulation;                             /* kills the 300ms delay */

  /* Notches, punch-holes and gesture bars, on both platforms. */
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* Text you are meant to read and copy keeps its selection behaviour. */
p, li, blockquote, .msg, .prompt-block, .field-input, .synthesis { -webkit-touch-callout: default; user-select: text; }

/* ── The mesh ──────────────────────────────────────────────────────
   A fixed, non-scrolling backdrop: four very soft radial gradients in the
   blue and pink seeds over --bg. CSS only — no image, no canvas, no JS,
   and it never animates on a loop.

   It is a real element (`.mesh` in base.html) rather than a pseudo-element
   because body is a flex container and a ::before would become a flex item
   on the pages that do not set position on it.

   The alphas are deliberately low: the darkest point of the mesh is
   #e2ecf6, and a glass panel over that still carries body text at 15:1. */

.mesh {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(58vw 46vw at 12% 4%, rgba(127, 178, 221, var(--mesh-blue-a)), transparent 62%),
    radial-gradient(52vw 44vw at 92% 14%, rgba(232, 180, 184, var(--mesh-pink-a)), transparent 64%),
    radial-gradient(66vw 52vw at 76% 88%, rgba(127, 178, 221, calc(var(--mesh-blue-a) * .7)), transparent 66%),
    radial-gradient(48vw 40vw at 4% 82%, rgba(61, 74, 92, var(--mesh-slate-a)), transparent 60%);
}

/* Mood is a shift in the mesh, not a different theme. Only the weighting
   between the same four gradients changes, so nobody reads it as a theme
   switch. .mood-still is the default and needs no override. */
body.mood-warm .mesh { --mesh-pink-a: 0.19; --mesh-blue-a: 0.11; }
body.mood-cool .mesh { --mesh-blue-a: 0.20; --mesh-pink-a: 0.08; }
body.mood-still .mesh { --mesh-blue-a: 0.13; --mesh-pink-a: 0.10; }

/* ── Ink ───────────────────────────────────────────────────────────
   The writing mode. Warm paper, no blur anywhere on the page, the mesh
   almost gone, and the chrome dimmed so the writing is the brightest
   thing on screen. Templates opt in with `mode-ink` on <body>. */

body.mode-ink { background: var(--paper); }
body.mode-ink .mesh { opacity: .25; }
/* .88, not lower: at .82 the sidebar's white labels fall to 4.23:1. This
   dims the chrome without dropping its own text under 4.5. */
body.mode-ink .akoti-sidebar { opacity: .88; }
body.mode-ink .akoti-sidebar:hover,
body.mode-ink .akoti-sidebar:focus-within { opacity: 1; }
/* No blur on a writing page, whatever asked for it. */
body.mode-ink * { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
body.mode-ink .app-bar { background: var(--paper); }
/* Nothing animates while a textarea has focus. */
body.mode-ink:has(textarea:focus) * { transition: none !important; animation: none !important; }

/* `.ink` is the partial case: one reading surface inside a page that is
   otherwise glass — a transcript detail is a meta strip above a long read.
   It carries the paper tone and kills blur for its subtree only. */
.ink {
  background: var(--paper);
  color: var(--on-surface);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.ink * { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* The reading measure. About 68 characters is where a line stops being
   work to track back from. Use it on prompt text, note bodies, pasted
   transcripts, insights and export copy rather than an inline max-width. */
.measure { max-width: 68ch; line-height: 1.7; }
.measure-tight { max-width: 56ch; line-height: 1.65; }
/* A textarea gets the same measure and the same generous leading. */
.ink-write { line-height: 1.7; background: var(--paper); max-width: 68ch; }
.ink-measure { max-width: 68ch; }   /* kept: earlier templates use this name */

/* ── Type ──────────────────────────────────────────────────────────
   Fraunces is loaded as four static instances (400/600/700/900) in
   vendor/fonts.css, not as the variable font — so there is no `opsz` axis
   to address and no weight beyond those four may be named here. */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.2;
  margin: 0 0 0.4em;
  letter-spacing: -0.01em;
  overflow-wrap: break-word;
}
h1 { font-size: clamp(1.6rem, 6vw, 2.9rem); font-weight: 900; letter-spacing: -0.03em; line-height: 1.08; }
h2 { font-size: clamp(1.24rem, 4.4vw, 1.8rem); letter-spacing: -0.02em; line-height: 1.14; }
h3 { font-size: clamp(1.02rem, 3.4vw, 1.18rem); letter-spacing: -0.015em; }

/* Display type used outside a heading — a hero line or a page lede. */
.display {
  font-family: var(--font-display);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1.05;
  font-size: clamp(2rem, 8vw, 3.4rem);
}
/* A lede or a through-line. The insight through-line is the most quotable
   thing the app produces, so it is set in the display face at a size that
   says so — not as body copy in bold. */
.lede {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.28;
  font-size: clamp(1.15rem, 3.6vw, 1.5rem);
  color: var(--on-surface);
  max-width: 62ch;
}
.display-lg {
  font-family: var(--font-display);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1.04;
  font-size: clamp(2.4rem, 9vw, 4.2rem);
}

/* Numbers are display-face, not body-face. */
.figure {
  font-family: var(--font-display);
  font-weight: 900;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums lining-nums;
}

a { color: var(--blue-deep); text-decoration-thickness: 1px; text-underline-offset: 2px; }
p { margin: 0 0 0.9em; overflow-wrap: break-word; }
img, svg, video { max-width: 100%; height: auto; }

/* --focus-ring rather than --blue: the light seed drops to 2.15:1 against a
   glass panel, which is a focus ring you cannot see. This one holds 6.47:1. */
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: 4px; }

