/* Bot AI design tokens -- the colour vocabulary and the type scale the whole
   product renders against. Every surface (landing, /app, /admin, the widget)
   reads these variables and nothing else, so switching the owner's palette is
   one attribute flip on <html> rather than a stylesheet swap.

   TWO VOCABULARIES, AND THEY ARE ORTHOGONAL. Colour is per palette and per mode
   and therefore lives in the `[data-palette][data-mode]` blocks below. Type is
   the same at every palette and in both modes, so it lives in a `:root` of its
   own and MUST NOT be moved into a palette block -- a size that changed with the
   theme would relayout the page on a colour switch.

   The three designed palettes (moss / amber / indigo) are copied verbatim from
   the redesign's PALETTES object. The numbers look arbitrary because they are
   measured, not chosen: each pairing was checked to clear WCAG AA 4.5:1. Nudging
   a value "to look nicer" silently breaks that, so treat them as fixed data.

   `classic` is ours, not the designer's. It carries the outgoing violet/cyan
   identity onto the new layout so an owner who liked the old look is not forced
   into a new one. The old theme was dark-only; the light half is derived from the
   same hues at lightnesses that clear 4.5:1 on white.

   Usage:
     <html data-palette="moss" data-mode="light">
   :root repeats moss/light so a page that renders before the attributes are set
   (or with them missing entirely) still gets the default palette rather than
   unstyled black-on-white. */

:root {
  /* Heading font. The design ships an optional serif alternate --
     'Noto Serif Georgian' -- swap this one variable to switch every heading. */
  --hf: 'Noto Sans Georgian';

  /* Destructive/at-risk red. The design hardcodes #D14343 for this in every
     palette, but that value only reaches 3.9:1 on the light panel2 and 3.5:1 on
     the dark panels -- it fails AA exactly where "this client is at risk" and
     "delete account" get rendered. Same hue, moved to a lightness that clears
     4.5:1 on every surface of all four palettes. It is deliberately not part of
     the per-palette set: danger should not change meaning with the theme. */
  --neg: #BA3630;
  --negFg: #FFFFFF;

  /* moss / light (default) */
  --warn: #8A5A12;
  --warnFg: #FFFFFF;
  --bg: #F6F8F4;
  --panel: #FFFFFF;
  --panel2: #E9EFE6;
  --line: rgba(20, 50, 30, .11);
  --fg: #0F1A13;
  --fg2: rgba(15, 26, 19, .66);
  --acc: #1F6B42;
  --accFg: #FFFFFF;
  --acc2: #617A6A;
  --pos: #1F6B42;
  --panelBlur: rgba(255, 255, 255, .75);
  --inv: #0F1A13;
  --invFg: #F6F8F4;
  --invSoft: rgba(255, 255, 255, .09);
  --invLine: rgba(255, 255, 255, .14);

  color-scheme: light;
}

/* ==========================================================================
   TYPE SCALE

   WHY THIS EXISTS. Colour in this product has been disciplined from the start:
   four palettes, one vocabulary, and a test that fails on a literal colour in a
   stylesheet. Type had none of that, and the result was measured on 2026-08-30:
   437 `font-size` declarations across the four stylesheets and the two cabinet
   scripts, spread over TWENTY-EIGHT distinct values -- 10, 10.5, 11, 11.5, 12,
   12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 17, 18, 19, 20, 24, 26, 28, 30, 32,
   34, 42, 44, 56, 60, 64. Seventeen of them sit between 10 and 20. Nobody chose
   to have both 12.5 and 13; they accumulated.

   WHY THE PRODUCT'S WHOLE UI BAND IS 10-16px, WHICH IS THE ROOT OF THE DRIFT.
   Measured off Noto Sans Georgian at 100px with canvas measureText:

     - Georgian ink ascent is 0.77em FOR EVERY LETTER. Mkhedruli is unicase --
       there is no capital and no x-height, so the whole alphabet is drawn at
       what Latin would call ascender height. (`text-transform: uppercase` is
       inert on it: the same string measures 562.6px transformed and untouched.)
     - Latin lowercase ink ascent is 0.51em; Latin caps reach 0.73em.

   So Georgian ink at a given px is 1.51x the height of Latin lowercase. 13px of
   Georgian carries the apparent size of ~19.6px of Latin body text. That is why
   this product's reading sizes sit at 12.5-13.5 where an English UI would sit at
   14-16, and it is why seventeen of the twenty-eight values are crammed into a
   six-pixel band: the entire legible range of a Georgian interface is spent in
   the space a Latin scale gives to two or three steps.

   THE MINIMUM STEP, DERIVED RATHER THAN CHOSEN. A step has to be a decision
   somebody can see. At 13px, half a pixel of font-size moves the ink by
   0.77 x 0.5 = 0.39px -- under one device pixel at 1x, i.e. nothing. A whole
   pixel moves it 0.77px, still under one. 1.5px moves it 1.16px, which is the
   first increment that is guaranteed to survive rasterisation on a 1x screen.
   Hence: THE LADDER STEPS BY 1.5px THROUGH THE UI BAND, and a half-pixel
   neighbour is not a step, it is drift.

   The same measurement is what makes adopting this cheap, and it is worth
   stating because it is the whole reason this could be done without a redesign:
   thirteen of the twenty-eight values -- 10 through 16, carrying 391 of the 437
   declarations, 89% of the product -- land within HALF A PIXEL of a rung below.
   By the rule above, half a pixel is not a size difference. Adopting the scale
   therefore removes steps without resizing text.

   ANCHOR AND RUNGS. The ladder is anchored on 13px because 13px is the mode:
   112 of the 437 declarations, more than any other value. Every rung is 1.5px
   from the last, with one deliberate exception at the floor.

     10.5  micro     one gap of 1.0px, not 1.5. The rule would put the floor at
                     10px, but 10.5 is already the smallest text in the product
                     and it is not going to get smaller to satisfy arithmetic.
     11.5  meta      +1.5
     13    body      +1.5  <- the anchor
     14.5  emphasis  +1.5
     16    lead      +1.5
     17.5  title     +1.5

   Above 17.5 the additive rule stops being honest -- 1.5px is 8.6% at 17.5px
   and 4.4% at 34px, so the eye starts reading proportion rather than ink -- and
   the band goes multiplicative:

     20    heading   x1.14
     28    section   x1.40
     34    hero      x1.21

   Those three are the existing .b-h3 / .b-h2 / .b-h1 sizes, ADOPTED UNCHANGED
   rather than re-derived. There was never any drift up there: one declaration
   each, no half-pixel neighbours. The drift is entirely below 20px, and that is
   where the work was.

   LINE HEIGHT, AND WHY MOST STEPS HAVE NONE. Left alone, `line-height: normal`
   on Noto Sans Georgian resolves to its metric box: ascent 1.07em + descent
   0.29em = 1.36. That is exactly the value below which consecutive metric boxes
   begin to overlap, so the browser default already sits on the boundary and
   there is nothing for a token to improve. A `-lh` companion is therefore
   defined ONLY where a leading TIGHTER than 1.36 is wanted, and each one states
   what it was measured against -- the rule .b-display's comment in
   components.css sets out, which is binding here: any line-height under 1.36 on
   this alphabet is a measured decision and must say what it was measured
   against. Ink collision starts below 1.02em (0.77 ascent + 0.25 descent);
   between 1.02 and 1.36 is a judgement about clearance.

     --type-lead-lh     1.6   looser than the box on purpose: an introductory
                              paragraph is read in full, not scanned.
     --type-section-lh  1.2   0.18em of clearance over the ink (5.0px at 28px).
     --type-hero-lh     1.15  0.13em over the ink (3.9px at 34px). This is
                              .b-display's number, arrived at the hard way; see
                              its comment. .b-h1 carried 1.08 -- 0.06em, half the
                              clearance, with no measurement stated anywhere --
                              and now shares this one.

   HOW TO ADD A STEP: don't, without measuring first. A tenth value is how the
   product got twenty-eight. typeScale.test.ts refuses a raw `font-size` literal
   in any stylesheet under src/**\/public, so the pressure to invent one shows up
   as a red test rather than as a number nobody reviews.
   ========================================================================== */

:root {
  --type-micro: 10.5px;
  --type-meta: 11.5px;
  --type-body: 13px;
  --type-emphasis: 14.5px;
  --type-lead: 16px;
  --type-title: 17.5px;
  --type-heading: 20px;
  --type-section: 28px;
  --type-hero: 34px;

  --type-lead-lh: 1.6;
  --type-section-lh: 1.2;
  --type-hero-lh: 1.15;
}

/* ==========================================================================
   CAUTION, AND THE STATE THAT DELIBERATELY HAS NO COLOUR

   The redesign delivery needs two colour roles this file did not have. They are
   answered differently on purpose, and the difference is the point.

   --- 1. --warn / --warnFg ARE REAL TOKENS, AND SPECIFICALLY NOT --acc ---------

   The delivery's `limit` banner is amber-on-cream (#8A5A12 on #FCEFD9) and there
   was no role for it. The tempting shortcut is `--warn: var(--acc)`: one line, no
   new numbers, and it looks fine in isolation. It is wrong, and it is wrong in
   exactly the place the token exists for. The limit banner sits directly beside
   the upgrade CTA it is warning you about. Paint them the same colour and the
   banner reads as a second button -- the signal dies at the one spot on the one
   screen where it had a job.

   So: a real value, per palette, per mode. Nine declarations, measured, not
   chosen. Every one clears WCAG AA 4.5:1 as text on that palette's bg, panel AND
   panel2, and --warnFg clears 4.5:1 on --warn as a fill.

     palette         --warn    bg / panel / panel2      --warnFg   on --warn
     moss light      #8A5A12   5.53 / 5.91 / 5.05       #FFFFFF    5.91
     moss dark       #E8A33D   8.90 / 8.21 / 7.48       #2A1A00    7.81
     amber light     #6F5B00   6.25 / 6.62 / 5.58       #FFFFFF    6.62
     amber dark      #EADC6E  13.40 / 12.45 / 11.37     #2A1A00   12.01
     indigo light    #8A5A12   5.57 / 5.91 / 5.15       #FFFFFF    5.91
     indigo dark     #E8A33D   8.92 / 8.18 / 7.35       #2A1A00    7.81
     classic light   #8A5A12   5.49 / 5.91 / 4.95       #FFFFFF    5.91
     classic dark    #E8A33D   9.14 / 8.73 / 8.03       #2A1A00    7.81

   THE AMBER PALETTE IS THE ONE THAT COULD NOT USE THE DESIGNER'S VALUE, and it
   is worth stating why because it looks like an inconsistency. Caution is amber
   everywhere; the amber palette's BRAND is amber. #8A5A12 (hue 36) against that
   palette's --acc #A56111 (hue 32) is a 4-degree hue difference at 1.22:1
   contrast -- the same colour, which is the collapse this token exists to
   prevent, arrived at by a different route. There is only 30 degrees of hue
   between --neg (hue 3) and that accent, so moving toward red would trade a
   warning that reads as the CTA for one that reads as "delete account" -- an
   understated signal for an overstated one. The room is on the other side:
   #6F5B00 is hue 49, 17 degrees off the accent at 1.36:1 and 47 degrees off the
   danger red. That is the widest separation from BOTH that still clears AA on
   white, and it was picked by measuring, not by taste.

   WHAT --warn IS NOT RATED FOR: the inverted surface in light mode. #8A5A12 on
   --inv is 3.02:1. An inverted band that has to say "caution" uses a pill on
   --invSoft, not --warn as text.

   --- 2. THE UNKNOWN / UNDETERMINED STATE GETS NO TOKEN AT ALL ----------------

   The delivery paints the widget's and /status's third state #C9A227 -- its own
   yellow, beside the green and the red. We do not, and this is a decision, not
   an omission: THE THIRD STATE USES --fg2, the muted body colour it would have
   had anyway.

   „ვერ შემოწმდა" does not mean the thing is broken. It means the READ failed --
   we do not know, and we are saying so instead of guessing. Give that its own
   colour and it joins the severity ladder: a colour beside green and red is read
   as a rung between them, so "we could not check" starts reporting itself as a
   fault, which is the precise misreading the three-state design was built to
   avoid. CLAUDE.md's rule is that a read we could not make must not draw a green
   dot; the corollary, and it costs just as much, is that it must not draw an
   alarm either. Muted grey is what "no information" looks like.

   It also means the state cannot rot. --fg2 is defined in all eight blocks
   already and is AA-rated in all eight; a ninth colour would be one more thing
   to keep clearing, for a state whose whole content is that there is nothing to
   report. components.css spends this as `.b-dot-unknown { background: var(--fg2) }`
   and nothing else.
   ========================================================================== */

/* --------------------------------------------------------------------------
   moss -- the default. Deep forest green on warm paper.
   -------------------------------------------------------------------------- */

[data-palette="moss"][data-mode="light"] {
  --warn: #8A5A12;
  --warnFg: #FFFFFF;
  --bg: #F6F8F4;
  --panel: #FFFFFF;
  --panel2: #E9EFE6;
  --line: rgba(20, 50, 30, .11);
  --fg: #0F1A13;
  --fg2: rgba(15, 26, 19, .66);
  --acc: #1F6B42;
  --accFg: #FFFFFF;
  --acc2: #617A6A;
  --pos: #1F6B42;
  --panelBlur: rgba(255, 255, 255, .75);
  --inv: #0F1A13;
  --invFg: #F6F8F4;
  --invSoft: rgba(255, 255, 255, .09);
  --invLine: rgba(255, 255, 255, .14);

  color-scheme: light;
}

[data-palette="moss"][data-mode="dark"] {
  --warn: #E8A33D;
  --warnFg: #2A1A00;
  --bg: #0B100D;
  --panel: #131A15;
  --panel2: #1A231D;
  --line: rgba(220, 255, 230, .1);
  --fg: #EAF2EC;
  --fg2: rgba(234, 242, 236, .58);
  --acc: #6FD69A;
  --accFg: #08120C;
  --acc2: #698A77;
  --pos: #5FC98A;
  --panelBlur: rgba(11, 16, 13, .8);
  --inv: #1A231D;
  --invFg: #EAF2EC;
  --invSoft: rgba(255, 255, 255, .07);
  --invLine: rgba(255, 255, 255, .1);

  /* Lifted off #BA3630: the light-mode red only reaches 3.5:1 on dark panels. */
  --neg: #FF8A85;
  --negFg: #2A0A08;

  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   amber -- warm ochre on bone.
   -------------------------------------------------------------------------- */

[data-palette="amber"][data-mode="light"] {
  --warn: #6F5B00;
  --warnFg: #FFFFFF;
  --bg: #FBF8F3;
  --panel: #FFFFFF;
  --panel2: #F1EBE1;
  --line: rgba(60, 40, 20, .13);
  --fg: #1B1611;
  --fg2: rgba(27, 22, 17, .61);
  --acc: #A56111;
  --accFg: #FFFFFF;
  --acc2: #7C6A55;
  --pos: #2E7D5B;
  --panelBlur: rgba(255, 255, 255, .75);
  --inv: #1B1611;
  --invFg: #FBF8F3;
  --invSoft: rgba(255, 255, 255, .09);
  --invLine: rgba(255, 255, 255, .14);

  color-scheme: light;
}

[data-palette="amber"][data-mode="dark"] {
  --warn: #EADC6E;
  --warnFg: #2A1A00;
  --bg: #14110E;
  --panel: #1D1915;
  --panel2: #26211B;
  --line: rgba(255, 240, 220, .11);
  --fg: #F5EFE7;
  --fg2: rgba(245, 239, 231, .58);
  --acc: #F0A03A;
  --accFg: #191309;
  --acc2: #9A7F5F;
  --pos: #5DD39E;
  --panelBlur: rgba(20, 17, 14, .8);
  --inv: #241E18;
  --invFg: #F5EFE7;
  --invSoft: rgba(255, 255, 255, .07);
  --invLine: rgba(255, 255, 255, .1);

  /* Lifted off #BA3630: the light-mode red only reaches 3.5:1 on dark panels. */
  --neg: #FF8A85;
  --negFg: #2A0A08;

  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   indigo -- cool blue-violet on porcelain.
   -------------------------------------------------------------------------- */

[data-palette="indigo"][data-mode="light"] {
  --warn: #8A5A12;
  --warnFg: #FFFFFF;
  --bg: #F7F8FC;
  --panel: #FFFFFF;
  --panel2: #ECEFF9;
  --line: rgba(20, 30, 70, .11);
  --fg: #111629;
  --fg2: rgba(17, 22, 41, .61);
  --acc: #4B5BF5;
  --accFg: #FFFFFF;
  --acc2: #6972A1;
  --pos: #2E7D5B;
  --panelBlur: rgba(255, 255, 255, .75);
  --inv: #111629;
  --invFg: #F7F8FC;
  --invSoft: rgba(255, 255, 255, .09);
  --invLine: rgba(255, 255, 255, .14);

  color-scheme: light;
}

[data-palette="indigo"][data-mode="dark"] {
  --warn: #E8A33D;
  --warnFg: #2A1A00;
  --bg: #0C0E18;
  --panel: #141828;
  --panel2: #1C2138;
  --line: rgba(210, 220, 255, .11);
  --fg: #EDEFFA;
  --fg2: rgba(237, 239, 250, .58);
  --acc: #8189FF;
  --accFg: #0C0E18;
  --acc2: #7C81A3;
  --pos: #5DD39E;
  --panelBlur: rgba(12, 14, 24, .8);
  --inv: #1B2038;
  --invFg: #EDEFFA;
  --invSoft: rgba(255, 255, 255, .07);
  --invLine: rgba(255, 255, 255, .1);

  /* Lifted off #BA3630: the light-mode red only reaches 3.5:1 on dark panels. */
  --neg: #FF8A85;
  --negFg: #2A0A08;

  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   classic -- the product's outgoing violet/cyan identity, ported onto the new
   layout. Derived from cortex-tokens.css: --violet oklch(0.68 0.22 300) and
   --cyan oklch(0.7 0.16 195) survive intact in dark mode; the light mode drops
   both to the lightness where they clear 4.5:1 on white, which is why they read
   as deeper than the originals.

   fg2 is a solid hex here rather than the translucent fg the other three use --
   at .58 alpha over panel2 it lands around 3.4:1, well under AA, and this
   palette is one we are inventing rather than transcribing.

   Measured (all eleven required pairs, both modes, >= 4.5):
     light  fg/bg 17.52  fg/panel 18.87  fg/panel2 15.81
            fg2/bg 5.58  fg2/panel 6.01  fg2/panel2 5.03
            acc/panel 5.42  acc2/panel 5.59  pos/panel 5.64
            accFg/acc 5.42  invFg/inv 17.52
     dark   fg/bg 18.09  fg/panel 17.27  fg/panel2 15.89
            fg2/bg 7.89  fg2/panel 7.54  fg2/panel2 6.94
            acc/panel 5.82  acc2/panel 10.20  pos/panel 8.97
            accFg/acc 6.15  invFg/inv 15.08
   -------------------------------------------------------------------------- */

[data-palette="classic"][data-mode="light"] {
  --warn: #8A5A12;
  --warnFg: #FFFFFF;
  --bg: #F6F6FB;
  --panel: #FFFFFF;
  --panel2: #EBEAF3;
  --line: rgba(35, 20, 80, .12);
  --fg: #11101A;
  --fg2: #62626F;
  --acc: #8843DB;
  --accFg: #FFFFFF;
  --acc2: #007475;
  --pos: #137738;
  --panelBlur: rgba(255, 255, 255, .75);
  --inv: #11101A;
  --invFg: #F6F6FB;
  --invSoft: rgba(255, 255, 255, .09);
  --invLine: rgba(255, 255, 255, .14);

  color-scheme: light;
}

[data-palette="classic"][data-mode="dark"] {
  --warn: #E8A33D;
  --warnFg: #2A1A00;
  --bg: #090A14;
  --panel: #0F111A;
  --panel2: #181A24;
  --line: rgba(190, 200, 255, .11);
  --fg: #F4F5F8;
  --fg2: #A3A3AE;
  --acc: #AF6EFF;
  --accFg: #0B0716;
  --acc2: #00D4D5;
  --pos: #5DC879;
  --panelBlur: rgba(9, 10, 20, .8);
  --inv: #1C1F29;
  --invFg: #F4F5F8;
  --invSoft: rgba(255, 255, 255, .07);
  --invLine: rgba(255, 255, 255, .1);

  /* Lifted off #BA3630: the light-mode red only reaches 3.5:1 on dark panels. */
  --neg: #FF8A85;
  --negFg: #2A0A08;

  color-scheme: dark;
}
