/*
 * Tare — the site
 *
 * The token layer only: custom properties, the dark scheme, and the base
 * reset. The frozen web client's component CSS is deliberately not carried
 * over — this site shares Tare's design language, not its screens.
 *
 * The design language as CSS. Ported by hand from the shared Kotlin source:
 *
 *   ../shared/src/commonMain/kotlin/com/charithp/tare/design/TareTokens.kt
 *
 * That file calls itself the single source of truth for both mobile platforms,
 * and CSS is a third consumer it cannot reach — Kotlin constants don't compile
 * to stylesheets. So these values are duplicated and can drift: change a token
 * there and change it here in the same commit.
 *
 * This project lives in the same repository as that Kotlin precisely so the
 * duplication can be removed later by generating this file rather than
 * maintaining it. Until then, the rule above is the whole safeguard.
 *
 * Reasoning for individual values lives in tare/DESIGN.md, not here.
 */

/* Geist carries display and heading styles only; body and label use the
   platform's system font, exactly as on iOS and Android. Two weights rather
   than four, because nothing here renders Geist at regular or medium.

   Still TTF — roughly twice the bytes of woff2. Converting needs a tool that
   isn't installed yet; font-display: swap means that costs a late swap rather
   than a blank page, so it is an optimisation outstanding, not a defect.

   Vite resolves and fingerprints these relative paths at build time. */
@font-face {
  font-family: "Geist";
  src: url("./assets/fonts/Geist-SemiBold.ttf") format("truetype");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Geist";
  src: url("./assets/fonts/Geist-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- Surfaces and ink ------------------------------------------------- */
  --tare-surface: #f7faf7;
  --tare-surface-raised: #ffffff;
  --tare-surface-sunken: #e8f0e9;
  --tare-border: #dce5de;
  --tare-ink: #12211a;
  --tare-ink-muted: #5f6f66;

  --tare-accent: #2e7d4f;
  --tare-accent-pressed: #266741;
  --tare-accent-wash: #e3f0e8;
  --tare-on-accent: #ffffff;

  /* --- Macros -----------------------------------------------------------
     Blue, amber and rose separate cleanly under deuteranopia and protanopia,
     and none collides with the green accent. Colour never carries meaning
     alone — every macro shown in a bar also carries its label and value. */
  --tare-protein: #2563eb;
  --tare-carbs: #f59e0b;
  --tare-fat: #db2777;

  /* Darkened for use as *text* on a tinted background, where the vivid
     version wouldn't clear 4.5:1. */
  --tare-protein-on-wash: #1d4ed8;
  --tare-carbs-on-wash: #92400e;
  --tare-fat-on-wash: #be185d;

  /* The composition arc: the vivid triad at saturation x0.75. Today's ring
     carries two arcs and only works if one clearly loses — the goal arc is
     13px in the accent, composition is 3px in these. Never used for text. */
  --tare-protein-arc: #3e6cd2;
  --tare-carbs-arc: #d89628;
  --tare-fat-arc: #c43e7a;

  /* --- Semantic ---------------------------------------------------------
     Critical is for destructive actions only — never for nutrition data.
     Going over a calorie target is information, not an error. */
  --tare-positive: #2e7d4f;
  --tare-caution: #b45309;
  --tare-critical: #b91c1c;

  /* Validation and auth failures, not --tare-critical. A red "password is too
     short" is punishment, which principle 3 forbids. */
  --tare-error: #8a4b3d;
  --tare-error-wash: #f7eeeb;

  /* --- Type -------------------------------------------------------------
     Line heights are absolute, not multipliers, so vertical rhythm holds
     when a size changes. */
  --tare-font-display: "Geist", ui-sans-serif, system-ui, sans-serif;
  --tare-font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  --tare-display-xl: 600 56px/56px var(--tare-font-display);
  --tare-display-l: 600 40px/44px var(--tare-font-display);
  --tare-display-m: 600 32px/36px var(--tare-font-display);
  --tare-heading-l: 600 24px/30px var(--tare-font-display);
  --tare-heading-m: 600 20px/26px var(--tare-font-display);
  --tare-heading-s: 600 17px/22px var(--tare-font-display);
  --tare-body-l: 400 17px/24px var(--tare-font-body);
  --tare-body-m: 400 15px/22px var(--tare-font-body);
  --tare-body-s: 400 13px/18px var(--tare-font-body);
  --tare-label: 500 13px/16px var(--tare-font-body);
  --tare-caption: 400 11px/14px var(--tare-font-body);

  /* --- Space, on a 4px grid. These are the only spacing values. --------- */
  --tare-space-xxs: 4px;
  --tare-space-xs: 8px;
  --tare-space-s: 12px;
  --tare-space-m: 16px;
  --tare-space-l: 20px;
  --tare-space-xl: 24px;
  --tare-space-xxl: 32px;
  --tare-space-xxxl: 40px;
  --tare-space-huge: 48px;

  /* iOS uses 20 and Android 16, each following its own convention. The web
     has no such convention, so it follows iOS. */
  --tare-screen-margin: 20px;

  /* A food diary is a single column of short rows. Full-width line lengths
     would be unreadable and would look nothing like the apps. */
  --tare-column: 560px;

  --tare-radius-field: 12px;
  --tare-radius-chip: 16px;

  /* 16 since 2026-08-19, down from 20, and it now equals the chip radius on
     purpose — a chip is a small container and a card is a large one, so one
     value across both is a rule where two was a coincidence. Field stays 12
     because a field is a control; sheet stays 28 because a sheet is the surface
     the app sits on rather than something on it.

     This file drifted for a few hours: the Kotlin and 104 frames moved and this
     did not, which is exactly what the header above forbids. Recorded rather
     than quietly corrected, because the header's rule is the only safeguard
     there is. */
  --tare-radius-card: 16px;
  --tare-radius-sheet: 28px;
  --tare-radius-pill: 999px;
}

/* Dark is written **once**, keyed on an attribute that `theme.ts` sets — including
   when the choice is Auto, where JS resolves `prefers-color-scheme` and writes
   the same attribute.

   The alternative was a `@media (prefers-color-scheme: dark)` block *and* a
   `[data-theme="dark"]` block holding identical values. Two copies of twenty
   colours is precisely the drift this session has spent its time repairing.

   The media query below remains as a no-JS fallback only, and is scoped so it
   can never fight an explicit choice. */
:root[data-theme="dark"] {
  --tare-surface: #0e1512;
  --tare-surface-raised: #1a231e;
  --tare-surface-sunken: #172019;
  --tare-border: #26302a;
  --tare-ink: #f2f7f3;
  --tare-ink-muted: #9aaaa1;

  /* Deliberately lighter than the light-mode accent: #2e7d4f on this
     surface is only ~3.7:1 and fails AA for text. This is ~8:1. */
  --tare-accent: #5fbf87;
  --tare-accent-pressed: #4fa873;
  --tare-accent-wash: #1b2c22;
  --tare-on-accent: #0e1512;

  --tare-protein: #60a5fa;
  --tare-carbs: #fbbf24;
  --tare-fat: #f472b6;

  --tare-protein-on-wash: #93c5fd;
  --tare-carbs-on-wash: #fcd34d;
  --tare-fat-on-wash: #f9a8d4;

  --tare-protein-arc: #73a7e7;
  --tare-carbs-arc: #e0b33f;
  --tare-fat-arc: #e482b5;

  --tare-positive: #5fbf87;
  --tare-caution: #fbbf24;
  --tare-critical: #f87171;

  --tare-error: #e0a896;
  --tare-error-wash: #2a1d19;
}

/* The same values again, for a visitor whose system says dark and who has made
   no explicit choice.

   **This block is complete here and was not in the app's copy**, where it
   redefined 7 of the 24 properties the theme changes. That was correct there
   and wrong here, and the difference is JS: the app's `theme.ts` always writes
   `data-theme`, so the block above always wins and the fallback only ever had
   to be right about the surface. This site ships no JS, so the fallback *is*
   the dark theme.

   The gap was not theoretical. `--tare-accent-wash` was among the seventeen it
   missed, so a heading in `--tare-ink` on a wash background measured **1.08:1**
   in dark — invisible — where the complete pair is 13.55:1.

   Duplicated rather than shared because CSS cannot hand one declaration block
   to both a media-scoped and an unscoped selector. Generating this file from
   TareTokens.kt, which the header above already contemplates, is what removes
   the duplication for good. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --tare-surface: #0e1512;
    --tare-surface-raised: #1a231e;
    --tare-surface-sunken: #172019;
    --tare-border: #26302a;
    --tare-ink: #f2f7f3;
    --tare-ink-muted: #9aaaa1;

    /* Deliberately lighter than the light-mode accent: #2e7d4f on this
       surface is only ~3.7:1 and fails AA for text. This is ~8:1. */
    --tare-accent: #5fbf87;
    --tare-accent-pressed: #4fa873;
    --tare-accent-wash: #1b2c22;
    --tare-on-accent: #0e1512;

    --tare-protein: #60a5fa;
    --tare-carbs: #fbbf24;
    --tare-fat: #f472b6;

    --tare-protein-on-wash: #93c5fd;
    --tare-carbs-on-wash: #fcd34d;
    --tare-fat-on-wash: #f9a8d4;

    --tare-protein-arc: #73a7e7;
    --tare-carbs-arc: #e0b33f;
    --tare-fat-arc: #e482b5;

    --tare-positive: #5fbf87;
    --tare-caution: #fbbf24;
    --tare-critical: #f87171;

    --tare-error: #e0a896;
    --tare-error-wash: #2a1d19;
  }
}

/* --- Base ---------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--tare-surface);
  color: var(--tare-ink);
  font: var(--tare-body-l);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
p,
figure {
  margin: 0;
}

a {
  color: var(--tare-accent);
}

/* Every changing number is tabular, so digits don't jitter as totals update. */
.tare-numeric {
  font-variant-numeric: tabular-nums;
}

