/* ironvail-house v2
 *
 * THE HOUSE TOKENS. Canonical copy of this file and the reasoning behind it:
 * The-Vault → Projects/Brands/ironvail-house-brand.md
 *
 * THIS FILE IS BYTE-IDENTICAL IN EVERY IRONVAIL APP — IronVail Standard,
 * IronVail Run Co. and IronVail CRM. There is no shared package to install
 * from: one of the four repositories that carries the identity is an Obsidian
 * vault, and a private registry for three files is machinery nobody will
 * maintain. So the system travels by copy, with a version stamp on the first
 * line, and `diff brand/house.css` across two checkouts is the whole drift
 * check. Bumping the stamp is a deliberate, greppable event.
 *
 * AN APP MAY ADD TOKENS. AN APP MAY NOT REDEFINE ONE. Redefining `--gold` in
 * one product is how a house ends up with three golds that nearly agree, which
 * is worse than three that plainly differ — nobody can see it, so nobody fixes
 * it. `scripts/verify-house.mjs` fails the build on both counts.
 *
 * DARK, ALWAYS. Not a system preference and not a toggle: the look was chosen
 * as a whole, and half of what makes it read as expensive is that the surfaces,
 * the shadows and the accent were tuned against one another on one ground. A
 * light mode is a second design, not a filter over this one, and inventing it
 * automatically would produce neither.
 *
 * JET, GOLD AND GREY. The gold is SAMPLED FROM THE LION — brand/lion.jpeg's
 * dominant colour, OKLCh L 0.83 C 0.15 h 87 — so the mark and the interface are
 * the same colour rather than two colours that nearly agree. The surfaces are
 * NEUTRAL greys: an earlier set was blue-cast (#14181E, #1C222A) and against a
 * warm gold that reads as navy-and-mustard rather than as jet-and-gold. Most of
 * what makes this palette land is the blue coming out of the greys.
 *
 * EVERY COLOUR BELOW WAS COMPUTED, NOT CHOSEN BY EYE. Contrast ratios and
 * colourblind separations are stated beside the values they describe and are
 * recomputed in the brand doc. (An earlier version of this header cited a
 * `scripts/validate_palette.js` that has never existed in any of these repos —
 * an instruction that cannot be followed is worse than none, and it was one
 * copy-paste away from being propagated into two more codebases.)
 */

:root {
  /* ---- ground and surfaces ---------------------------------------------
   * An elevation scale, not one card colour. A single surface plus a 1px
   * shadow makes every page a stack of identical boxes with no rhythm and
   * nothing to signal what sits on top of what.
   *
   * ON A DARK GROUND, DEPTH IS LIGHTNESS. A card is lighter than the page and
   * an inset is lighter still. The light-theme habit of tinting a raised
   * surface *darker* inverts the whole model and nothing throws, so the
   * ordering below is an invariant, not a preference:
   *     ground  <  leaf  <  leaf-2  <  leaf-3
   *
   * Neutral, deliberately: chroma under 0.005 at every step. A card with a
   * blue cast under a gold accent is the single thing that made three earlier
   * drafts read as cheap. */
  --ground:      #08090B;  /* the page — jet */
  --leaf:        #121316;  /* a card */
  --leaf-2:      #1A1C20;  /* pressed, and insets inside a card */
  --leaf-3:      #23262B;  /* meter tracks, skeletons, inputs, popovers */

  /* ---- ink --------------------------------------------------------------
   * Contrast on a card (#121316): 16.7 / 8.1 / 4.0. --ink-faint is BELOW the
   * 4.5:1 floor for normal text and that is not an oversight — it is the
   * decorative tier, and the moment it carries a label or a control it is a
   * bug. Assert it at 3:1, never at 4.5. */
  --ink:         #F2F3F4;
  --ink-soft:    #A8ABB0;
  --ink-faint:   #70747A;  /* decorative only — never a control */

  /* ---- rules ------------------------------------------------------------
   * --rule divides INSIDE a surface; --rule-strong is the edge OF one. Neither
   * clears 3:1 against a card, because neither is a UI component boundary — a
   * form field's border is, and it uses --ink-faint for exactly that reason. A
   * compliant field border is lighter than a quiet dark palette wants, and it
   * does not get to be resolved in the border's favour. */
  --rule:        #26282D;
  --rule-strong: #3A3D43;

  /* ---- the gold ---------------------------------------------------------
   * ONE accent, used sparingly, and gold demands MORE restraint than a blue or
   * an indigo rather than less: gold everywhere reads as cheap, gold on exactly
   * one thing per screen reads as expensive. What is allowed to be gold is a
   * short list, and it lives in the brand doc and in each app's ui primitives.
   *
   * 10.9:1 as text on a card. Jet on gold is 11.7:1 — the button fill is the
   * highest-contrast pairing in the app, which is the right way round for the
   * one control a screen wants you to press.
   *
   * --on-rubric IS NOT OPTIONAL. White on this gold is 1.70:1. Any app that
   * paints text on an accent fill and reaches for `text-white` has shipped an
   * unreadable button, and it will look fine to whoever wrote it. */
  --gold:        #F0C040;  /* sampled from brand/lion.jpeg */
  /* THE SECOND BRAND COLOUR, and it is the metal rather than an accent.
   *
   * The mark is two-tone: the crown, its band and rim, and the chevron on the
   * forehead are IRON, and the lion under them is gold. The wordmark says the
   * same thing — "Iron" in this, "Vail" in gold — so the name and the drawing
   * are one idea instead of two that happen to sit together.
   *
   * IT IS NOT AN ACCENT AND MUST NOT BEHAVE LIKE ONE. Gold is what a screen
   * spends on its single most important thing; iron is a material the identity
   * is made of. Painting a button in it would give a screen two primaries, and
   * the reason the short gold list exists is that a screen can only have one.
   * 6.34:1 on the ground and 5.91:1 on a card, so it clears the text floor —
   * which it needs to, because "Iron" is half the product name and not a
   * caption. The two lighter greys tried first (#C7CBD1, #A8ABB0) read as
   * chrome beside the gold rather than as iron, and at 32px and below the
   * brighter one started competing with the mark it was supposed to sit under.
   */
  --iron:        #8C9298;
  --rubric:      var(--gold);
  --rubric-deep: #FFD463;  /* pressed — LIGHTER on a dark ground, not darker */
  --on-rubric:   #08090B;
  --link:        var(--gold);

  /* ---- status -----------------------------------------------------------
   * THE ALARM CANNOT BE THE ACCENT, because gold IS amber. A meter that fills
   * --rubric when it is fine and amber when it is over would be one hue doing
   * both jobs, and the most load-bearing colour distinction in a budget
   * collapses into nothing.
   *
   * So gold is the brand, red is the alarm, green is the all-clear. Gold vs
   * red measures dE 20.0 deutan / 22.7 tritan — a wide, safe separation.
   *
   * Red vs green is the classic 6.4 dE deutan, which is legal ONLY with
   * secondary encoding: a badge renders a WORD, a stat pairs its tone with a
   * label. A bare coloured dot is not a signal to roughly one man in twelve. */
  --warn:        #E0574E;  /* over, overdue, failed — 5.0:1 on a card */
  --good:        #3FB27C;  /* cleared, paid, on track — 7.0:1 on a card */

  /* ---- semantic pairs ---------------------------------------------------
   * A tinted chip with its own text colour, for the apps that need badges
   * rather than a bare tone. THE HOUSE GREW THESE FOR THE CRM: it carries four
   * bg/fg pairs and the two status colours above could not supply them without
   * breaking two of the house's own rules — a gold "warning" collides with the
   * brand accent, and a --series-2 "info" is a chart colour outside a chart.
   *
   * Each fg is TEXT ON ITS OWN BG and owes 4.5:1 at the 11px these are set in.
   * The margins are deliberately fat (6.3–8.9 rather than the ~4.7 the obvious
   * picks land on): on a dark ground the backgrounds sit only 1.03–1.16 from
   * their container, so the fg is doing nearly all of the work.
   *
   * --neg-fg is a LIGHTER red than --warn on purpose. --warn on its own tint is
   * 4.73:1 — within a hundredth of the class of miss that survives review
   * forever. --warn stays the signal colour for icons, meters and dots, where
   * the 4.5 floor does not apply. */
  --pos-bg:  #0D1F17;  --pos-fg:  #4FC98D;  /* 8.22:1 */
  --neg-bg:  #241110;  --neg-fg:  #F0736A;  /* 6.33:1 */
  --warn-bg: #231A0B;  --warn-fg: #E9B14A;  /* 8.87:1 — NOT the rubric gold */
  --info-bg: #0F1A29;  --info-fg: #6BA0E4;  /* 6.48:1 */

  /* ---- films ------------------------------------------------------------
   * Hover, selection and hairline as alpha over whatever is beneath. WHITE, at
   * low alpha. The light-theme values for these are rgba(0,0,0,…), and black
   * over jet is invisible — a hover state that does nothing, on every row of
   * every table, with no error anywhere. The alphas are NOT the light theme's
   * numbers inverted: white at 8% on #08090B is not the perceptual twin of
   * black at 8% on #fbfbfa. */
  --hairline: rgb(255 255 255 / 0.07);
  --hover:    rgb(255 255 255 / 0.045);
  --sel:      rgb(255 255 255 / 0.06);

  /* ---- chart series -----------------------------------------------------
   * Validated at L 0.48–0.67, chroma >= 0.1, CVD separation and >=3:1 contrast
   * on #08090B. The brand gold (L 0.83) is far ABOVE the lightness band, so a
   * chart cannot simply use it — --series-1 is a deeper gold that sits inside
   * the band and still reads as the same family.
   *
   * --series-2 IS A BLUE, AND THAT IS DELIBERATE. "Jet, gold and grey" is the
   * INTERFACE; a two-series chart needs two hues a colourblind reader can tell
   * apart, and a neutral grey fails the chroma floor at C 0.019 — it reads as
   * grey rather than as data. Gold + steel blue measures dE 25.1 protan.
   * The blue appears ONLY inside a chart: no button, label, border or link is
   * ever blue.
   *
   * STATUS COLOURS ARE NEVER CHART SERIES, and the rule runs both ways: --warn
   * and --good are reserved for verdicts, and --series-2 is reserved for data.
   * A pair that borrows a status colour measured dE 12.4 under protanopia
   * against these two's 25.1. */
  --series-1:    #B8860B;
  --series-2:    #4C87D6;

  /* ---- elevation --------------------------------------------------------
   * On a dark ground a shadow alone does almost nothing — depth comes from the
   * surface being lighter than what is behind it, with the shadow only
   * separating the edge. A scrim over near-black is the exception: it needs a
   * far higher alpha than it would over paper to read as a layer at all. */
  --shadow:      0 1px 2px rgb(0 0 0 / 0.5), 0 8px 24px -8px rgb(0 0 0 / 0.6);
  --shadow-lift: 0 2px 4px rgb(0 0 0 / 0.5), 0 16px 40px -12px rgb(0 0 0 / 0.7);

  --radius:      14px;
  --radius-sm:   9px;

  /* ---- spacing ----------------------------------------------------------
   * A scale, so that pages share a rhythm. Without one every value is ad-hoc
   * (p-4, mb-3, py-2.5) and nothing on any screen lines up with anything. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.75rem;
  --space-7: 2.5rem;
}

@theme inline {
  --color-ground:      var(--ground);
  --color-leaf:        var(--leaf);
  --color-leaf-2:      var(--leaf-2);
  --color-leaf-3:      var(--leaf-3);
  --color-ink:         var(--ink);
  --color-ink-soft:    var(--ink-soft);
  --color-ink-faint:   var(--ink-faint);
  --color-rule:        var(--rule);
  --color-rule-strong: var(--rule-strong);
  --color-rubric:      var(--rubric);
  --color-on-rubric:   var(--on-rubric);
  --color-gold:        var(--gold);
  --color-iron:        var(--iron);
  --color-warn:        var(--warn);
  --color-good:        var(--good);

  /* ---- the type scale ---------------------------------------------------
   * EIGHT STEPS, AND A SIZE THAT IS NOT ON THE SCALE DOES NOT GO IN. The rule
   * is the scale's entire value: the moment one screen needs "just a bit
   * bigger" and writes a pixel size, the next one does too, and there is no
   * scale any more — only a list of numbers that used to be one.
   *
   * --text-mega exists for marketing display type, which is the one place a
   * house of three products genuinely disagrees: a running brand's hero wants
   * to be twice a finance app's. It is a step ON the scale rather than a
   * licence to leave it. */
  --text-label:    0.6875rem;  /* 11px */
  --text-marginal: 0.8125rem;  /* 13px */
  --text-body:     0.9375rem;  /* 15px */
  --text-lead:     1.0625rem;  /* 17px */
  --text-title:    1.375rem;   /* 22px */
  --text-display:  1.75rem;    /* 28px */
  --text-hero:     3rem;       /* 48px */
  --text-mega:     4rem;       /* 64px */
  --text-colossal: 6.5rem;     /* 104px — marketing hero only */
}
