/* =============================================================================
   SEMANTIC TOKENS — the intent layer.
   -----------------------------------------------------------------------------
   These are the ONLY tokens components and screens are allowed to use. Each one
   aliases a primitive (--p-*) and is named for its INTENT ("what it's for"),
   not its value. Swap a primitive here to re-theme the whole app.

   Rules:
   • Every value here is a var(--p-*) reference — NO raw literals.
   • Components/screens reference these names; they never touch --p-* directly.
   • Need a new intent? Add the raw value to primitives.css, then alias it here.

   BRAND: TrueUp / Stiles. Crimson is the single accent; Slate is the dark
   surface + credit; Ink on Paper; Mist/Cloud neutrals. Warning states fold to
   neutral Slate/Mist (no second accent); success stays green but sparing.
   ========================================================================== */
:root {
  /* ── Brand / accent (Crimson) ─────────────────────────────────────────────
     One accent only — CTAs, links, active/selected states, accent bars. */
  --color-accent:          var(--p-crimson);
  --color-accent-hover:     var(--p-crimson-hover);
  --color-accent-strong:    var(--p-crimson-hover);
  --color-accent-muted:     var(--p-crimson);
  --color-accent-subtle:    var(--p-crimson-06);
  --color-accent-bg:        var(--p-crimson-06);
  --color-accent-bg-strong: var(--p-crimson-12);
  /* Find-in-lease, marked over the SOURCE PAGE IMAGE — translucent so the lease text under it
     stays readable (a solid fill would hide the very words the manager searched for). */
  --color-find-mark:        var(--p-crimson-26);
  --color-find-mark-edge:   var(--p-crimson-50);
  --color-accent-light:     var(--p-crimson-light);   /* accent on dark surfaces */

  /* Brand mark bars — the equals-sign logo. Slate top bar + crimson bottom bar;
     reversed variants (white / light-crimson) for slate/dark surfaces. */
  --color-brand-slate:          var(--p-slate);
  --color-brand-crimson:        var(--p-crimson);
  --color-brand-on-dark:        var(--p-white);
  --color-brand-accent-on-dark: var(--p-crimson-light);

  /* ── Status ───────────────────────────────────────────────────────────────
     Success = green (sparing). "Owes" reads in Crimson (danger); "credit"
     reads in Slate. Warning has no colour of its own — it folds to neutral. */
  --color-success:          var(--p-green);
  --color-success-text:      var(--p-green);
  --color-credit:           var(--p-slate);
  --color-warning:          var(--p-slate);
  --color-warning-text:      var(--p-slate);
  --color-warning-text-strong: var(--p-slate);
  --color-warning-accent:    var(--p-mist);
  --color-danger:           var(--p-crimson);
  --color-danger-strong:     var(--p-crimson-hover);

  /* ── Text ───────────────────────────────────────────────────────────────── */
  --color-text-primary:      var(--p-ink);
  --color-text-heading:      var(--p-ink);
  --color-text-secondary:    var(--p-ink-72);
  --color-text-body:         var(--p-ink-72);
  --color-text-muted:        var(--p-ink-55);
  --color-text-subtle:       var(--p-ink-55);
  /* Faint TEXT tier. Was --p-mist — a BORDER grey, only ~1.5:1 on the canvas and
     unreadable as text. Point it at the muted ink so de-emphasized copy stays subtle
     but legible (~3.4:1). Non-text greys (fills/dots) use --color-na / --color-border,
     not this token. */
  --color-text-faint:        var(--p-ink-55);
  --color-text-placeholder:  var(--p-mist);
  --color-text-on-accent:    var(--p-white);

  /* ── Surfaces / backgrounds ───────────────────────────────────────────────*/
  --color-canvas:                  var(--p-paper);
  --color-surface:                 var(--p-white);
  --color-surface-dark:            var(--p-slate);   /* dark bands, table heads */
  --color-surface-sunken:          var(--p-paper);
  --color-surface-sage:            var(--p-paper);
  --color-surface-muted:           var(--p-cloud);
  --color-surface-info:            var(--p-cloud);
  --color-surface-warning:         var(--p-cloud);
  --color-surface-warning-strong:  var(--p-cloud);
  --color-surface-danger:          var(--p-crimson-06);
  --color-surface-success:         var(--p-green-12);
  --color-surface-success-strong:  var(--p-green-12);
  --color-surface-neutral:         var(--p-cloud);
  --color-surface-slate:           var(--p-slate-12);   /* soft slate tint — muted, non-CTA task chips */

  /* ── Borders / lines ──────────────────────────────────────────────────────*/
  --color-border:                 var(--p-mist);
  --color-border-strong:           var(--p-mist);
  --color-border-subtle:           var(--p-cloud);
  --color-border-faint:            var(--p-cloud);
  --color-border-sage:             var(--p-cloud);
  --color-border-accent:           var(--p-crimson);
  --color-border-success:          var(--p-green-30);
  --color-border-success-subtle:   var(--p-green-30);
  --color-border-warning:          var(--p-mist);
  --color-border-danger:           var(--p-crimson-12);
  --color-border-slate:            var(--p-slate-light);   /* muted teal-grey — non-CTA task chips */
  --color-divider:                 var(--p-cloud);

  /* ── Stacking plan — lease time-to-expiry encoding ─────────────────────────*/
  /* Two on-brand families: crimson escalates through the danger zone (rolling →
     expired); a slate ordinal ramp deepens across the safe horizon (near → far).
     No new accent hue — stays Ink-on-Paper. Validated CVD-distinct; blocks always
     carry text labels, satisfying the sub-3:1 relief on the lightest slate. */
  --color-lease-expired:        var(--p-crimson);       /* past expiry            */
  --color-lease-rolling:        var(--p-crimson-light);  /* ≤ 12 months           */
  --color-lease-horizon-near:   var(--p-slate-light);    /* 1–3 years             */
  --color-lease-horizon-mid:    var(--p-slate-mid);      /* 3–5 years             */
  --color-lease-horizon-far:    var(--p-slate);          /* 5 years +             */
  --color-lease-vacant-line:    var(--p-mist);           /* vacant hatch          */
  --color-scrim:                var(--p-scrim);          /* modal / lightbox backdrop */

  /* ── Interactive markers (nav pins, steppers, dots) ────────────────────────*/
  --color-pin-active:    var(--p-crimson);
  --color-pin-inactive:  var(--p-mist);

  /* ── Misc roles ─────────────────────────────────────────────────────────── */
  --color-arrow:        var(--p-mist);
  --color-na:           var(--p-mist);
  --color-slate-text:    var(--p-slate);
  --color-slate-icon:    var(--p-slate);
  --color-slate-border:  var(--p-slate);

  /* ── Spacing scale ───────────────────────────────────────────────────────── */
  --space-0:  var(--p-space-0);
  --space-1:  var(--p-space-1);
  --space-2:  var(--p-space-2);
  --space-4:  var(--p-space-4);
  --space-6:  var(--p-space-6);
  --space-8:  var(--p-space-8);
  --space-10: var(--p-space-10);
  --space-12: var(--p-space-12);
  --space-14: var(--p-space-14);
  --space-16: var(--p-space-16);
  --space-20: var(--p-space-20);
  --space-24: var(--p-space-24);
  --space-28: var(--p-space-28);
  --space-32: var(--p-space-32);
  --space-36: var(--p-space-36);
  --space-40: var(--p-space-40);
  --space-44: var(--p-space-44);
  --space-48: var(--p-space-48);
  --space-64: var(--p-space-64);

  /* ── Radii — all resolve to 0 (square corners are the brand signature). ──── */
  --radius-xs:     var(--p-radius-xs);
  --radius-sm:     var(--p-radius-sm);
  --radius-md:     var(--p-radius-md);
  --radius-lg:     var(--p-radius-lg);
  --radius-xl:     var(--p-radius-xl);
  --radius-2xl:    var(--p-radius-2xl);
  --radius-3xl:    var(--p-radius-3xl);
  --radius-pill:   var(--p-radius-pill);
  --radius-full:   var(--p-radius-full);
  --radius-circle: var(--p-radius-circle);

  /* ── Typography ──────────────────────────────────────────────────────────── */
  --text-7:       var(--p-text-7);
  --text-11:      var(--p-text-11);
  --text-12:      var(--p-text-12);
  --text-13:      var(--p-text-13);
  --text-14:      var(--p-text-14);
  --text-15:      var(--p-text-15);
  --text-16:      var(--p-text-16);
  --text-18:      var(--p-text-18);
  --text-20:      var(--p-text-20);
  --text-24:      var(--p-text-24);
  --text-display: var(--p-text-display);

  --weight-light:    var(--p-weight-light);
  --weight-regular:  var(--p-weight-regular);
  --weight-medium:   var(--p-weight-medium);
  --weight-semibold: var(--p-weight-semibold);
  --weight-bold:     var(--p-weight-bold);

  --tracking-tighter: var(--p-tracking-tighter);
  --tracking-1:       var(--p-tracking-1);
  --tracking-2:       var(--p-tracking-2);
  --tracking-4:       var(--p-tracking-4);
  --tracking-5:       var(--p-tracking-5);
  --tracking-6:       var(--p-tracking-6);
  --tracking-8:       var(--p-tracking-8);

  --font-serif: var(--p-font-serif);
  --font-sans:  var(--p-font-sans);
  --font-mono:  var(--p-font-mono);

  /* ── Elevation ───────────────────────────────────────────────────────────── */
  --shadow-sm:        var(--p-shadow-sm);
  --shadow-md:        var(--p-shadow-md);
  --shadow-lg:        var(--p-shadow-lg);
  --shadow-raised:    var(--p-shadow-raised);
  --shadow-statement: var(--p-shadow-statement);
  --shadow-hover:     var(--p-shadow-hover);
  --shadow-focus:     var(--p-shadow-focus);

  /* ── Border widths ───────────────────────────────────────────────────────── */
  --border-hairline: var(--p-border-hairline);
  --border-thin:     var(--p-border-thin);
  --border-thick:    var(--p-border-thick);
  --border-accent:   var(--p-border-accent);
  --border-bar:      var(--p-border-bar);

  /* ── Redesign (theme-new) additive semantic tokens ───────────────────────────
     Intent names the "new" UI (styles/theme-new.css) resolves against. ADDITIVE
     ONLY — every one is a brand-new name aliasing a new primitive; nothing
     existing is re-aliased, so the current UI is byte-identical. Only add the
     token names theme-new.css actually references (audited). */
  --text-10:      var(--p-text-10);
  --text-22:      var(--p-text-22);
  --text-30:      var(--p-text-30);
  --text-32:      var(--p-text-32);
  --space-18: var(--p-space-18);
  --space-22: var(--p-space-22);
  --space-26: var(--p-space-26);
  --tracking-tight:   var(--p-tracking-tight);
  --tracking-10:      var(--p-tracking-10);
  --color-on-dark-body:    var(--p-on-dark-75);
  --size-320:         var(--p-size-320);   /* card min-width — lease-intelligence grid track */
  --size-232:         var(--p-size-232);   /* tile min-width — property-hub inventory grid track */
  --size-clause:      var(--p-size-440);   /* a verbatim lease quote sitting in a table of figures */
  --size-prose:       var(--p-size-680);   /* max width of a column of prose meant to be READ, not scanned */
  --size-stat:        var(--p-size-150);   /* one number-and-label tile in a summary grid */
  --size-nav:         var(--p-size-72);    /* sticky nav height — offset for anything sticky beneath it */
  --size-factgrid:    var(--p-size-560);   /* the per-lease fact grid: below this its cells wrap to three lines */
  --size-wf-rail:     var(--p-size-44);    /* the guided-flow rail's own height */
  --size-wf-dot:      var(--p-size-26);    /* one numbered step on that rail */
  --size-wf-link:     var(--p-size-14);    /* the hairline connector between two steps */
  --size-crumb:       var(--p-size-crumb); /* the "back to the property" crumb band — see --size-return-band */
  /* How far a sticky element under the nav must ALSO clear the return crumb. The crumb is
     one shared button rendered into whichever screen slot is showing (renderPropReturn), so
     its presence is a single global fact and lives on <html> — which means a sticky element
     ANYWHERE can offset itself by it, with no measuring and no resize listener. Zero when
     there is no crumb, so the common case costs nothing. A LENGTH (--p-size-0), because
     `--p-space-0` is unitless and `calc(72px + 0)` is invalid CSS. */
  --size-return-band: var(--p-size-0);
  /* Inset anything pinned to a screen edge by these, or the system UI sits on top of it. */
  --safe-top:         var(--p-safe-top);
  --safe-right:       var(--p-safe-right);
  --safe-bottom:      var(--p-safe-bottom);
  --safe-left:        var(--p-safe-left);
}

/* The nav is shorter at phone widths (one row: Portfolio · New · Admin + avatar), so the
   offset every sticky element uses has to shrink with it — otherwise a "sticky below the
   nav" element floats with a gap, or slides under it. One token, redefined once, keeps
   every such element correct at both widths (the property tab strip, the return crumb).
   A smoke test asserts they actually sit below the nav at phone width, so a future nav
   that changes height fails loudly instead of drifting. */
/* 560px, NOT 640: that is where app.css gives the nav `min-height: 0` and it becomes one
   compact row. Getting this boundary wrong is silent and ugly — at exactly 640px the token
   shrank while the nav did not, and the property tab strip sat 19px UNDERNEATH it. Measured,
   not guessed; a smoke test now checks both sides of the boundary. */
@media (max-width: 560px) {
  :root { --size-nav: var(--p-size-53); }
}

/* The rail and its dots shrink with the nav, for the same reason: three pinned bands (nav +
   crumb + rail) on a 780px phone is a fifth of the screen, and the "earn its screen" rule in
   CLAUDE.md is measured, not judged. */
@media (max-width: 640px) {
  :root {
    --size-wf-rail: var(--p-size-38);
    --size-wf-dot:  var(--p-size-22);
  }
}

/* Set by renderPropReturn whenever the crumb is actually rendered. */
html.has-prop-return { --size-return-band: var(--size-crumb); }
