/* ============================================================================
   NovaTools — shared stylesheet for every page except the app
   ============================================================================
   index.html carries its own CSS inline and stays a single self-contained
   file, which is the whole point of it: one paste, no dependencies, works
   from a file:// URL. Everything around it — legal pages, blog, contact — is
   ordinary content, and content pages benefit from sharing one stylesheet
   that the browser caches once and reuses for the rest of the visit.

   The tokens below are the same oklch palette index.html uses. They are
   repeated rather than imported so that neither file can break the other.
   ============================================================================ */

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

:root {
  --radius: 0.9rem;
  --background: oklch(0.985 0.004 250);
  --foreground: oklch(0.19 0.02 264);
  --card: oklch(1 0 0);
  --primary: oklch(0.55 0.2 262);
  --primary-foreground: oklch(0.99 0.005 250);
  --secondary: oklch(0.955 0.008 255);
  --muted-foreground: oklch(0.5 0.02 258);
  --accent: oklch(0.72 0.13 200);
  --border: oklch(0.9 0.01 258);
  --gradient-brand: linear-gradient(120deg, oklch(0.6 0.2 262), oklch(0.72 0.14 200) 55%, oklch(0.72 0.16 330));
  --glow: oklch(0.55 0.2 262 / 22%);
  --shadow-soft: 0 1px 0 oklch(1 0 0 / 40%) inset, 0 18px 50px -20px oklch(0.2 0.03 264 / 25%);
  --shadow-glow: 0 30px 90px -30px var(--glow);
  --focus: oklch(0.55 0.2 262);
}
:root[data-theme="dark"] {
  --background: oklch(0.155 0.014 265);
  --foreground: oklch(0.97 0.005 250);
  --card: oklch(0.19 0.016 265);
  --primary: oklch(0.68 0.18 264);
  --primary-foreground: oklch(0.14 0.02 265);
  --secondary: oklch(0.245 0.018 265);
  --muted-foreground: oklch(0.72 0.02 262);
  --accent: oklch(0.8 0.13 195);
  --border: oklch(1 0 0 / 12%);
  --gradient-brand: linear-gradient(120deg, oklch(0.68 0.18 264), oklch(0.8 0.13 195) 55%, oklch(0.75 0.17 330));
  --glow: oklch(0.68 0.18 264 / 30%);
  --shadow-soft: 0 1px 0 oklch(1 0 0 / 6%) inset, 0 24px 60px -28px oklch(0 0 0 / 70%);
  --shadow-glow: 0 40px 120px -40px var(--glow);
  --focus: oklch(0.8 0.13 195);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --background: oklch(0.155 0.014 265); --foreground: oklch(0.97 0.005 250);
    --card: oklch(0.19 0.016 265); --primary: oklch(0.68 0.18 264);
    --primary-foreground: oklch(0.14 0.02 265); --secondary: oklch(0.245 0.018 265);
    --muted-foreground: oklch(0.72 0.02 262); --accent: oklch(0.8 0.13 195);
    --border: oklch(1 0 0 / 12%);
    --gradient-brand: linear-gradient(120deg, oklch(0.68 0.18 264), oklch(0.8 0.13 195) 55%, oklch(0.75 0.17 330));
    --glow: oklch(0.68 0.18 264 / 30%);
    --shadow-soft: 0 1px 0 oklch(1 0 0 / 6%) inset, 0 24px 60px -28px oklch(0 0 0 / 70%);
    --shadow-glow: 0 40px 120px -40px var(--glow);
    --focus: oklch(0.8 0.13 195);
  }
}

/* System fonts only. A web font is 30-120KB, a round trip to a third party,
   and a guaranteed layout shift when it swaps in. The stack below renders
   instantly on every platform and costs nothing against Largest Contentful
   Paint or Cumulative Layout Shift. */
body {
  background: var(--background); color: var(--foreground);
  font-family: "Geist", "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px; line-height: 1.65; -webkit-font-smoothing: antialiased;
  min-height: 100vh; overflow-x: hidden;
}
code, pre, .mono { font-family: "Geist Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; }

/* ---- accessibility ---------------------------------------------------------
   A visible focus ring on everything that takes focus, and a skip link that is
   the first thing a keyboard lands on. Both are requirements, not polish. */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 6px; }
.skip { position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--card); color: var(--foreground); padding: 12px 18px;
  border: 1px solid var(--border); border-radius: 0 0 12px 0; text-decoration: none; }
.skip:focus { left: 0; }
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---- background ------------------------------------------------------------
   Two blurred blobs rather than the app's three: this is a reading surface and
   the point is contrast, not spectacle. */
.aurora { position: fixed; inset: 0; z-index: -10; overflow: hidden; pointer-events: none; }
.blob { position: absolute; border-radius: 9999px; filter: blur(90px); opacity: .5; }
.b1 { width: 520px; height: 520px; top: -140px; left: -100px;
  background: color-mix(in oklab, var(--primary) 45%, transparent); }
.b2 { width: 440px; height: 440px; top: 120px; right: -140px;
  background: color-mix(in oklab, var(--accent) 40%, transparent); }
.gridlines { position: absolute; inset: 0; opacity: .18;
  background-image: linear-gradient(color-mix(in oklab, var(--border) 90%, transparent) 1px, transparent 1px),
                    linear-gradient(90deg, color-mix(in oklab, var(--border) 90%, transparent) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: linear-gradient(to bottom, #000, transparent 55%);
          mask-image: linear-gradient(to bottom, #000, transparent 55%); }

/* ---- navbar ---------------------------------------------------------------- */
.nav { position: sticky; top: 0; z-index: 50; padding: 12px;
  backdrop-filter: blur(14px); }
@media (min-width: 640px) { .nav { padding: 16px 20px; } }
.navin { max-width: 1200px; margin: 0 auto; display: flex; align-items: center; gap: 10px;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  background: color-mix(in oklab, var(--card) 78%, transparent);
  border-radius: calc(var(--radius) + 4px); padding: 8px 12px; box-shadow: var(--shadow-soft); }
.brand { display: flex; align-items: center; gap: 9px; text-decoration: none; color: inherit; font-weight: 600; }
.brandsq { display: block; width: 32px; height: 32px; border-radius: 10px; overflow: hidden;
  flex: 0 0 auto; transition: transform .3s cubic-bezier(.22,1,.36,1); }
.brandsq svg { display: block; width: 100%; height: 100%; }
.brand:hover .brandsq { transform: rotate(-8deg) scale(1.06); }
.navlinks { display: none; align-items: center; gap: 2px; margin-left: 8px; }
@media (min-width: 900px) { .navlinks { display: flex; } }
.navlinks a { border-radius: 10px; padding: 7px 12px; font-size: 14px; text-decoration: none;
  color: var(--muted-foreground); transition: .2s; }
.navlinks a:hover, .navlinks a[aria-current="page"] {
  color: var(--foreground); background: color-mix(in oklab, var(--secondary) 65%, transparent); }
.navright { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.iconbtn { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent); background: none;
  color: var(--muted-foreground); cursor: pointer; transition: .2s; }
.iconbtn:hover { color: var(--foreground); background: color-mix(in oklab, var(--secondary) 60%, transparent); }
.cta { border: 0; border-radius: 12px; padding: 9px 17px; font: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer; background: var(--gradient-brand); color: var(--primary-foreground);
  text-decoration: none; display: inline-block; transition: box-shadow .25s, transform .2s; }
.cta:hover { box-shadow: var(--shadow-glow); }
.cta:active { transform: translateY(1px); }
.ghost { border-radius: 12px; padding: 9px 17px; font: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer; text-decoration: none; color: var(--foreground); display: inline-block;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  background: color-mix(in oklab, var(--secondary) 40%, transparent); transition: .2s; }
.ghost:hover { background: color-mix(in oklab, var(--secondary) 85%, transparent); }

/* ---- page shell ------------------------------------------------------------ */
.wrap { max-width: 1200px; margin: 0 auto; padding: 0 20px; }
.page { max-width: 760px; margin: 0 auto; padding: 44px 20px 20px; }
.crumbs { font-size: 13.5px; color: var(--muted-foreground); margin-bottom: 22px; }
.crumbs a { color: inherit; text-decoration: none; }
.crumbs a:hover { color: var(--foreground); text-decoration: underline; }
.eyebrow { font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted-foreground); font-weight: 600; display: block; margin-bottom: 12px; }
h1 { font-size: clamp(2rem, 4.4vw, 2.9rem); font-weight: 600; letter-spacing: -.033em; line-height: 1.08; }
h1 .g { background: var(--gradient-brand); -webkit-background-clip: text; background-clip: text; color: transparent; }
.lede { color: var(--muted-foreground); font-size: 17px; margin-top: 16px; }
.updated { font-size: 13.5px; color: var(--muted-foreground); margin-top: 18px;
  padding-top: 16px; border-top: 1px solid color-mix(in oklab, var(--border) 70%, transparent); }

/* ---- prose ----------------------------------------------------------------- */
.prose { margin-top: 34px; }
.prose h2 { font-size: 1.45rem; font-weight: 600; letter-spacing: -.02em; margin: 40px 0 12px;
  scroll-margin-top: 90px; }
.prose h3 { font-size: 1.12rem; font-weight: 600; margin: 28px 0 8px; scroll-margin-top: 90px; }
.prose p { margin: 0 0 16px; }
.prose ul, .prose ol { margin: 0 0 18px; padding-left: 22px; }
.prose li { margin-bottom: 8px; }
.prose a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }
.prose a:hover { text-decoration-thickness: 2px; }
.prose strong { font-weight: 600; }
.prose code { font-size: .9em; padding: 2px 6px; border-radius: 6px;
  background: color-mix(in oklab, var(--secondary) 75%, transparent); }
.prose blockquote { margin: 0 0 18px; padding: 2px 0 2px 18px;
  border-left: 3px solid color-mix(in oklab, var(--primary) 55%, transparent);
  color: var(--muted-foreground); }
.prose table { width: 100%; border-collapse: collapse; margin: 0 0 20px; font-size: 14.5px; }
.prose th, .prose td { text-align: left; padding: 10px 12px;
  border-bottom: 1px solid color-mix(in oklab, var(--border) 70%, transparent); }
.prose th { font-weight: 600; }
.tablewrap { overflow-x: auto; }
.note { border-radius: var(--radius); padding: 16px 18px; margin: 0 0 20px; font-size: 14.5px;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  background: color-mix(in oklab, var(--secondary) 40%, transparent); }
.note b { display: block; margin-bottom: 4px; }

/* ---- cards ----------------------------------------------------------------- */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); gap: 16px; margin: 26px 0; }
.card { border-radius: calc(var(--radius) + 6px); padding: 20px; text-decoration: none; color: inherit;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  background: color-mix(in oklab, var(--card) 60%, transparent);
  transition: transform .25s, box-shadow .25s, border-color .25s; }
a.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-glow);
  border-color: color-mix(in oklab, var(--primary) 40%, transparent); }
.card b { display: block; font-size: 15.5px; font-weight: 600; }
.card p { margin-top: 6px; font-size: 14px; color: var(--muted-foreground); }

/* ---- forms ----------------------------------------------------------------- */
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13.5px; font-weight: 500; margin-bottom: 6px; }
input, textarea, select { width: 100%; border-radius: 11px; padding: 11px 13px; font: inherit; font-size: 15px;
  border: 1px solid color-mix(in oklab, var(--border) 80%, transparent);
  background: color-mix(in oklab, var(--card) 70%, transparent); color: var(--foreground); }
textarea { min-height: 140px; resize: vertical; }
input:focus, textarea:focus { border-color: color-mix(in oklab, var(--primary) 50%, transparent); }
.formmsg { margin-top: 14px; font-size: 14.5px; }
.formmsg.ok { color: var(--accent); }
.formmsg.err { color: oklch(0.62 0.21 25); }

/* ---- ad slots ---------------------------------------------------------------
   An ad slot occupies no space until it has an ad in it. Reserving a fixed
   height for something that may never render is how a page gets a bad
   Cumulative Layout Shift score AND a hole in the middle of it; reserving
   nothing is how a page jumps when the ad arrives. The compromise here is a
   min-height applied only once the slot is known to be live, so the space is
   held before the iframe paints but never held for nothing. */
.adslot { display: none; margin: 32px auto; text-align: center; }
.adslot.live { display: block; min-height: 100px; }
.adslot.live.tall { min-height: 250px; }
.adslot > .adlabel { display: block; font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted-foreground); margin-bottom: 6px; }
.adslot.preview { display: block; }
.adslot.preview .adbox { display: grid; place-items: center; min-height: 110px; border-radius: var(--radius);
  border: 1px dashed color-mix(in oklab, var(--border) 100%, transparent);
  background: color-mix(in oklab, var(--secondary) 30%, transparent);
  color: var(--muted-foreground); font-size: 13px; }
.adrail { display: none; }
@media (min-width: 1400px) {
  .adrail.live, .adrail.preview { display: block; position: fixed; top: 96px; right: 20px; width: 300px; z-index: 20; }
}

/* ---- footer ----------------------------------------------------------------- */
.foot { margin-top: 70px; padding: 52px 0 28px;
  border-top: 1px solid color-mix(in oklab, var(--border) 70%, transparent); }
.footcols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr)); gap: 30px; }
.footcols h2 { font-size: 12px; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 12px;
  color: var(--foreground); font-weight: 600; }
.footcols a { display: block; color: var(--muted-foreground); text-decoration: none; font-size: 14px; padding: 4px 0; }
.footcols a:hover { color: var(--foreground); text-decoration: underline; }
.footcols p { color: var(--muted-foreground); font-size: 14px; max-width: 32ch; }
.news { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.news input { flex: 1; min-width: 160px; font-size: 14px; padding: 9px 12px; }
.footbot { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; margin-top: 40px; padding-top: 22px;
  border-top: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  color: var(--muted-foreground); font-size: 13.5px; }
.social { display: flex; gap: 8px; margin-left: auto; }
.social a { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  color: var(--muted-foreground); text-decoration: none; }
.social a:hover { color: var(--foreground); border-color: color-mix(in oklab, var(--primary) 40%, transparent); }

/* ---- cookie banner -----------------------------------------------------------
   Only ever shown when something that actually sets a cookie has been switched
   on in nt-config.js. A consent banner on a site that stores nothing is noise,
   and users learn to dismiss banners without reading them. */
#ntconsent { position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 120; display: none;
  border-radius: calc(var(--radius) + 4px); padding: 18px;
  border: 1px solid color-mix(in oklab, var(--border) 80%, transparent);
  background: color-mix(in oklab, var(--card) 96%, transparent); backdrop-filter: blur(16px);
  box-shadow: var(--shadow-glow); }
@media (min-width: 720px) { #ntconsent { left: auto; right: 20px; bottom: 20px; max-width: 420px; } }
#ntconsent.show { display: block; }
#ntconsent p { font-size: 14px; color: var(--muted-foreground); }
#ntconsent .row { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }

/* ---- blog -------------------------------------------------------------------- */
.postmeta { display: flex; gap: 14px; flex-wrap: wrap; align-items: center;
  color: var(--muted-foreground); font-size: 13.5px; margin-top: 18px; }
.avatar { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 9999px;
  background: var(--gradient-brand); color: var(--primary-foreground); font-size: 12px; font-weight: 700; }
.tag { display: inline-block; border-radius: 9999px; padding: 3px 11px; font-size: 12.5px;
  text-decoration: none; color: var(--muted-foreground);
  border: 1px solid color-mix(in oklab, var(--border) 80%, transparent); }
a.tag:hover, .tag.on { color: var(--foreground);
  background: color-mix(in oklab, var(--secondary) 80%, transparent); }
.taglist { display: flex; gap: 8px; flex-wrap: wrap; margin: 24px 0; }
.toc { border-radius: var(--radius); padding: 18px 20px; margin: 30px 0;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  background: color-mix(in oklab, var(--secondary) 32%, transparent); }
.toc h2 { font-size: 12px !important; letter-spacing: .13em; text-transform: uppercase;
  margin: 0 0 10px !important; color: var(--muted-foreground); }
.toc ol { margin: 0; padding-left: 20px; font-size: 14.5px; }
.toc li { margin-bottom: 5px; }
.share { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 34px 0 0;
  padding-top: 22px; border-top: 1px solid color-mix(in oklab, var(--border) 70%, transparent); }
.share span { font-size: 13.5px; color: var(--muted-foreground); margin-right: 4px; }
.postlist { display: grid; gap: 14px; margin-top: 28px; }
.post { display: block; padding: 22px; border-radius: calc(var(--radius) + 6px); text-decoration: none; color: inherit;
  border: 1px solid color-mix(in oklab, var(--border) 70%, transparent);
  background: color-mix(in oklab, var(--card) 55%, transparent);
  transition: transform .25s, box-shadow .25s, border-color .25s; }
.post:hover { transform: translateY(-3px); box-shadow: var(--shadow-glow);
  border-color: color-mix(in oklab, var(--primary) 40%, transparent); }
.post h2 { font-size: 1.2rem; font-weight: 600; letter-spacing: -.02em; }
.post p { margin-top: 7px; color: var(--muted-foreground); font-size: 14.5px; }

/* ---- fitting a finger ----
   Same reasoning as the application page: only where the primary input is
   coarse, and only on standalone controls. A link inside a sentence is left
   alone — WCAG exempts it, and padding it would break the line it sits in. */
@media (pointer: coarse) and (hover: none) {
  .navlinks a, .footcols a, .tag, .social a { min-height: 40px; display: flex; align-items: center; }
  .social a { justify-content: center; }
  .iconbtn { min-width: 40px; min-height: 40px; }
  .cta, .ghost { min-height: 42px; padding-top: 11px; padding-bottom: 11px; }
  input, textarea, select { min-height: 44px; font-size: 16px; }
  .toc a, .postlist .post { padding-top: 10px; padding-bottom: 10px; }
  /* A breadcrumb trail is a row of destinations, not a sentence. */
  .crumbs a { display: inline-block; padding: 11px 3px; }
  .crumbs { margin-bottom: 12px; }
  /* Secondary labels sized for a monitor are too small on any handheld,
     tablets included — so this is tied to the input device, not the width. */
  .tag, .adslot .adlabel { font-size: 12.5px; }
}

@media (max-width: 520px) {
  .page { padding: 30px 16px 16px; }
  .prose h2 { font-size: 1.3rem; }
  .lede { font-size: 16px; }
  .tag { font-size: 12.5px; }
  /* A table wider than the phone scrolls inside its own box rather than
     forcing the article to. Every table in the articles is already wrapped. */
  .tablewrap { margin-inline: -16px; padding-inline: 16px; }
}

@media (max-width: 360px) {
  .navin { padding: 6px 8px; gap: 6px; }
  .page { padding-left: 13px; padding-right: 13px; }
}

/* Reading measure is a function of the text, not the screen. On a large
   monitor the column stays put and the margins grow — which is correct — but
   the footer and the nav can use the extra room. */
@media (min-width: 1800px) {
  .wrap { max-width: 1560px; }
  .navin { max-width: 1560px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important;
      transition-duration: .001ms !important; scroll-behavior: auto !important; }
}
