/* ============================================================================
   BUDTELLO DESIGN TOKENS — THE canonical source of truth.
   ----------------------------------------------------------------------------
   CANONICAL FILE: dispensary-ai/public/tokens.css
   SYNCED COPIES:  askbud-marketplace/app/tokens.css   (build fails on drift —
                   scripts/check-token-sync.sh, wired as `prebuild`)
                   askbud-preview/public/tokens.css    (Phase 2)
   Edit ONLY the canonical file, then re-copy. Do not let a fifth token system
   happen.

   RULES
   - No colour value may exist outside this file: no hex/rgb in components,
     template literals, SVG fills, or JS. Derived tints use color-mix() over
     these tokens at the point of use.
   - Semantic names only (--accent, not --peach).
   - JS-drawn surfaces (Leaflet map, canvas orb) read tokens at runtime:
       getComputedStyle(document.documentElement).getPropertyValue('--canvas')
     and re-read on the `themechange` CustomEvent that theme.js dispatches on
     window ({detail:{pref,theme}}). They never keep their own copy.
   - Theme switching: theme.js + the inline no-flash <head> script set
     data-theme="light|dark" (the RESOLVED theme) and data-theme-pref=
     "light|dark|system" (the user's choice) on <html> before first paint.
   ========================================================================== */

/* ── LIGHT (default) ─────────────────────────────────────────────────────── */
:root {
  color-scheme: light;

  /* Surfaces. The canvas is the paper; everything else is a flat opaque
     plane resting on it (see --elevation). Texture goes on the canvas ONLY. */
  --canvas: #eae4da;            /* page background — bone paper */
  --surface-raised: #f1ece2;    /* cards, chips, panels, inputs, nav sheets */
  --surface-recessed: #d5cbb8;  /* alternate bands, wells, inactive tabs */

  /* Lines */
  --border: #cdc6ba;            /* default hairline on raised surfaces */
  --border-strong: #a49d8f;     /* hover/active borders, emphasized rules */

  /* Ink */
  --text: #1d1d1b;              /* body + headings */
  --text-secondary: #686560;    /* secondary text — 4.59:1 on --canvas
                                   (nudged from #6d6a63/4.27:1 in Phase A to
                                   clear the 4.5:1 body-text AA bar) */

  /* Accent — peach. THE only accent. Allowed on: primary buttons, the active
     nav underline, video/media indicators. NOWHERE else. Never encodes data.
     No second peach: hover = opacity or border weight, never a variant. */
  --accent: #ffa07a;
  --accent-edge: #e0805a;       /* light mode only: hairline border on filled
                                   accent buttons + small icons ≤16px (peach
                                   on bone is too low-contrast without it) */
  --on-accent: #1d1d1b;         /* text/icons on accent fills (8.5:1) */

  /* Status colours — semantic, never brand.
     --danger: deep + saturated where peach is pale, so the two can't be
     confused at chip size (decided 2026-08-01, retires marketplace #FF9D8A).
     --status-live: the reclassified green. live/active/success indicators
     ONLY — never a button, never emphasis. Green = "this is running",
     peach = "you can click this". Light value = the marketplace's deep green
     (#2f6f4f, 4.7:1 on bone); dark value = the original brand green
     (#83b842, 6.0:1 on charcoal) — each is the existing green that reads
     best on its canvas. */
  --danger: #a8342a;
  --status-live: #2f6f4f;

  /* Shadow ingredients (see --elevation) */
  --shadow-color: rgba(29, 29, 27, 0.13);
  --shadow-color-tight: rgba(29, 29, 27, 0.07);

  /* Elevation — two tight layers: a card RESTING on paper, not hovering.
     Applies to buttons, chips, tags, filter panels, table header bands,
     cards, modals, dropdowns. Anything carrying it must be OPAQUE
     (--surface-raised) — texture showing through a floating element reads
     as a mistake. */
  --elevation: 0 1px 2px var(--shadow-color), 0 1px 1px var(--shadow-color-tight);

  /* Focus ring — neutral (accent is not a focus colour) */
  --focus-ring: 0 0 0 3px var(--shadow-color);

  /* DEPRECATED size vocabulary (ADR-0443). The product reads the radius ROLES
     further down; nothing in app/ or components.css references these four any
     more. They survive ONLY because budtello.com's own stylesheets
     (public/style.css, public/lockup.css) and docs/stylesheets/budtello.css
     still read them, and those belong to lane 8 of the visual-system
     reduction, which converts them and then deletes these four lines.
     Deleting them here would square every corner on the marketing site.
     Do not add a new reader. --radius-xl already has none. */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 20px;

  /* --radius-pill is a ROLE, not a size — it stays when the four above go. */
  --radius-pill: 999px;

  /* Type */
  --display: 'Inter Tight', 'Inter', system-ui, sans-serif;
  --sans: 'Inter', system-ui, -apple-system, sans-serif;

  /* Third-party brand plates — theme-invariant by design. */
  --logo-plate: #f4f1eb;        /* light plate behind third-party logo marks
                                   (Metrc) — stays light in both themes */
  --claude-bg: #faf9f5;         /* "powered by Claude" frame — warm ivory.  */
  --claude-bg-2: #f0eee6;       /* Anthropic's look, confined to that       */
  --claude-ink: #3d3929;        /* section, identical in both themes.       */
  --claude-ink-soft: #6e6a5b;
  --claude-line: rgba(61, 57, 41, 0.12);
  --claude-coral: #d97757;      /* Claude spark — their brand, not our accent */
}

/* ── DARK ────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] {
  color-scheme: dark;

  --canvas: #2b2b29;
  --surface-raised: #343431;
  --surface-recessed: #1d1d1b;

  --border: #444441;
  --border-strong: #4d4d49;

  --text: #eae4da;
  --text-secondary: #96928a;    /* 4.58:1 on dark canvas (nudged from
                                   #918d85/4.29:1 in Phase A for body-text AA) */

  --accent: #ffa07a;
  --accent-edge: #ffa07a;       /* collapses to the accent: dark mode needs
                                   neither the hairline nor the icon swap */
  --on-accent: #1d1d1b;

  --danger: #e05a4e;
  --status-live: #83b842;

  --shadow-color: rgba(0, 0, 0, 0.40);
  --shadow-color-tight: rgba(0, 0, 0, 0.25);
}

/* ── PAPER GRAIN (v2 — stitched turbulence overlay) ──────────────────────────
   One 240px fractal-noise tile with stitchTiles='stitch' (NON-NEGOTIABLE —
   without it the tile edges don't match at repeats and seams show). Rendered
   by a fixed `body::after` overlay in the consuming stylesheet (style.css):
     background-image: var(--grain-img);
     background-repeat: repeat;   ← natural tile size — NEVER set
                                    background-size on the grain; scaling
                                    blurs and chunks the noise
     opacity: var(--grain-opacity);
     mix-blend-mode: var(--grain-blend);
   Tunable knobs (stay inside these bands):
     baseFrequency 0.6 = coarser ←→ 1.2 = finer   (current: 0.9)
     opacity band 0.03–0.06 — grain should be barely perceptible at arm's
     length; dark canvases need LESS (and soft-light, since multiply
     crushes on dark).
   Texture belongs to the page canvas ONLY. The overlay sits above the page
   at ~4% opacity, which reads as canvas grain; buttons, chips, cards and
   recessed bands stay flat. (v1 history: two background-size-scaled layers
   at 0.3–0.55 opacity — rendered choppy, seamed, and blotchy in dark.) */
:root {
  --grain-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --grain-opacity: 0.045;
  --grain-blend: multiply;
}
:root[data-theme="dark"] {
  --grain-opacity: 0.035;
  --grain-blend: soft-light;
}

/* .paper = the canvas fill. The grain itself arrives via the body::after
   overlay in style.css — this class no longer carries background-image. */
.paper {
  background-color: var(--canvas);
}

/* ============================================================================
   DESIGN SYSTEM v1 — role tokens (ADR-0329). ADDITIVE ONLY: nothing above is
   redefined, so every existing surface renders byte-for-byte as before. These
   roles are consumed by components.css; surfaces migrate to them in later
   styling-only swap sessions. Values are David's picks from
   docs/pending/ui-shape-decisions.json (2026-08-19, "Confirm all proposed").
   ========================================================================== */
:root {
  /* Spacing scale — pick spacing=s.8step (4/8/12/16/24/32/48/64) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Radius ROLES (ADR-0443) — five corners in the product, and only five.
     --radius-pill already exists above (999px) and is reused unchanged.
     Folder tabs compose control: "var(--radius-control) var(--radius-control)
     0 0" for the tab, "0 var(--radius-control) x3" for the panel (ADR-0411).
     We keep a 12px container where SLDS 2 publishes 16 — David's call on
     7 Sept: the flat product card is 12. That divergence is deliberate. */
  --radius-xs: 4px;           /* boxes under ~20px tall: overlay badges on media */
  --radius-control: 8px;      /* buttons, inputs, tabs, rect badges, pagination */
  --radius-container: 12px;   /* cards, panels, modals, table wrappers, alerts */
  --radius-circle: 50%;       /* avatars, round icon buttons, status dots */

  /* Border weight — pick border=b.1 */
  --border-width: 1px;

  /* ── TYPE SCALE (ADR-0441) ────────────────────────────────────────────────
     Seven sizes, three line-height ratios, three tracking values. Every
     number is a published SLDS 2 global styling hook value, read from the
     shipped CSS of @salesforce-ux/sds-styling-hooks 2.0.0-beta.16 — the only
     public artefact that self-flags --_slds-is-v2-enabled. (NOT
     @salesforce-ux/design-system@2.264.x: it publishes the same hook NAMES
     with SLDS-1-era values.)

     Before this block the product had no type scale at all: 261 font-size
     declarations typed by hand across the app stylesheets, 45 distinct
     values, 7 of them reading a token. That is why the 2026-09-05 census
     found 14 sizes and 19 line heights on the product surfaces.

     THE RULE: no font-size, line-height or letter-spacing is typed as a
     literal anywhere outside this file. A new style lands on an existing
     step, or it does not land. If a step cannot earn its one-line
     description below, it does not belong here either. */
  --font-micro: 10px;   /* slds font-scale-neg-2 — glyphs sitting on top of a
                           photo, e.g. the ▶ on a thumbnail. Never sentences. */
  --font-sm: 12px;      /* slds font-scale-neg-1 — secondary meta inside a
                           dense row: "under <vendor>", colour words,
                           column-head counts, footer legal. */
  --font-base: 13px;    /* slds font-scale-base — small controls and chips:
                           the toolbar tier. */
  --font-body: 14px;    /* slds font-scale-1 — body copy, table cells, and the
                           primary value in a row: strain, price, THC. */
  --font-h3: 16px;      /* slds font-scale-2 — card, panel and section titles;
                           the large-button tier. */
  --font-h2: 20px;      /* slds font-scale-4 — page titles and the product
                           lockup. */
  --font-h1: 24px;      /* slds font-scale-5 — the single page heading on
                           budtello.com's long-form pages, outside the hero.
                           The hero keeps its clamp() display sizes: it is
                           artistic and out of scope (David, 2026-09-09). */

  /* Line heights are RATIOS, never pixels, so the fractional pixel is
     computed rather than typed and cannot drift. 19 measured values collapse
     onto these three. */
  --lh-1: 1;            /* slds line-height-1 — glyph badges, icon buttons:
                           anything whose box is its glyph. */
  --lh-tight: 1.25;     /* slds line-height-2 — table cells, chips, badges,
                           controls, column heads. THE row-height lever: this
                           and cell padding decide rows per screen, not
                           font-size (measured, ADR-0441). */
  --lh-body: 1.5;       /* slds line-height-base — paragraphs, card copy,
                           policy pages. */

  /* Tracking. Three values; the −0.5px that existed only under Outfit dies
     with it in the family lane. */
  --tracking: 0;              /* everything */
  --tracking-tight: -0.01em;  /* headings 20px and up — optical only */
  --tracking-caps: 0.06em;    /* uppercase column heads and micro-labels,
                                 which need it to stay readable at 12px */

  /* Control SIZE TIERS — pick height=h.36 (md 36; sm 32 / lg 44),
     btnpad=p.616 (md 6x16; sm 4x12 / lg 8x20). Components read the active
     --control-* ; [data-density] rescales a whole subtree (see components.css). */
  --control-h-sm: 32px;   --control-h-md: 36px;   --control-h-lg: 44px;
  --control-pad-sm: 4px 12px;  --control-pad-md: 6px 16px;  --control-pad-lg: 8px 20px;
  --control-font-sm: var(--font-base);   /* 13 */
  --control-font-md: var(--font-body);   /* 14 */
  --control-font-lg: var(--font-h3);     /* 16 */
  --control-h: var(--control-h-md);
  --control-pad: var(--control-pad-md);
  --control-font: var(--control-font-md);

  /* Table density TIERS — pick table=t.md (.mi-table verbatim: head 9x10,
     row 8x10, 13.5px, horizontal rules only, NO vertical separators).
     sm=6x8, lg=12x12 derived. Active row/head read below; [data-density] swaps. */
  --table-head-sm: 6px 8px;   --table-head-md: 9px 10px;  --table-head-lg: 12px 12px;
  --table-cell-sm: 6px 8px;   --table-cell-md: 8px 10px;  --table-cell-lg: 12px 12px;
  --table-head-pad: var(--table-head-md);
  --table-cell-pad: var(--table-cell-md);
  --table-font: var(--font-body);        /* 14 — was a lone 13.5px */

  /* Elevation ROLE — pick elevation=e.flat (cards are flat: border only, no
     drop shadow). The legacy --elevation (two tight layers) is untouched above
     and stays available for chips/dropdowns that already use it. */
  --elevation-card: none;
  /* Overlay ROLE — modals and toasts, the only elevation above --elevation. */
  --elevation-overlay: 0 6px 24px rgba(0, 0, 0, 0.25);

  /* Focus ring — pick focus=f.twolayer (inner canvas 1px + outer accent 2px;
     visible on any background, salmon included). NEW token — the legacy neutral
     --focus-ring above is left untouched so existing inputs do not change. */
  --ring: 0 0 0 1px var(--canvas), 0 0 0 3px var(--accent);

  /* Semantic status palette — pick palette=pal.cool (each meaning a distinct
     hue). Badges + alerts ONLY (never brand, never a button). amber + slate are
     NEW hues; they live here in the canonical token file (the one legal home for
     colour literals) with dark-theme values below. */
  --sem-ok: var(--status-live);
  --sem-warn: hsl(38 92% 40%);
  --sem-fail: var(--danger);
  --sem-info: hsl(215 24% 45%);
  --sem-neutral: var(--text-secondary);
}

:root[data-theme="dark"] {
  /* Only the two NEW hues need a dark value; ok/fail/neutral ride the themed
     tokens they alias. */
  --sem-warn: hsl(38 95% 60%);
  --sem-info: hsl(215 32% 68%);
}

/* ============================================================================
   THEME-CONTROL TOKENS — buttons + tables (ADR-0461). ADDITIVE ONLY, defaults
   equal today's rendered values so nothing moves. /theme.css (ADR-0462) is the
   only thing meant to override these, from the /theme control page. Every
   colour-carrying token below just re-points to a role token already in
   force (--surface-raised, --text, --border, --accent, ...), so it follows
   light/dark automatically — no dark-section entries are needed here. The
   handful of literal values (weight/case/tracking keyword/px) don't carry
   colour either, so they don't need one.
   ========================================================================== */
:root {
  /* Buttons — components.css .btn family */
  --btn-weight: 600;                /* .btn font-weight, current value */
  --btn-case: none;                 /* .btn text-transform — none today */
  --btn-tracking: var(--tracking);  /* .btn letter-spacing — unset today,
                                        i.e. the same 0 as --tracking */
  --btn-bg: var(--surface-raised);          /* .btn background */
  --btn-fg: var(--text);                    /* .btn text colour */
  --btn-border: var(--border);              /* .btn border colour */
  --btn-primary-bg: var(--accent);              /* .btn--primary background */
  --btn-primary-fg: var(--on-accent);           /* .btn--primary text colour */
  --btn-primary-border: var(--accent-edge);     /* .btn--primary border */
  --btn-secondary-bg: var(--surface-recessed);  /* .btn--secondary background */
  --btn-secondary-fg: var(--text);              /* .btn--secondary text colour */
  --btn-secondary-border: var(--border);        /* .btn--secondary border */

  /* Tables — components.css .table rules today; also the defaults for the
     literals in askbud-marketplace app/globals.css (thead th / tbody td /
     .portal-tablecard) that a later lane points at these same names. */
  --row-h: 43px;      /* plain, padding-driven row height today: two
                          --cell-pad-y (11px) plus a 21px line box at
                          --font-body/--lh-body (14px * 1.5) */
  --row-h-card: 56px; /* askbud-marketplace .portal-tablecard tbody tr — a
                          second, different row height, so it keeps its own
                          token rather than sharing --row-h. 56 IS A MULTIPLE
                          OF 4 CSS PX ON PURPOSE (ADR-0489). Chrome stores
                          every length in 1/64 of a CSS px, so a row of h CSS
                          px at display scaling s is a whole number of screen
                          pixels that Chrome can represent exactly only when
                          h * s * 64 is a whole multiple of 64 — which, for
                          the Windows scalings 100/125/150/175/200%, holds for
                          every multiple of 4. At 175% a 56px row is exactly
                          98 screen px, at 125% 70, at 150% 84. 54 was 94.5 at
                          175% — half a pixel, so alternate dividers vanished
                          (ADR-0483) — and the rounded 54.2857 that fix asked
                          for stores as 54.28125 = 94.992, which drifted the
                          dividers off phase as the table scrolled. */
  --cell-pad-y: 11px; /* marketplace tbody td vertical padding today */
  --cell-pad-x: 14px; /* marketplace tbody td horizontal padding today */
  --table-head-weight: 600;     /* .table th / marketplace thead th weight */
  --table-head-case: none;      /* .table th has no text-transform today —
                                    the marketplace's separate legacy thead
                                    th uppercase rule is untouched, out of
                                    this lane's scope (app/globals.css) */
  --table-line: var(--border);  /* .table td row-divider colour today */
  --table-zebra: transparent;   /* off today. No nth-child rule reads this
                                    yet in components.css, so none is added
                                    here (no existing rule to convert) —
                                    reserved for a future zebra-stripe rule */
  --table-hover: var(--surface-recessed); /* .table tbody tr:hover today */

  /* Lane F (ADR-0467) — table wrapper corners and header row height. */
  --table-radius: var(--radius-container); /* table wrapper corners; separate
                                    from cards so David can square tables
                                    alone (a rounded wrapper clips the
                                    select-all cell on /sell). Default
                                    follows card corners, so nothing moves
                                    until dialled. */
  --table-head-h: 28px; /* header row height of the product's tables,
                                    measured on /sell and /sell/metrc on 10
                                    Sept 2026. On plain tables whose header
                                    padding is still literal (12px 14px ->
                                    ~41px) this acts as a MINIMUM: the dial
                                    grows them, cannot shrink them, until
                                    their padding is tokenised. */
}
