/* base.css — the public site's own foundation.
 *
 * WHY THIS FILE EXISTS. The fifteen public pages (the blog index, twelve posts,
 * terms and privacy) each loaded style.css, the ESTIMATOR's stylesheet: 478 KB
 * raw, 101 KB gzipped, render blocking. Measured on the blog index, 3,351 of
 * its 3,386 rules matched nothing on the page. They were not loading it for its
 * rules. They were loading it because every design token in the product is
 * declared there and nowhere else, 6.9 KB of :root blocks, 1.5% of the file.
 *
 * So this is that 1.5%, plus the handful of things the public pages genuinely
 * share with the app: the reset, the site nav, and the mobile bottom nav. The
 * selector list was not guessed. It is the union of what actually matched on
 * the three public page shapes, read out of the browser.
 *
 * style.css is UNCHANGED and app.html still loads it. Nothing here is removed
 * from there, so the two cannot disagree about a token today. If a token moves,
 * it has to move in both, and scripts/check-tokens.js is what notices.
 *
 * One deliberate difference: style.css's body rule carries the app shell
 * (100dvh, overflow hidden, flex column). That frame is the estimator's, and
 * carrying it here is why every public page has had to override body. The
 * typography and the colour come across; the frame does not.
 *
 * Load it where style.css used to sit, before the page's own sheets, so
 * blog.css and a page's own block still win.
 */

/* PROD: minify with: npx lightningcss --minify style.css -o style.min.css */
/* PROD: or: npx cleancss -o style.min.css style.css                       */
/* ── Shared Nav Styles ─────────────────────────────────────────── */
.site-nav {
  display: flex;
  align-items: center;
  padding: 0 32px;
  height: 60px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  gap: 32px;
  font-family: 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.site-nav .nav-brand {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  letter-spacing: -0.3px;
}

.site-nav .nav-brand span { color: var(--accent-ink); }

.site-nav .nav-links {
  display: flex;
  gap: 24px;
  flex: 1;
}

.site-nav .nav-links a {
  color: var(--text2);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  transition: color 0.15s;
}

.site-nav .nav-links a:hover { color: var(--text); }

.site-nav .nav-links a.active { color: var(--accent-ink, var(--accent)); }

.site-nav .nav-cta {
  padding: 8px 18px;
  background: var(--accent2);
  color: #fff;
  border-radius: 6px;
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  transition: background 0.15s;
  white-space: nowrap;
}

.site-nav .nav-cta:hover { background: var(--accent2); }

/* Shared "Log In" / "Sign In" nav link — sits to the left of the CTA on every
   unauthenticated page. Hidden on narrow screens; mobile bottom nav covers it. */
.site-nav .nav-login {
  font-size: 14px;
  font-weight: 600;
  color: var(--text2);
  text-decoration: none;
  padding: 7px 14px;
  border: 1px solid var(--border2);
  border-radius: 6px;
  white-space: nowrap;
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.site-nav .nav-login:hover {
  color: var(--text);
  border-color: var(--accent-ink, var(--accent));
  background: rgba(58,98,224,0.08);
  text-decoration: none;
}

@media (max-width: 600px) {
  .site-nav .nav-login { display: none; }
}

/* ── Reset & Base ──────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

:root {
  --bg:        #0f1117;
  --surface:   #1a1d27;
  --surface2:  #22263a;
  --surface3:  #2a2e42;
  /* Aliases consumed by ported components (e.g. the Project Defaults card).
     Defined per-theme — without these, `var(--card-bg, #1a1d27)` fell back to
     the hardcoded DARK value and rendered dark-on-light once light became the
     default. (Dark values here; light overrides in the [data-theme="light"]
     block below.) */
  --card-bg:   #1a1d27;
  --input-bg:  #22263a;
  --border:    #2e3250;
  --border2:   #3a3f5c;
  --text:      #e2e4f0;
  --text2:     #b0b5cf;   /* was #8b90b0: 4.28:1 on raised, under AA */
  --text3:     #9298bb;   /* was #555a7a: 2.0 to 2.8:1, unreadable on every dark surface */
  /* #3a62e0 is retired. The comment on the line below has said why since it
     was written: white on it is 3.71:1. The split it describes was applied to
     filled buttons and to ONE panel (#rightPanel.panel-expanded #projV4, which
     scopes --accent:#3a62e0 for itself) and never to the app. Promoted here,
     which is what that panel was proving. */
  --accent:    #3a62e0;   /* the FILL. White on it is 4.95:1. */
  --accent2:   #2f50c4;   /* pressed/darker, and white on it is 6.7:1 */
  --accent-ink: #93b0ff;  /* the accent used AS TEXT on dark: 7.0:1 on surface2 */
  --green:     #2dd4bf;
  --orange:    #f97316;
  --red:       #f43f5e;
  --yellow:    #fbbf24;
  --rebar-color: #fb923c;   /* rebar-v1 (Prompt 4) — overlay accent, dark theme */
  --radius:    8px;
  --radius-sm: 5px;
  --canvas-bg: #ffffff;
}

html[data-theme="light"] {
  --bg:        #f5f6fa;
  --surface:   #ffffff;
  --surface2:  #f0f1f5;
  --surface3:  #e4e6f0;
  --border:    #e0e2ed;
  --border2:   #c8cad8;
  --text:      #1a1d27;
  --text2:     #4a4f6a;
  /* Every token in the dark block above carries the ratio it was chosen for.
     This block carried none, and #9096b0 is why: 2.93:1 on white and 1.71:1
     on --surface3, which is the ground the save badge uses. dashboard.html
     found the same number on the same token and fixed it to #5b6270; this is
     that fix, arriving on the surface that needed it most.
     #5b6270 measures 6.15:1 on white and 4.95:1 on --surface3. */
  --text3:     #5b6270;
  /* Dark has had an --accent-ink since it was audited. Light never did, so
     accent-as-text here fell back to the fill. #2f50c4 is the committed ink
     from PRODUCT.md: 6.9:1 on white. */
  --accent-ink: #2f50c4;
  --card-bg:   #ffffff;     /* light override of the ported-component aliases */
  --input-bg:  #f0f1f5;
  --rebar-color: #ea580c;   /* rebar-v1: darker orange for light theme contrast */
  --canvas-bg: #f8f9fc;
}

html { overscroll-behavior: none; }

/* Public Sans, matching surface.css --font and the twenty public pages.
   Inter was removed sitewide on 2026-08-19 as the loudest tell on the slop
   list; the app surfaces were held out of that sweep and kept it. Note this
   rule sets the face DIRECTLY rather than through var(--font), and style.css
   is also loaded by blog, privacy and terms, so those pages were inheriting
   Inter from here too. Stack copied verbatim from surface.css. */
body {
  margin:0;
  font-family:'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background:var(--bg);
  color:var(--text);
  font-size:14px;
  line-height:1.5;
}

/* ── Mobile bottom nav (public pages only) ───────────────────── */
.mob-bottom-nav {
  display: none;
}

@media (max-width: 768px) {
  .mob-bottom-nav {
      display: flex;
      position: fixed; bottom: 0; left: 0; right: 0;
      background: var(--surface);
      border-top: 1px solid var(--border);
      box-shadow: 0 -4px 20px rgba(0,0,0,0.18);
      z-index: 500;
      padding-bottom: env(safe-area-inset-bottom);
    }

  .mbn-item {
      flex: 1; display: flex; flex-direction: column;
      align-items: center; justify-content: center;
      gap: 3px; padding: 8px 4px;
      color: var(--text3); text-decoration: none;
      font-size: 11px; font-weight: 600;
      letter-spacing: 0.2px;
      transition: color 0.15s;
    }

  .mbn-item:hover, .mbn-item.active { color: var(--accent-ink, var(--accent)); }

  .mbn-item svg { flex-shrink: 0; }

  /* Open App button stands out */
  .mbn-item.mbn-cta {
      color: var(--accent-ink, var(--accent));
    }

  .mbn-item.mbn-cta svg {
      background: var(--accent2);
      color: #fff;
      border-radius: 12px;
      padding: 4px;
      width: 32px; height: 32px;
    }

  /* Add padding so footer isn't hidden behind the nav — only on pages that show it */
  body:has(.mob-bottom-nav) { padding-bottom: calc(64px + env(safe-area-inset-bottom)); }
}

@media (max-width: 600px) {
  .site-nav { padding: 0 16px; gap: 12px; }

  .site-nav .nav-links { display: none; }
}

@media (max-width: 768px) {
  button { touch-action:manipulation; }
}

@media print {
  body {
    background:#fff;
    color:#000;
  }
}

/* Native form controls already get good focus styling — keep their
   coloured borders, but lift outline-offset so the ring sits cleanly
   around their box. */
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline-offset: 0;
}

/* Visually-hidden label class for screen-reader / a11y associations on
   inputs that have a visible placeholder instead of a visible label. */
.sr-only {
  position: absolute !important;
  width: 1px !important; height: 1px !important;
  padding: 0 !important; margin: -1px !important;
  overflow: hidden !important; clip: rect(0,0,0,0) !important;
  white-space: nowrap !important; border: 0 !important;
}

/* ============================================================
   MOBILE BOTTOM NAV (Draw · Takeoff · Estimate) — keystone
   discoverability fix. Replaces hidden paths (KPI tap / overflow
   menu) with 3 obvious labeled thumb taps. Mobile (≤768px) only.
   ============================================================ */
#mobBottomNav { display: none; }

@media (max-width: 768px) {
  /* Removed from mobile: the Draw/Takeoff bottom nav sat at z-201 behind the
       z-202 toolbar, so it was half-hidden / untappable ("non-functional"). The
       Takeoff panel is opened by tapping the KPI strip and closed by the panel's
       ✕ Back-to-canvas button, so this duplicate is just hidden. */
  #mobBottomNav { display: none !important; }
}

/* ── Authored for the public site, not extracted ─────────────────────────── */

/* The footer links are inline text, so they were 16px tall on a phone: a third
   of the 44px target, on the surface PRODUCT.md describes as "a phone in a
   truck in sunlight". inline-flex gives them a real box without breaking the
   middot-separated line they sit on, and desktop is left alone because a mouse
   does not need it. */
@media (max-width: 768px) {
  footer a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    /* 10px, so even the shortest labels ("App", "Blog") clear 44 across as
       well as down. WCAG 2.5.5 is a box, not a height. */
    padding: 0 10px;
  }
}
