/* ============================================================================
   PropertyMeasure Admin — design tokens
   ============================================================================
   THE single definition of colour, type, radius, shadow and page width for the
   admin tool. Before this file, admin.css / clients.css / cadstyles.css /
   login.css and five inline <style> blocks each redeclared the same values from
   scratch — which is how the tool ended up with five font stacks, twelve
   shadows, twelve corner radii, and the same font sizes written in both px and
   rem. Every one of those was a symptom of having nowhere to put a decision.

   Rules:
   - Change a value HERE, never at the call site.
   - The admin has no build step, so these are plain CSS custom properties.
     Load this file FIRST on every page, before any other stylesheet.
   - Measurement LAYER colours (Soft Edge, Road Side, etc.) are NOT in this file.
     They live in constants.js and encode which layer a shape is — a categorical
     data palette that must stay mutually distinguishable over aerial imagery.
     Do not fold them into the brand.
   ========================================================================== */

:root {
  /* ── Brand ───────────────────────────────────────────────────────────────
     Two hexes only. The admin was already clean here — no near-duplicates,
     unlike the client app which had five. Keep it that way. */
  --brand-green:       #1F9352;
  --brand-green-dark:  #17703F;   /* hover / pressed / text-on-light */
  --brand-green-tint:  #E8F2EC;   /* success wash, selected rows */
  --brand-blue:        #056E9D;
  --brand-blue-dark:   #044F72;
  --brand-blue-tint:   #E4F1F8;

  /* ── Neutrals ────────────────────────────────────────────────────────────
     One ramp, already consistent across the tool. Preserved as-is. */
  --grey-50:   #F9FAFB;
  --grey-100:  #F3F4F6;
  --grey-200:  #E5E7EB;
  --grey-300:  #D1D5DB;
  --grey-400:  #9CA3AF;
  --grey-500:  #6B7280;
  --grey-600:  #4B5563;
  --grey-700:  #374151;
  --grey-900:  #111827;
  --white:     #FFFFFF;

  /* Semantic — deliberately separate from brand, so "success" never competes
     with "this is our product". */
  --ok:        #17703F;
  --ok-wash:   #E8F2EC;
  --warn:      #92400E;
  --warn-wash: #FEF3C7;
  --danger:    #DC2626;
  --danger-wash: #FEE2E2;

  /* ── Type ────────────────────────────────────────────────────────────────
     Six steps, one unit. px chosen over rem because the admin has no
     user-scaling requirement and mixing the two is what caused the drift:
     0.875rem and 14px are the same size written two ways.
     Floor is 11px — the tool is stared at all day, and 8/9px text was both
     an accessibility failure and a genuine source of eye strain.

     The three display steps are FLUID, keyed to a 360px -> 1440px viewport: a
     24px page title is right on a laptop and crowds a tablet held in portrait.
     The two smallest steps stay fixed on purpose — a label that shrinks below
     11px stops being readable, and no amount of viewport justifies that. Each
     clamp tops out at the exact value the token had before, so nothing moves at
     the design width; the scale only ever compresses below it. */
  --text-xs:   11px;   /* uppercase labels only, with tracking — fixed */
  --text-sm:   12px;   /* fixed */
  --text-base: clamp(13px, 12.67px + 0.09vw, 14px);   /* the workhorse */
  --text-md:   clamp(14px, 13.33px + 0.19vw, 16px);
  --text-lg:   clamp(17px, 16.00px + 0.28vw, 20px);
  --text-xl:   clamp(19px, 17.33px + 0.46vw, 24px);

  --font-sans: Inter, system-ui, -apple-system, Roboto, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", Consolas, monospace;

  /* Display type is spaced for body sizes; large headings need tightening. */
  --tracking-tight: -0.022em;
  --tracking-label:  0.08em;

  /* ── Radius ──────────────────────────────────────────────────────────────
     Three tiers, encoding SCALE: a small control gets a small corner, a large
     surface a larger one. An 8px button inside an 8px card reads flat. */
  --radius-sm:   6px;    /* inputs, chips, small buttons */
  --radius-md:  10px;    /* buttons, cards */
  --radius-lg:  16px;    /* panels, modals */
  --radius-pill: 9999px; /* status pills ONLY */

  /* ── Depth ───────────────────────────────────────────────────────────────
     Two layers, tinted with the ink navy rather than flat black. A single
     layer of black at 10% is what makes a UI look papery rather than seated. */
  --shadow-1: 0 1px 2px rgba(14, 31, 45, .04), 0 8px 24px rgba(14, 31, 45, .06);
  --shadow-2: 0 2px 4px rgba(14, 31, 45, .06), 0 16px 40px rgba(14, 31, 45, .10);
  --shadow-brand: 0 4px 14px rgba(31, 147, 82, .18);
  --ring-brand: 0 0 0 3px rgba(31, 147, 82, .14);

  /* ── Tool chrome (light) ─────────────────────────────────────────────────
     The chrome palette for the editors, the shell bar and every floating panel.
     Everything that used to be hard-coded #fff / #e5e7eb / #111827 across four
     stylesheets now resolves from here, so the whole surface can be retuned by
     editing this block alone.

     A dark variant was trialled and rejected. Two reasons it was the wrong call
     here, both worth recording so it is not retried by accident:
       1. The panels carry a lot of small text — layer names, areas, running
          totals. Dark grounds make that harder to scan, not easier.
       2. It required every text colour in the editor to be re-declared. One
          that was missed (the layer name) rendered dark-on-dark and vanished.

     The neutrals below are very slightly COOL rather than pure grey, which sits
     correctly against the green-blue brand instead of fighting it. Surfaces are
     white; the ground behind them is a soft tint so panels read as raised
     without needing heavy shadows. */
  --chrome-bg:        #EDF1F4;
  --chrome-surface:   #FFFFFF;
  --chrome-raised:    #F2F6F8;
  --chrome-border:    #E0E7EC;
  --chrome-ink:       #0F1F2B;
  --chrome-ink-2:     #445A69;
  --chrome-muted:     #6B808F;
  --chrome-accent:    #1F9352;
  --chrome-accent-2:  #056E9D;
  --chrome-accent-wash: rgba(31, 147, 82, .12);
  --chrome-shadow:    0 1px 2px rgba(14, 31, 45, .05), 0 8px 24px rgba(14, 31, 45, .08);

  /* ── Layout ──────────────────────────────────────────────────────────────
     Was 1280px everywhere, which left ~320px of white on each side of a
     1920px screen. Fills the viewport with breathing room instead; the cap
     only engages on ultrawide, where edge-to-edge reads as broken. */
  --container-max: 1920px;
  --container-pad: 2rem;

  /* ── Legacy aliases ──────────────────────────────────────────────────────
     admin.css and login.css EACH defined their own copy of this colour set —
     two independent declarations of the same values, free to drift apart, and
     invisible to any page that loads neither (the aerial editor, CAD editor,
     estimator, project selection and 404 all reference nothing). Re-declared
     here so the names resolve from ONE place on EVERY page.

     The originals are left in place deliberately: they redeclare identical
     values after this file loads, so behaviour is unchanged today, and they can
     be deleted in a follow-up once each page is confirmed loading tokens.css.
     American spelling kept — renaming ~200 call sites buys nothing. */
  --primary-start: #1F9352;
  --primary-end:   #056E9D;
  --gray-50:  #F9FAFB;
  --gray-100: #F3F4F6;
  --gray-200: #E5E7EB;
  --gray-300: #D1D5DB;
  --gray-400: #9CA3AF;
  --gray-500: #6B7280;
  --gray-600: #4B5563;
  --gray-700: #374151;
  --gray-800: #1F2937;
  --gray-900: #111827;
  --status-pending:  #FCD34D;
  --status-approved: #34D399;
  --status-rejected: #EF4444;
}

/* ── Breakpoints ────────────────────────────────────────────────────────────
   FIVE tiers, shared with the client app (mirrored in its tailwind.config.js).
   The admin previously used seven different values — 768 ×6, 600 ×2, 640 ×2,
   plus 480 / 900 / 1024 / 1180 once each — which is another way of saying it
   had no system, and is why pages break at different widths from each other.

     phone      <= 640      single column; sidebars become sheets; tables become cards
     tablet     641-1024    sidebar collapses to icons; TOUCH TARGETS GROW to 44px
     laptop     1025-1440   the design target — everything visible, one toolbar row
     desktop    1441-1920   wider canvas, more table columns
     ultrawide  > 1920      capped and centred by --container-max

   CSS custom properties cannot be used inside a @media condition, so these
   cannot be literal variables — the values below are the contract. Use these
   numbers and no others.
   -------------------------------------------------------------------------- */
:root {
  --bp-phone: 640px;
  --bp-tablet: 1024px;
  --bp-laptop: 1440px;
  --bp-desktop: 1920px;

  /* Comfortable minimum for a finger. Applied at tablet and below, where the
     device is likely touch — a 30px control is right for a mouse and too small
     for a tablet on a truck dashboard. */
  --touch-min: 44px;
}

@media (max-width: 1024px) {
  :root { --container-pad: 1.5rem; }
}

@media (max-width: 640px) {
  :root { --container-pad: 1rem; }
}

/* ── Nothing scrolls sideways ────────────────────────────────────────────────
   Same floor the client app sets, for the same reason: a horizontal scrollbar on
   a page with no wide content is the commonest "it doesn't fit my screen"
   report, and the culprit is never the element you can see.

   `clip` rather than `hidden`: `hidden` makes the element a scroll container and
   silently breaks `position: sticky`, which the order table headers and the
   estimator's toolbars rely on. `clip` contains without creating a scroll port.

   Wide content still needs its own `overflow-x: auto` wrapper — see
   `.table-container` in admin.css. Clip is a backstop, not a substitute. */
html {
  overflow-x: clip;
}

body {
  max-width: 100%;
  overflow-x: clip;
}

img, svg, video, iframe {
  max-width: 100%;
}

/* Note on viewport heights: every `height: 100vh` in this tool is followed by a
   `height: 100dvh` on the next line. 100vh counts the space BEHIND a mobile
   browser's collapsible toolbars, so a 100vh editor is taller than what is
   actually visible and the map runs off the bottom of the screen. 100dvh is the
   height really on screen. Browsers that predate dvh ignore the second
   declaration and keep the first, so no @supports guard is needed. */

/* Page header. Sits UNDER the shell bar and carries only what is page-specific:
   the title, and any action that has no home in the global nav. Global concerns
   (brand, section nav, signed-in user, sign-out) belong to the shell and must not
   be repeated here — that duplication is what put two headers on every page. */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.page-head h1 {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--chrome-ink);
}

.page-head-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Editor exit control. Neither editor had one — the browser back button was the
   only way out of a takeoff. Sized to match the sidebar's other icon button. */
.back-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border: 1px solid var(--chrome-border);
  border-radius: var(--radius-sm);
  background: var(--chrome-surface);
  color: var(--chrome-ink-2);
  text-decoration: none;
  transition: background .15s, color .15s, border-color .15s;
}

.back-btn:hover {
  background: var(--chrome-accent-wash);
  color: var(--chrome-accent);
  border-color: var(--chrome-accent);
}

.back-btn:focus-visible {
  outline: 2px solid var(--chrome-accent);
  outline-offset: 2px;
}

.back-btn .icon { width: 1.05rem; height: 1.05rem; }

@media (max-width: 1024px) {
  .back-btn { width: var(--touch-min); height: var(--touch-min); }
}

/* Shared page shell. Any full-width admin surface can use this directly
   instead of redeclaring a max-width. */
.pm-container {
  width: 100%;
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--container-pad);
}
