/* ============================================================================
   LARDER DESIGN TOKENS — the single source of truth for the whole product.

   Every page (app shell, login, menu print, allergen sheet, stock checklist,
   recipe cards) links THIS file. Nothing else may declare a palette. If you
   need a new colour, add a token here; never inline a hex in app.css or a
   template. tests/guardrails/test_design_tokens.py enforces both rules.

   ---------------------------------------------------------------------------
   THE ELEVATION RULE — "up is lighter", in BOTH themes.

   The page canvas is always the DARKEST surface on screen; every layer stacked
   on top of it steps one rung toward the light. Light mode is therefore the
   mirror of dark mode, not an inversion of the ladder's direction:

       rung          dark          light        what sits here
       ----          ----          -----        --------------
       --well        #0d0b09       #d5ccbb      grooves carved INTO a panel:
                                                progress tracks, code, inset
       --bg          #141310       #e1d8c6      the page canvas
       --surface     #1c1a16       #f6f2e9      panels, cards, nav pill, top bar
       --surface-2   #25221c       #fcf9f4      a box INSIDE a panel: inputs,
                                                KPI tiles, sub-cards, hover
       --surface-3   #2f2b23       #ffffff      floats ABOVE everything:
                                                popovers, sheets, toasts,
                                                tooltips, drag ghosts — and
                                                controls nested two levels deep

   Two consequences worth stating out loud:
     * Light mode's canvas is a warm sand, NOT white. White is reserved for the
       top rung, so "elevated == brighter" holds in light mode exactly as it
       does in dark. This is the Apple / GitHub / Linear / Stripe model.
     * `--well` runs BELOW the canvas in both themes, so a progress track or a
       code block reads as carved in rather than raised — the one place the
       ladder legitimately runs downward.

   Steps are perceptually even (measured in OKLCH lightness, brand hue 85°):
   ~0.035 per rung in dark; in light the steps compress toward white
   (0.037 / 0.077 / 0.021 / 0.017) because lightness perception compresses there
   too. --bg -> --surface is the widest rung in both themes on purpose: the
   canvas/panel boundary is the one a user reads first, and it is what lets the
   nav pill wear the ordinary --surface and still stand off the page.

   ---------------------------------------------------------------------------
   THE CONTRAST RULE

   --ink    body text, AAA everywhere (>= 11.4:1 on every rung)
   --muted  secondary text, AA everywhere (>= 4.7:1 on every rung)
   --faint  DECORATIVE ONLY — placeholders, chart axes, dividers, disabled
            glyphs. It clears 3:1 but not 4.5:1, so it must never carry
            content. Use --muted for anything a user has to read.

   Every `--x` that can be used as text clears 4.5:1 on --surface.
   Every `--x-contrast` is the accessible foreground for a solid `--x` fill.
   --accent clears 3:1 against --surface so a filled button is identifiable
   as a control (WCAG 2.1 SC 1.4.11), and --field-border clears 3:1 so form
   inputs have a visible boundary.

   ---------------------------------------------------------------------------
   THE MECHANISM

   `light-dark()` picks a value from `color-scheme`, which we drive from the
   `data-theme` attribute. Bare `:root` declares `dark light`, so with no
   attribute at all (JS disabled, or a print/aux page loaded cold) the browser
   honours the OS preference and falls back to dark when there is none — the
   same behaviour the inline theme script gives everyone else, minus the JS.

   Baseline: light-dark() needs Chrome/Edge 123, Safari 17.5, Firefox 120. The
   @supports block at the bottom serves the dark palette to anything older, so
   the app degrades to "dark only" rather than to unstyled. Those literals are
   asserted equal to the dark half of every pair by the token test.
   ========================================================================= */

:root { color-scheme: dark light; }
[data-theme="dark"]  { color-scheme: dark; }
[data-theme="light"] { color-scheme: light; }

:root {
  /* ---------- Layout ---------- */
  /* Installed to an iPad/iPhone home screen, the app is drawn under the status
     bar: index.html asks for viewport-fit=cover and a black-translucent status
     bar, so y=0 is the top of the SCREEN, not the top of the usable area.
     Anything anchored to the viewport top has to add this or it sits underneath
     the clock, wifi and battery. Zero in a browser tab and on desktop, so it
     costs nothing there. (The bottom inset is already handled case by case —
     see env(safe-area-inset-bottom) throughout app.css.) */
  --safe-top: env(safe-area-inset-top, 0px);
  /* Viewport top to the BOTTOM of the floating nav pill — its 14px offset plus
     its own height — which is what content offsets and sticky sidebars key off.
     Carries the inset so all of them clear the status bar together. */
  --navh: calc(66px + var(--safe-top));
  /* The content column, and with it the floating nav pill (app.css sizes the
     pill from this so their edges line up). The wider step is applied by the
     media query below rather than set here — see it for why. */
  --maxw: 1200px;
  --pad: 21px;              /* every container's inner padding derives from this */

  /* ---------- Radii — same golden ladder as the spacing scale ----------
     Containers only. Every CONTROL is a pill (see below), so --r-xs/--r-sm
     should not appear on a button, chip, toggle or single-line field. */
  --r-xs: 5px; --r-sm: 8px; --r-md: 13px; --r-lg: 21px; --r-pill: 999px;

  /* ---------- Controls ----------
     Every button, chip, toggle and single-line field in the product is a PILL
     and is exactly one of three sizes. Height is set explicitly rather than
     implied by padding, so a row of mixed controls always lines up.

       sm  inline and secondary: table-row buttons, chips, tags, move/delete
       md  the default action size: primary, ghost, danger, segmented, icons
       lg  filter-bar row only, so search + select + toggle share one height

     If a new control does not fit one of these, the answer is to reuse the
     nearest one, not to add a fourth. Multi-line textareas are the single
     exception to the pill rule — they keep --r-md. */
  --ctl-h-sm: 28px;  --ctl-px-sm: 13px;  --ctl-fs-sm: 11.5px;
  --ctl-h-md: 36px;  --ctl-px-md: 16px;  --ctl-fs-md: 13px;
  --ctl-h-lg: 42px;  --ctl-px-lg: 21px;  --ctl-fs-lg: 14px;

  /* ---------- Golden ladder — the spacing scale ----------
     Fibonacci rungs, consecutive steps ~ x1.618: hairlines 3, chips 5,
     rows 8, cards 13, panels 21, page gutters 21/34. */
  --g1: 3px; --g2: 5px; --g3: 8px; --g4: 13px; --g5: 21px; --g6: 34px; --g7: 55px;

  /* ---------- Type scale ---------- */
  --fs-eyebrow: 11px;   /* uppercase section labels */
  --fs-mini: 11.5px;    /* captions, meta */
  --fs-sm: 12.5px;      /* secondary text */
  --fs-base: 15px;      /* body */
  --fs-lg: 17px;        /* emphasis / sub-headings */
  --fs-xl: 22px;        /* card values */
  --fs-2xl: 27px;       /* KPI values */
  --fs-3xl: 32px;       /* hero numerals */
  --fs-logo: 19px;
  --lsp-eyebrow: .14em; /* tracking for uppercase eyebrows */
  --lsp-micro: .08em;   /* tracking for small uppercase labels */

  /* ---------- Motion ---------- */
  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.2, .7, .3, 1);

  /* ---------- Fonts ---------- */
  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  /* ======================= PALETTE — light | dark ======================= */

  /* ---------- The elevation ladder ---------- */
  /* Light's canvas is the deeper cream the design work settled on — the whole
     ladder below --surface moved down one notch to reach it, rather than --bg
     being darkened into --well and collapsing the bottom rung. A groove still
     has somewhere to go. */
  --well:      light-dark(#d5ccbb, #0d0b09);
  --bg:        light-dark(#e1d8c6, #141310);
  --surface:   light-dark(#f6f2e9, #1c1a16);
  --surface-2: light-dark(#fcf9f4, #25221c);
  --surface-3: light-dark(#ffffff, #2f2b23);

  /* ---------- Lines ----------
     --border        panel outlines and dividers (quiet, ~1.3:1)
     --border-strong emphasis, dashed drop zones, hover borders, form controls
                     (~1.6:1)

     Both are deliberately soft. A form control is identified primarily by its
     FILL — inputs sit on --surface-2, one rung off the panel they're in, in
     both themes — with the border as a secondary cue and a full accent ring on
     :focus-visible. An earlier pass gave inputs a 3:1 border to satisfy WCAG
     2.1 SC 1.4.11 literally; at that weight every field shouted, so the
     boundary work moved to the fill. The token test pins both to a band so
     they can neither creep back up nor decay to the invisible 1.2:1 they were
     before the surface ladder existed. */
  --border:        light-dark(#ded5c3, #343027);
  --border-strong: light-dark(#ccc2ae, #494338);

  /* ---------- Interaction states ----------
     THE RULE, and there is only one. Two families, and every interactive thing
     in the product belongs to exactly one of them:

       ROWS AND CARDS (a list item, a supplier, a menu, a tile, a chat thread)
       move UP THE LADDER, so a state is always lighter in both themes:
         rest      the parent's own rung (usually transparent on a panel)
         :hover    one rung up      -> --surface-2
         selected  two rungs up     -> --surface-3, plus --accent-text on the
                                       label. It LIFTS; it never takes a tint.

       CONTROLS (button, chip, toggle, segmented option, icon button) move
       TOWARD THE ACCENT:
         rest      transparent or --surface-2
         :hover    --accent-soft
         on/active solid --accent + --accent-contrast

     What this replaced: selected rows were drawn with a
     color-mix(var(--accent), transparent) tint at 10%, 12%, 13% and 16% in
     different places, so the menus sidebar and the prices sidebar disagreed
     with each other and both went DARKER on light mode, against the ladder.
     A tint of the accent is never a selected state. If you reach for
     color-mix() on a background, you are almost certainly writing a bug. */

  /* ---------- Ink ---------- */
  --ink:   light-dark(#242018, #efe9dd);
  /* Light's --muted went a shade deeper WITH the canvas. On the old #ebe4d5 it
     cleared AA with almost nothing to spare (4.64:1); on the cream canvas the
     same value reads 4.15:1, which is a fail, and "the background got nicer"
     is not a reason to stop meta text being readable. Restated as a literal in
     --icon-search / --icon-chevron below — change both when you change this. */
  --muted: light-dark(#615b4e, #a49e91);
  --faint: light-dark(#7d7769, #868073);   /* decorative only — see contrast rule */

  /* ---------- Accent (gold, the default; presets override below) ----------
     --accent          the solid fill (>= 3:1 vs --surface)
     --accent-strong   the top of the fill's gradient / its hover
     --accent-contrast the foreground ON that fill (>= 4.5:1)
     --accent-text     the accent used AS text on a surface (>= 4.5:1)
     --accent-soft     a tint for backgrounds; derived, so it can never drift */
  --accent:          light-dark(#9b6c0b, #cdab6e);
  --accent-strong:   light-dark(#8c5d00, #ddbd83);
  --accent-contrast: light-dark(#ffffff, #191308);
  --accent-text:     light-dark(#926300, #dcbd84);
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);

  /* ---------- Status ----------
     Base value is text-capable (>= 4.5:1 on --surface) because that is how
     these are used ~30:1 over solid fills. -soft is a derived tint for
     backgrounds; -contrast is the foreground for the rare solid fill.

     Only the variants something actually renders exist — there is deliberately
     no --ok-contrast or --info-soft, because nothing sets text on a solid --ok
     fill or tints a background with --info. Add them when a component needs
     them; the token test fails on anything declared and unused.

     These carry the +/- deltas all over Insights, Prices and Home (.trend-up /
     .trend-down / .gp-ok / .dchip / .toast .dot), so they have to read as RED
     and GREEN at a glance, at 11-12px, not merely as "a dark colour". Two
     rules, in order:
       1. hue is fixed to the brand's original angles — green 137°, amber 80°,
          red 44°, blue 255°. Rotating red toward crimson or green toward teal
          is what makes a delta stop looking like a delta.
       2. chroma is pushed to the sRGB gamut edge for that hue, and only THEN
          is lightness set to whatever clears 4.5:1 on --surface.
     Saturation first, darkness last. The pre-token-system values sat at
     3.5-3.6:1 on this canvas, which is below AA for text this small — these
     match their hue and beat them on chroma. */
  --ok:      light-dark(#3e7c1c, #86b06a);
  --ok-soft: color-mix(in srgb, var(--ok) 14%, transparent);

  --warn:          light-dark(#916600, #dab15c);
  --warn-contrast: light-dark(#ffffff, #171207);
  --warn-soft:     color-mix(in srgb, var(--warn) 14%, transparent);

  --flag:          light-dark(#b84c0d, #d76f55);
  --flag-contrast: light-dark(#ffffff, #1b0f0c);
  --flag-soft:     color-mix(in srgb, var(--flag) 14%, transparent);

  --info: light-dark(#296ec0, #6ea8fe);

  /* ---------- Chart categories ----------
     Food deliberately rides --accent (see 05_insights.js); these three are
     fixed hues tuned per theme so stacked bars stay legible in both. */
  --cat-drink:    light-dark(#568fc8, #6ea8fe);
  --cat-cleaning: light-dark(#5b9c66, #7bd88f);
  --cat-other:    light-dark(#9c76c7, #b98cff);

  /* ---------- Skeletons ----------
     One tone, not two: the pulse animates the bar's OPACITY over this, so the
     "light end" of the breath is this colour blended into whatever surface
     the skeleton sits on — the second tone the old shimmer needed (--skel-a)
     fell out of use when the gradient did. */
  --skel-b: light-dark(#e1d8c6, #2f2b22);

  /* ---------- Depth ----------
     Dark casts pure black; light casts a warm brown, because a neutral black
     shadow on a cream canvas reads as dirt. Every shadow in the product comes
     from one of these — app.css declares no raw rgba(). */
  --shadow-sm:    light-dark(0 1px 2px rgba(74,58,26,.07),
                             0 1px 2px rgba(0,0,0,.4));
  --shadow:       light-dark(0 1px 2px rgba(74,58,26,.06), 0 16px 32px -18px rgba(74,58,26,.22),
                             0 1px 2px rgba(0,0,0,.4), 0 14px 30px -16px rgba(0,0,0,.6));
  --shadow-lg:    light-dark(0 2px 8px rgba(74,58,26,.08), 0 30px 60px -28px rgba(74,58,26,.28),
                             0 2px 6px rgba(0,0,0,.4), 0 30px 60px -28px rgba(0,0,0,.72));
  --shadow-pop:   light-dark(0 12px 28px rgba(74,58,26,.16),
                             0 12px 28px rgba(0,0,0,.34));   /* popovers, tooltips, toasts */
  --shadow-sheet: light-dark(0 -16px 44px rgba(74,58,26,.18),
                             0 -16px 44px rgba(0,0,0,.44));  /* bottom sheets (upward) */
  --shadow-nav:   light-dark(0 -10px 30px rgba(74,58,26,.10),
                             0 -10px 30px rgba(0,0,0,.24));  /* phone nav bar (upward) */
  --shadow-drag:  light-dark(0 14px 30px -10px rgba(74,58,26,.30), 0 3px 10px rgba(74,58,26,.14),
                             0 14px 30px -10px rgba(0,0,0,.5), 0 3px 10px rgba(0,0,0,.22));
  --shadow-btn:   light-dark(0 1px 2px rgba(74,58,26,.16),
                             0 1px 2px rgba(0,0,0,.18));     /* under filled buttons */
  --scrim:        light-dark(rgba(48,38,16,.38), rgba(0,0,0,.58));  /* modal backdrops */

  /* Hairline of light along a panel's top edge — reads as a crafted bevel. */
  --panel-hi: light-dark(rgba(255,255,255,.62), rgba(255,247,232,.05));
  /* Focus ring. */
  --ring: color-mix(in srgb, var(--accent) 38%, transparent);
  /* Page ambience: a whisper of warmth behind the content. */
  --bg-glow: radial-gradient(1100px 620px at 50% -320px,
             color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%);

  /* ---------- Themed inline SVG ----------
     A data: URI cannot read a custom property, so the two icons that must
     restate --muted as a literal live here, beside the value they mirror,
     rather than as [data-theme] overrides scattered through app.css. */
  /* NOT light-dark(): that function accepts colours only, so wrapping a url()
     in it computes to nothing and the icon silently vanishes on every browser
     (CSS.supports('background-image','light-dark(url(a),url(b))') is false in
     Chromium and Firefox both). The dark icons are declared here as the
     default and the light pair rides the same [data-theme]/media switches
     that drive color-scheme above — the one token family that has to do the
     dance by hand. */
  --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a49e91' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
  --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23a49e91' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
}

[data-theme="light"] {
  --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23615b4e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
  --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23615b4e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
}
/* System preference, for the "follow the OS" default (no data-theme set). */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23615b4e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
    --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23615b4e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  }
}

/* ---------- The wider content column, for real desktops only ----------
   Laptops and desktops get ~10% more column; tablets keep 1200px, which is what
   the layout was tuned against and what iPad landscape is meant to look like.

   The threshold is a WIDTH rather than a pointer/hover query because iPadOS
   reports a Magic Keyboard trackpad as a fine, hovering pointer — it would call
   an iPad a laptop. 1400px is chosen to clear the widest tablet viewport there
   is: the 13" iPad Pro (M4) is 1376 x 1032 CSS px in landscape, the 12.9" is
   1366. Both therefore stay at 1200, as do the 11" (1194) and Air (1180), which
   never reached the cap in the first place. A 1366-wide laptop keeps 1200 too —
   no regression, it simply doesn't earn the extra room. */
@media (min-width: 1400px) {
  :root { --maxw: 1320px; }
}

/* ---------- Accent presets ----------
   Each preset restates only the four accent tokens. --accent-soft, --ring and
   --bg-glow derive from --accent, so they follow automatically.

   ONE RULE, both themes: the foreground on a filled accent is the pole OPPOSITE
   the fill. Light mode fills are deep (OKLCH L ~.55-.58) and carry white; dark
   mode fills are light (L ~.66-.78) and carry a near-black tint of their own
   hue. Both directions clear 4.5:1, and the accent still clears 3:1 against
   --surface so a filled button reads as a control.

   The light fills are as bright as that white text allows — gold sits at the
   sRGB gamut edge for its hue (C .115 at L .566; more chroma just clips). Going
   lighter would need dark ink on the fill, which reads muddy on these hues. */
[data-accent="sage"] {
  --accent:          light-dark(#478241, #9bbd86);
  --accent-strong:   light-dark(#377431, #b0cd9c);
  --accent-contrast: light-dark(#ffffff, #0e160d);
  --accent-text:     light-dark(#3e7939, #aecb9b);
}
[data-accent="terracotta"] {
  --accent:          light-dark(#b65b3f, #d98a68);
  --accent-strong:   light-dark(#a64b2f, #e6a184);
  --accent-contrast: light-dark(#ffffff, #1c100c);
  --accent-text:     light-dark(#ab5236, #e8a98c);
}
[data-accent="slate"] {
  --accent:          light-dark(#3978b5, #88a9cf);
  --accent-strong:   light-dark(#2869a6, #a3bedb);
  --accent-contrast: light-dark(#ffffff, #0c151d);
  --accent-text:     light-dark(#306fac, #a6c1de);
}

/* ---------- Density ---------- */
[data-density="compact"] { --pad: 15px; }

/* ---------- Phone ---------- */
@media (max-width: 760px) {
  :root { --fs-logo: 16px; --pad: 16px; }
  [data-density="compact"] { --pad: 12px; }
}

/* ---------- Pre-2024 engines ----------
   No light-dark() => every token above would be invalid at computed-value time
   and the app would render unstyled. Serve the dark palette (the product's
   default) instead; light mode is simply unavailable there. These literals are
   asserted identical to the dark half of each pair by tests/guardrails/test_design_tokens.py. */
@supports not (color: light-dark(#fff, #000)) {
  :root {
    --well: #0d0b09; --bg: #141310; --surface: #1c1a16;
    --surface-2: #25221c; --surface-3: #2f2b23;
    --border: #343027; --border-strong: #494338;
    --ink: #efe9dd; --muted: #a49e91; --faint: #868073;
    --accent: #cdab6e; --accent-strong: #ddbd83; --accent-contrast: #191308; --accent-text: #dcbd84;
    --ok: #86b06a;
    --warn: #dab15c; --warn-contrast: #171207;
    --flag: #d76f55; --flag-contrast: #1b0f0c;
    --info: #6ea8fe;
    --cat-drink: #6ea8fe; --cat-cleaning: #7bd88f; --cat-other: #b98cff;
    --skel-b: #2f2b22;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 14px 30px -16px rgba(0,0,0,.6);
    --shadow-lg: 0 2px 6px rgba(0,0,0,.4), 0 30px 60px -28px rgba(0,0,0,.72);
    --shadow-pop: 0 12px 28px rgba(0,0,0,.34);
    --shadow-sheet: 0 -16px 44px rgba(0,0,0,.44);
    --shadow-nav: 0 -10px 30px rgba(0,0,0,.24);
    --shadow-drag: 0 14px 30px -10px rgba(0,0,0,.5), 0 3px 10px rgba(0,0,0,.22);
    --shadow-btn: 0 1px 2px rgba(0,0,0,.18);
    --scrim: rgba(0,0,0,.58);
    --panel-hi: rgba(255,247,232,.05);
    --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a49e91' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
    --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23a49e91' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  }
  [data-accent="sage"]       { --accent: #9bbd86; --accent-strong: #b0cd9c; --accent-contrast: #0e160d; --accent-text: #aecb9b; }
  [data-accent="terracotta"] { --accent: #d98a68; --accent-strong: #e6a184; --accent-contrast: #1c100c; --accent-text: #e8a98c; }
  [data-accent="slate"]      { --accent: #88a9cf; --accent-strong: #a3bedb; --accent-contrast: #0c151d; --accent-text: #a6c1de; }
}
