/* ═══════════════════════════════════════════════════════════════════════════
   EVORRAH — SHARED DESIGN TOKENS
   The one place both surfaces agree. Created 2026-08-03 (branding audit §7).

   WHY THIS FILE EXISTS
   The public site (assets/main.css) and the client portal (styles/portal.css)
   shared ZERO lines of CSS. They were two hand-maintained systems that had
   drifted into using THE SAME VARIABLE NAMES FOR DIFFERENT VALUES, and — worse
   — DIFFERENT NAMES FOR THE SAME VALUE. A designer told "errors are brick"
   could not find brick in the portal, because there it is called --bad.

   WHAT IS IN HERE
   Built in two owner-directed passes on 2026-08-03:
     PASS 1 "Tokens file only — no visible change": the palette, the three
       semantic colour roles under both vocabularies, and the heading scale —
       everything whose value was already IDENTICAL on both surfaces.
     PASS 2 "do the full fix, make the portal match the site": the ROOT FONT
       SIZE and the whole TYPE SCALE moved here too, at the SITE's values. This
       one WAS a visible change and was asked for.

   WHAT PASS 2 ACTUALLY DID, measured before and after in a browser:
     portal root      16px  → 18px on desktop (16px on mobile, as the site does)
     --text-xs        0.69  → 0.72rem     --text-base   0.81 → 0.9rem
     --text-sm        0.75  → 0.78rem     --text-md     0.88 → 1rem
     --text-ui        0.76  → var(--text-sm)   (folded in)
     --text-body      0.82  → var(--text-base) (folded in)
   Net: portal text grew ~12% (root) to ~23% (--text-body) on desktop. Verified
   afterwards: zero horizontal overflow on all five portal tabs at 1440px AND at
   375px, no sideways scroll, every text-entry field still ≥16px on mobile so
   iOS does not zoom, and the PUBLIC SITE measured byte-identical to its
   pre-change baseline.

   ⚠️ STILL NOT SHARED — these genuinely differ and were left alone. Moving any
   of them is another visible change and needs the owner, not a tidy-up:

     token            site (main.css)        portal (portal.css)
     hairline         --border-l             --border
                      rgba(64,100,95,0.30)   rgba(45,16,21,0.08)
                      sage, 30%              ink, 8% — a quarter the weight
     shadows          24 declarations        68 declarations, 3 elevation tokens
     --sp-1..9        defined                not defined

   The hairline is the one that still reads: the site looks drawn, the portal
   looks soft, because its rules are a quarter the weight.

   HOW TO USE
   Linked BEFORE the surface stylesheet in both app/index.html and
   app/client-portal.html, so either file can still override any of it.
   Change a colour here and it changes in both products. That is the point.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Core palette ─────────────────────────────────────────────────────────
     Identical in both files before this change. brand/brand.json is the
     upstream authority for these hexes; this is their runtime home. */
  --ivory:          #FAF6EE;   /* the ground. never pure white. */
  --onyx:           #2D1015;   /* ink */
  --bloodstone:     #922630;   /* ACTION ONLY — never "broken", never decoration */
  --bloodstone-dk:  #7a1f28;
  --sage:           #40645F;
  --sage-dk:        #30504B;
  --greige:         #EEF2F1;
  --gold:           #B8935A;

  /* ── Secondary ink ────────────────────────────────────────────────────────
     MOVED HERE 2026-08-06 (branding audit, critical #5). It lived in
     app/assets/main.css only, and portal.css referenced it FIFTEEN times —
     so every one of those declarations was invalid and dropped, and the
     portal's whole secondary-text layer (captions, sub-labels, helper text,
     table meta) inherited full-strength ink instead of 62% of it. Measured in
     the running portal before the fix: getPropertyValue('--ash') returned
     empty, and a probe with `color:var(--ash)` computed to rgb(45,16,21) —
     i.e. --onyx at 100%. The two-level type hierarchy had collapsed to one.
     Verified before moving: ZERO pages link main.css without tokens.css, so
     nothing loses the token by it living here.
     ⚠ app/brand-assets.html defines its OWN --ash at 0.48 in an inline block
     and links neither file — it is a standalone reference page, left alone
     here, but it is showing a stale alpha. */
  --ash:            rgba(45,16,21,0.62);

  /* ── Semantic roles ───────────────────────────────────────────────────────
     Same three hexes, two vocabularies. The site called them brick/forest/ochre
     and the portal called them bad/success/warn. Both names are defined here so
     neither stylesheet breaks and either spelling keeps working.
     PREFER the brick/forest/ochre names in new code — they are the ones
     brand/brand.json uses, and the reason brick exists at all is so that
     bloodstone never has to mean "broken". */
  --brick:          #B54834;   /* ERRORS ONLY */
  --forest:         #2D6A4F;   /* success */
  --ochre:          #B7791F;   /* warning — the house amber, not CRM gold */

  --bad:            var(--brick);    /* alias — portal.css spelling */
  --success:        var(--forest);   /* alias — portal.css spelling */
  --warn:           var(--ochre);    /* alias — portal.css spelling */

  /* ── Type scale — ONE scale, both surfaces ────────────────────────────────
     2026-08-03, owner: "do the full fix, make the portal match the site".
     These are the SITE's values. The portal previously ran its own, smaller
     set (xs .69 / sm .75 / base .81 / md .88) on a 16px root while the site
     used these on an 18px root — so the same token name rendered 15–22%
     smaller once a client logged in. Both now resolve identically. */
  --text-micro:     0.62rem;
  --text-xs:        0.72rem;
  --text-sm:        0.78rem;
  --text-base:      0.9rem;
  --text-md:        1rem;

  /* Portal-only names, kept so ~500 existing portal rules keep working.
     They were .76 and .82 against a base of .81 — i.e. "a touch under base"
     and "base". Folded into the shared scale rather than carried as two more
     near-duplicate numbers. */
  --text-ui:        var(--text-sm);
  --text-body:      var(--text-base);

  --h3:             1.05rem;
  --h2-sm:          clamp(1.5rem, 2.8vw, 2.4rem);
  --h2:             clamp(1.8rem, 3.6vw, 3rem);
  --h2-display:     clamp(2.2rem, 5vw, 4rem);

  /* ── Tracking — the four named values from brand/brand.json, plus one ──────
     concession the code clearly needs. Measured 2026-08-06: main.css runs 207
     letter-spacing declarations across 28 distinct values, portal.css 524
     across 47 — a continuum, not a scale, and the two sides of the login do
     not agree (main.css leans 0.14em, portal.css leans .16em). --tr-ui exists
     because 0.14em and 0.16em together account for ~144 declarations and
     rounding them all to 0.18em would be a visible change. ADOPT THESE AS
     RULES ARE TOUCHED. Do not sweep the stylesheets in one pass. */
  --tr-body:        0;
  --tr-ui:          0.14em;
  --tr-tight:       0.18em;
  --tr-label:       0.24em;
  --tr-seal:        0.30em;
}

/* ── Root size — the other half of "the portal shrinks when you pay" ────────
   The site set 112.5% (18px) and dropped to 100% (16px) on phones; the portal
   set nothing at all, so it was 16px everywhere. That is why the step-down was
   DESKTOP-ONLY — on mobile the two already agreed. Defined here once so both
   surfaces move together. Media queries are unaffected by this (they resolve
   rem against the initial 16px, not against :root), so no breakpoint shifts. */
html { font-size: 112.5%; }
@media (max-width: 768px) { html { font-size: 100%; } }

/* ── Focus ring ─────────────────────────────────────────────────────────────
   This rule was already byte-identical in main.css and portal.css. Keyboard
   users get one consistent brand signal across the whole product; it now has
   one definition instead of two copies that could drift apart. */
*:focus-visible {
  outline: 2px solid var(--bloodstone);
  outline-offset: 2px;
}
