/* ═══════════════════════════════════════════════════════════════════════════
   CRAZY DUCK — DESIGN TOKENS
   crazyduck.com.au · a side brand of OneHQ
   ───────────────────────────────────────────────────────────────────────────
   Plain CSS. No build step, no preprocessor, no network requests.

   BRAND DIRECTION v2 — OBSIDIAN & CHAMPAGNE
   ─────────────────────────────────────────
   v1 was fountain-pen ink on warm stock with a burnt-sienna accent: a light
   brand with a dark scheme bolted on. v2 inverts that. Crazy Duck's own ground
   is obsidian and its accent is a champagne gold, because the thing we are
   selling is the calm surface — and a still black surface with one warm light
   on it says that in a way warm paper cannot.

   The change is a change of GROUND, not of structure. The waterline still runs
   through the mark, the interface and the writing (BRAND.md §6); the white-label
   contract in §5 below is untouched. See BRAND.md §7 for the argument, including
   why a gold is not the rubber-duck yellow that v1 rightly banned.

   HOW THIS FILE IS ORGANISED
   ──────────────────────────
   §0  Registration ...... @property, so bad input degrades instead of exploding
   §1  Brand palette ..... Crazy Duck's own colours. Fixed. Not overridable.
   §2  Scale ............. type, space, radii, shadow, motion, z. Ours. Fixed.
   §3  Light scheme ...... semantic surfaces + inks + the lightness windows
   §4  Dark scheme ....... same, re-derived. The brand's home ground.
   §5  Accent derivation .. THREE TIERS, progressively enhanced:
                             tier 0 — static      (any browser)
                             tier 1 — color-mix() (Safari 16.2+, Chrome 111+)
                             tier 2 — oklch(from) (Safari 16.4+, Chrome 119+)
   §6  Preference queries . reduced motion, more contrast, forced colours

   THE TWO LAYERS
   ──────────────
   Layer 1 is Crazy Duck's own identity (--cd-brand-*). It appears on the
   marketing site and the practice admin. It never appears in a client's
   booking flow except as the "Powered by" mark.

   Layer 2 is the white-label layer. An accounting firm supplies a handful of
   inputs; everything else — spacing, type, structure, states, motion — is ours
   and must stay coherent whether they pick navy or an unfortunate lime.

   Obsidian and champagne live entirely in layer 1. A firm that sets no accent
   inherits the champagne, which is deliberate — the default state of the
   product is already coherent — but a firm that sets navy gets navy, and
   nothing in layer 2 knows or cares that our own brand went dark.

   WHAT A PRACTICE MAY SET  (and nothing else)
   ───────────────────────────────────────────
     --cd-accent          <color>   their primary. Default = Crazy Duck champagne.
     --cd-on-accent       <color>   label on the accent. OPTIONAL: derived if absent.
     --cd-accent-ink      <color>   accent-as-text.   OPTIONAL: derived if absent.
     --cd-font-body       <stack>   UI type. Default: the platform's own UI face.
     --cd-font-display    <stack>   headings. Default: a transitional serif stack.
     --cd-radius-scale    <number>  0 = square, 1 = default, 2 = pill-ish.
     --cd-density         <number>  0.85 compact … 1 default … 1.15 roomy.
     --cd-canvas-tint     <number>  0–1. Bleeds ≤5% of the accent into the page.
     --cd-shadow-strength <number>  0 = flat, 1 = default, 1.6 = lifted.
     --cd-size-base       <length>  1rem default. Set to 16px only for a
                                    non-iframe embed on a host with a hostile
                                    root font-size (it costs the user's zoom
                                    preference, so avoid it).

   Backgrounds and text colours are deliberately NOT overridable. That is the
   single rule that keeps contrast provable. See §5 for the guarantee.

   WHERE TO SET THEM — AND THE ONE WAY THIS GOES WRONG
   ───────────────────────────────────────────────────
   On the element that carries class `cd` (the widget root), or on :root for a
   hosted page. Derived tokens are declared on the same selector list, so they
   recompute from whatever accent wins on that element:

     <div class="cd" style="--cd-accent:#12294B; --cd-radius-scale:.5">…</div>

   Set --cd-accent anywhere ELSE and you get a silent, plausible wrong answer.
   §5's derivations are declared on `:root, .cd, [data-cd-scheme]` and nowhere
   else, so an element outside that list gets the raw accent — which inherits —
   while --cd-accent-solid, --cd-on-accent, --cd-accent-ink, --cd-accent-line
   and --cd-accent-subtle all keep the values computed on the nearest ancestor
   that DID match. On a page whose root accent is the default, that means every
   button, fill and wash comes out Crazy Duck champagne while the practice's own
   colour sits in --cd-accent looking correct in devtools.

   It has happened, on the marketing site's white-label section — the one panel
   on crazyduck.com.au whose entire argument is "you give us one colour and
   everything derives from it" — where a `<div class="mk-device">` set the
   accent and matched none of the three selectors. Nothing warns you: the value
   is a real colour, the contrast guarantee still holds, and the card renders
   beautifully in the wrong brand.

   If you need a derivation site that is not a widget root, `data-cd-scheme`
   is the hook: put the scheme the surface is in on the same element as the
   accent and everything below it re-derives.

   Server-rendered pages should emit an explicit --cd-on-accent computed from
   true WCAG luminance (reference implementation in §5). The CSS derivation is
   the safety net for hand-written embeds, not the authority.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ─── §0  REGISTRATION ─────────────────────────────────────────────────────
   Typed custom properties give us three things: a bad value from a practice's
   config falls back to the initial value instead of poisoning the cascade;
   relative colour syntax gets a real <color> to read channels from; and
   numbers can be used in calc() without unit gymnastics. */

@property --cd-accent {
  syntax: "<color>"; inherits: true; initial-value: #ebd3a3;
}
@property --cd-accent-solid {
  syntax: "<color>"; inherits: true; initial-value: #ebd3a3;
}
@property --cd-accent-shade {
  syntax: "<color>"; inherits: true; initial-value: #000000;
}
@property --cd-radius-scale    { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --cd-density         { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --cd-shadow-strength { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --cd-canvas-tint     { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --cd-motion          { syntax: "<number>"; inherits: true; initial-value: 1; }


/* ─── §1 · §2 · §3  BASE: brand palette, scale, light scheme ───────────────── */

:root,
.cd,
[data-cd-scheme="light"] {

  /* ── §1  CRAZY DUCK PALETTE (fixed) ─────────────────────────────────────
     Obsidian, champagne, bone, and duck-egg as the cool counterweight.

     Three ramps and one accent. The OBSIDIAN ramp is the brand's ground: a
     warm-neutral near-black, deliberately not the blue-black of every other
     SaaS dark mode and no longer v1's green-cast ink. The BONE ramp is good
     stock — it is the light scheme's page and, inverted, the text on obsidian.
     CHAMPAGNE is the one warm light in the room.

     The gold is metallic, not sunny: chroma 0.068 at hue 84° in OKLCH, which
     is a sixth of the chroma of a rubber duck. That distinction is the whole
     licence for it — see BRAND.md §7. There is no bright yellow in this file
     and there is not going to be one.

     Every ratio below is measured, not estimated. Dark values are stated
     against the obsidian canvas, light values against bone paper. */

  /* Obsidian — the brand's ground. */
  --cd-brand-obsidian:        #0a0a09;  /* the page in deep water              */
  --cd-brand-obsidian-raised: #131211;  /* cards                               */
  --cd-brand-obsidian-sunken: #1c1a17;  /* wells, inputs                       */
  --cd-brand-obsidian-deep:   #050504;  /* below the waterline. Deeper than
                                           the page, because that is what the
                                           thing is depicting.                 */
  --cd-brand-onyx:            #302b24;  /* hairline on obsidian                */
  --cd-brand-onyx-strong:     #443d33;

  /* Bone — good stock. The light scheme's page, and the ink on obsidian. */
  --cd-brand-bone:         #f6f2e9;   /* 17.7:1 on obsidian                     */
  --cd-brand-bone-2:       #c2bcae;   /* 10.4:1 on obsidian                     */
  --cd-brand-bone-3:       #968f80;   /*  6.1:1 on obsidian — the muted floor   */
  --cd-brand-bone-4:       #6b655a;   /*  3.4:1 — non-text only (rules, icons)  */

  --cd-brand-paper:        #f7f4ec;   /* warm laid stock                        */
  --cd-brand-paper-raised: #fffdf6;
  --cd-brand-paper-sunken: #efeade;
  --cd-brand-rule:         #ded8c9;   /* decorative hairline                    */

  /* Ink — warm near-black on stock, tuned to the obsidian hue rather than
     v1's green cast, so the two schemes read as one brand. */
  --cd-brand-ink:          #14120f;   /* 17.0:1 on paper                        */
  --cd-brand-ink-2:        #4a463e;   /*  8.5:1 on paper                        */
  --cd-brand-ink-3:        #585349;   /*  6.9:1 on paper — the muted floor      */
  --cd-brand-ink-4:        #8c8578;   /*  3.3:1 — non-text only (rules, icons)  */

  /* Champagne — THE accent, and the default --cd-accent.
     13.5:1 on obsidian. As a fill it needs a dark label, which tier 2 works
     out for itself; --cd-brand-on-gold is the hand-picked warm near-black we
     use where the fill is ours rather than a practice's. */
  --cd-brand-champagne:      #ebd3a3;
  --cd-brand-champagne-lift: #f7e7c6;  /* the lit edge of the sheen            */
  --cd-brand-champagne-deep: #e2c48c;  /* the shaded edge                      */
  --cd-brand-on-gold:        #17130b;  /* 11.0:1 on the darkest sheen stop     */

  /* Brass — the same gold conditioned to carry text on stock. A champagne is
     too light to be read on bone paper, so the light scheme gets this instead
     and the two are the same hue: 5.3:1 on paper, 5.7:1 on a raised card. */
  --cd-brand-brass:        #7d6029;

  /* Graphite — what a practice that has told us NO colour gets on the pages
     their clients see.
     ─────────────────────────────────────────────────────────────────────────
     Not champagne, which is the initial value of --cd-accent and therefore what
     an unset practice used to inherit. That put OUR brand on THEIR page, on the
     one surface whose entire proposition is that it is theirs — and it did it
     silently, to every firm who finished signup without opening the colour
     picker, which is most of them.

     Warm, not neutral: it is the ink of the light scheme lifted just far enough
     to be a colour rather than the text. Every §5 derivation handles it without
     a special case — dark enough that --cd-accent-solid leaves it alone and
     --cd-on-accent comes back near-white, dark enough to clear 3:1 as a line,
     and its wash is a pale warm grey rather than a tint of anything.

     It also makes the homepage demo tell the truth. The device's resting state
     is now what a real unset practice looks like, so "watch it turn into yours"
     is a change from NO colour to their colour — which lands for a navy firm
     exactly as hard as it lands for anyone else. Pick a handsome colour for the
     demo instead and every visitor whose brand happens to be near it sees
     nothing happen at all. */
  --cd-brand-graphite:     #3a352d;

  /* The sheen. Crazy Duck's own gold, with a light edge and a shaded one — it
     is what makes the gold read as a metal rather than a swatch. LAYER 1 ONLY:
     never on a control that a practice's accent could land on, because a
     gradient is not a colour and the contrast guarantee in §5 is written about
     colours. Marketing and the practice admin, nowhere else. */
  --cd-brand-gold-sheen:
      linear-gradient(180deg,
        var(--cd-brand-champagne-lift) 0%,
        var(--cd-brand-champagne)     52%,
        var(--cd-brand-champagne-deep) 100%);

  /* Duck-egg — the cool counterweight, and the one colour that stops the
     palette being entirely warm. Decorative and informational only. A pun that
     reads as a colour rather than as a gag, which is why it survived v1. */
  --cd-brand-duckegg:      #9ac7bc;   /* 10.1:1 on obsidian — decorative        */
  --cd-brand-duckegg-ink:  #2e5a51;   /*  7.0:1 on paper                        */

  --cd-brand-success:      #2e6b45;
  --cd-brand-warning:      #8a5a00;
  --cd-brand-danger:       #a5192a;   /* crimson-lean, so it can never be read
                                         as the accent — which mattered when the
                                         accent was a sienna and still matters
                                         now that a warning amber sits next to
                                         a champagne gold                       */

  /* ── §2  TYPE ───────────────────────────────────────────────────────────
     No webfonts. Not a compromise — a decision. Firms embed us under strict
     CSP, and the booking flow is supposed to look like the firm's, not ours.
     So the product UI wears the platform's own UI face and disappears.

     THE DISPLAY STACK is where the whole character budget is spent, and v2
     spends it differently. v1 led with Iowan Old Style and Charter: warm,
     bookish, low-contrast — right for ink on paper, wrong for gold on
     obsidian, where a low-contrast face goes muddy and heavy. A gold headline
     on black wants HIGH stroke contrast and sharp, fine serifs: the thin
     strokes catch the light, which is exactly the effect being paid for.

     So the stack now leads with Hoefler Text and Didot on Apple, and Sitka
     Banner — the display optical size of Matthew Carter's Sitka, installed on
     every Windows 10/11 machine — on Windows. Both are genuinely good faces
     and both ship a real italic, which matters more here than anywhere else:
     the undercut (BRAND.md §5) is set in the display italic, and a synthesised
     slant on a high-contrast serif looks like a mistake. Big Caslon is
     deliberately absent for exactly that reason — no italic.

     Georgia stays as the last resort. It always was the floor and it is a
     perfectly respectable floor.

     Self-hosting plan for crazyduck.com.au marketing (NOT for the widget):
     two weights of a licensed display serif + one variable grotesque, subset
     to Latin + AU punctuation + $ and the en-dash, served from /fonts on our
     own origin, woff2, font-display:swap, <link rel=preload> for the display
     weight only. The widget never loads them. */

  --cd-font-display:
      "Hoefler Text", Didot, "Sitka Banner", "Sitka Display",
      "Sitka Subheading", Constantia, "Palatino Linotype", Palatino,
      "Book Antiqua", "Noto Serif Display", "Noto Serif",
      "Liberation Serif", Georgia, serif;

  --cd-font-body:
      "Segoe UI Variable Text", "Segoe UI", -apple-system, BlinkMacSystemFont,
      "SF Pro Text", "Helvetica Neue", "Noto Sans", "Liberation Sans",
      Arial, sans-serif;

  /* LAYER 1 ONLY. Crazy Duck's own UI face, for marketing chrome and the
     practice admin: nav, eyebrows, button labels, small caps. It prefers the
     DISPLAY optical size of the platform UI face — Segoe UI Variable Display
     on Windows 11, SF Pro Display on Apple — which is cut tighter and cleaner
     at large sizes and holds tracked uppercase without going ragged.

     It must never reach the widget. --cd-font-body is what a client reads,
     because a client should be reading their accountant's typeface, not ours. */
  --cd-font-brand:
      "Segoe UI Variable Display", "SF Pro Display", "Avenir Next", Avenir,
      "Segoe UI", -apple-system, BlinkMacSystemFont, "Helvetica Neue",
      "Noto Sans", "Liberation Sans", Arial, sans-serif;

  --cd-font-mono:
      ui-monospace, "SF Mono", "Cascadia Mono", "Segoe UI Mono",
      "Roboto Mono", Menlo, Consolas, monospace;

  /* Type scale — ~1.2 with a widened top. Anchored on --cd-size-base so the
     whole system can be pinned for a hostile embed without touching 40 rules. */
  --cd-size-base:  1rem;
  --cd-text-2xs:   calc(var(--cd-size-base) * 0.6875);  /* 11 — eyebrows only    */
  --cd-text-xs:    calc(var(--cd-size-base) * 0.75);    /* 12 — meta, legal      */
  --cd-text-sm:    calc(var(--cd-size-base) * 0.875);   /* 14 — hints, dense UI  */
  --cd-text-base:  calc(var(--cd-size-base) * 1);       /* 16 — the floor for
                                                           anything a client reads */
  --cd-text-md:    calc(var(--cd-size-base) * 1.125);   /* 18 */
  --cd-text-lg:    calc(var(--cd-size-base) * 1.3125);  /* 21 */
  --cd-text-xl:    calc(var(--cd-size-base) * 1.5625);  /* 25 */
  --cd-text-2xl:   calc(var(--cd-size-base) * 1.875);   /* 30 */
  --cd-text-3xl:   calc(var(--cd-size-base) * 2.25);    /* 36 */
  --cd-text-4xl:   calc(var(--cd-size-base) * 2.75);    /* 44 */

  --cd-leading-flat:    1;
  --cd-leading-tight:   1.16;
  --cd-leading-snug:    1.3;
  --cd-leading-normal:  1.55;
  --cd-leading-relaxed: 1.72;

  /* A high-contrast display serif sets tighter than a bookish one without
     closing up, so --cd-track-display goes a little further negative than v1's
     -0.021em. Anything set in --cd-font-brand as tracked uppercase uses
     --cd-track-brand, which is wider than the product's eyebrow tracking on
     purpose: layer 1 is allowed to be a bit more composed than layer 2. */
  --cd-track-display: -0.026em;
  --cd-track-tight:   -0.011em;
  --cd-track-normal:  0em;
  --cd-track-eyebrow:  0.1em;   /* ledger column heads */
  --cd-track-brand:    0.16em;  /* layer 1 only — marketing + admin caps */

  --cd-weight-regular: 400;
  --cd-weight-medium:  500;
  --cd-weight-semi:    600;
  --cd-weight-bold:    700;

  /* ── SPACE ──────────────────────────────────────────────────────────────
     4px unit, multiplied by --cd-density. A firm that wants a tighter or
     roomier feel turns one dial and the whole system moves together. */
  --cd-u:         calc(var(--cd-size-base) * 0.25 * var(--cd-density));
  --cd-space-1:   var(--cd-u);
  --cd-space-2:   calc(var(--cd-u) * 2);
  --cd-space-3:   calc(var(--cd-u) * 3);
  --cd-space-4:   calc(var(--cd-u) * 4);
  --cd-space-5:   calc(var(--cd-u) * 5);
  --cd-space-6:   calc(var(--cd-u) * 6);
  --cd-space-8:   calc(var(--cd-u) * 8);
  --cd-space-10:  calc(var(--cd-u) * 10);
  --cd-space-12:  calc(var(--cd-u) * 12);
  --cd-space-16:  calc(var(--cd-u) * 16);
  --cd-space-20:  calc(var(--cd-u) * 20);
  --cd-space-24:  calc(var(--cd-u) * 24);

  /* ── SHAPE ──────────────────────────────────────────────────────────────
     v2 set these small — "stationery, not a consumer app" — and for a letter
     or an invoice that was right. It is the wrong instinct for the one screen
     this system has to win on. The booking widget is a stranger's first
     contact with a firm, sitting on that firm's own website beside whatever
     else is on the page, and at 6px a card reads as a form field: the thing
     you fill in at a government portal, not the thing you press. Nobody names
     the radius, but everybody feels the difference between an interface that
     looks like paperwork and one that looks like a product — and paperwork is
     precisely the feeling this product exists to remove.

     So the card sizes step up to where the rest of the world already is
     (12-16px) and the small ones follow, so the family still reads as one
     family. --cd-radius-scale is untouched and still does its job: a firm who
     wants the older, squarer look sets it to 0.5 and gets it back exactly. */
  --cd-radius-xs:   calc(4px  * var(--cd-radius-scale));
  --cd-radius-sm:   calc(8px  * var(--cd-radius-scale));
  --cd-radius-md:   calc(12px * var(--cd-radius-scale));
  --cd-radius-lg:   calc(18px * var(--cd-radius-scale));
  --cd-radius-xl:   calc(24px * var(--cd-radius-scale));
  --cd-radius-pill: 999px;

  /* SELECTION.
     A chosen card is drawn with the page's own ink, not with the accent, and
     that is deliberate: --cd-accent-line only has to clear 3:1 against the
     surface, so on a pale champagne or a soft grey the "chosen" border is
     technically visible and practically not — you can be looking straight at
     the thing you picked and still be hunting for it. Ink wins whatever
     colour the firm sent us, and it survives greyscale. The accent still
     carries the selection too, as the wash and the mark; this is the third
     channel, not a replacement.

     A ring rather than a thicker border, because growing a border by a pixel
     moves the content inside it and a row of cards twitches as you click
     along it. Composed AFTER --cd-ring in every box-shadow that uses it, so a
     focused card still paints its focus ring over the top. */
  --cd-selected-ring: 0 0 0 var(--cd-border) var(--cd-ink);

  --cd-hairline: 1px;
  --cd-border:   1px;
  --cd-border-strong: 1.5px;

  /* ── MINIMA (accessibility floors — do not lower) ────────────────────── */
  --cd-tap:        44px;   /* WCAG 2.5.8 target size, applied everywhere      */
  --cd-focus-w:    2px;    /* inner ring                                      */
  --cd-focus-w-2:  4px;    /* outer ring                                      */
  --cd-focus-offset: 0px;

  /* ── ELEVATION ──────────────────────────────────────────────────────────
     Tinted with the ink hue, never pure black. Multiplied by
     --cd-shadow-strength so a firm can flatten the whole system to zero. */
  --cd-shadow-rgb: 20 18 15;
  --cd-shadow-1:
      0 1px 1px -0.5px rgb(var(--cd-shadow-rgb) / calc(0.10 * var(--cd-shadow-strength))),
      0 2px 6px -2px   rgb(var(--cd-shadow-rgb) / calc(0.08 * var(--cd-shadow-strength)));
  --cd-shadow-2:
      0 1px 1px -0.5px rgb(var(--cd-shadow-rgb) / calc(0.09 * var(--cd-shadow-strength))),
      0 6px 16px -6px  rgb(var(--cd-shadow-rgb) / calc(0.14 * var(--cd-shadow-strength)));
  --cd-shadow-3:
      0 1px 2px -1px   rgb(var(--cd-shadow-rgb) / calc(0.08 * var(--cd-shadow-strength))),
      0 14px 34px -12px rgb(var(--cd-shadow-rgb) / calc(0.20 * var(--cd-shadow-strength)));
  --cd-shadow-inset: inset 0 1px 0 rgb(255 255 255 / 0.55);

  /* ── MOTION ─────────────────────────────────────────────────────────────
     One decelerating curve does almost all the work. --cd-motion is a 0/1
     switch that §6 flips; components multiply transform distances by it so
     reduced-motion removes movement rather than merely shortening it. */
  --cd-motion: 1;
  --cd-dur-1: 110ms;
  --cd-dur-2: 190ms;
  --cd-dur-3: 300ms;
  --cd-dur-4: 520ms;
  --cd-ease:        cubic-bezier(0.16, 0.84, 0.34, 1);
  --cd-ease-in-out: cubic-bezier(0.62, 0, 0.28, 1);
  --cd-ease-spring: cubic-bezier(0.2, 1.22, 0.36, 1);

  /* ── LAYERS ─────────────────────────────────────────────────────────────
     Low numbers on purpose. We live inside somebody else's page. */
  --cd-z-base:    0;
  --cd-z-sticky:  10;
  --cd-z-overlay: 20;
  --cd-z-popover: 30;
  --cd-z-toast:   40;

  /* ── MEASURE ────────────────────────────────────────────────────────────— */
  --cd-measure:      62ch;
  --cd-width-narrow: 26rem;
  --cd-width-form:   34rem;
  --cd-width-page:   60rem;

  /* ══ §3  LIGHT SCHEME ══════════════════════════════════════════════════
     Contrast ratios are against --cd-canvas (#f7f4ec, Y = 0.905).
     Anything used for body text clears 4.5:1. Anything used for a control
     border or a meaningful graphic clears 3:1 (WCAG 1.4.11).

     v2's brand is dark, but the light scheme is not a courtesy — it is where
     most booking pages will actually be read, because it is the scheme a
     firm's own website is most likely in. It gets the same care it always did.
     What changed is the hue: ink and paper are now warm-neutral rather than
     green-cast, so a champagne accent has something to sit on. */

  --cd-canvas-base:    var(--cd-brand-paper);  /* --cd-canvas is derived in §5 */
  --cd-surface:        var(--cd-brand-paper-raised);
  --cd-surface-2:      var(--cd-brand-paper-sunken);
  --cd-surface-inverse: var(--cd-brand-obsidian);

  --cd-ink:            var(--cd-brand-ink);      /* 17.0 : 1 */
  --cd-ink-2:          var(--cd-brand-ink-2);    /*  8.5 : 1 */
  --cd-ink-3:          var(--cd-brand-ink-3);    /*  6.9 : 1 */
  --cd-ink-4:          var(--cd-brand-ink-4);    /*  3.3 : 1 — never text     */
  --cd-ink-on-inverse: var(--cd-brand-bone);

  --cd-line:           var(--cd-brand-rule);     /* decorative rules          */
  --cd-line-strong:    #c8c1af;
  --cd-control-line:   #8c8578;                  /*  3.3 : 1 — field borders  */
  --cd-control-line-hover: #6f695e;

  /* Crazy Duck's own gold, for the rare layer-1 element that appears on a
     light surface — the admin's brand chrome, a mark on stock. Fixed rather
     than derived, because it is OUR colour and does not move when a practice
     supplies theirs. 5.3:1 on paper, 5.7:1 on a raised card. */
  --cd-brand-gold-ink: var(--cd-brand-brass);

  --cd-success:        var(--cd-brand-success);
  --cd-warning:        var(--cd-brand-warning);
  --cd-danger:         var(--cd-brand-danger);
  --cd-info:           var(--cd-brand-duckegg-ink);
  --cd-on-status:      #ffffff;

  --cd-success-subtle: #e2ede5;
  --cd-warning-subtle: #f4eada;
  --cd-danger-subtle:  #f6e2e3;
  --cd-info-subtle:    #e2edea;

  --cd-disabled-bg:    #eae5d7;
  --cd-disabled-ink:   #655f53;   /* 5.0:1 on --cd-disabled-bg. Disabled text is
                                     exempt from 1.4.3; we clear it anyway,
                                     because "which day is unavailable" is
                                     information the client still has to read.  */

  /* Focus: a two-tone ring. The inner ring is the surface colour, the outer is
     maximum contrast against the surface. Whatever sits underneath — a lime
     button, a navy button, a photo — at least one of the two boundaries clears
     3:1, so the indicator is never invisible. The accent is deliberately NOT
     used here: it is the one thing we cannot predict. */
  --cd-focus-inner: var(--cd-surface);
  --cd-focus-outer: #0b0a08;    /* 19.4:1 on a raised card */

  --cd-selection-bg: #f0e2c4;
  --cd-selection-fg: var(--cd-brand-ink);

  --cd-shade-toward: #0a0806;   /* tier-1 hover/active mixing target */

  /* ── LIGHTNESS WINDOWS (tier 2) ───────────────────────────────────────
     These four pairs are the ONLY thing that differs between light and dark
     in the accent derivation, so §5 can be written once. See §5 for the
     arithmetic that justifies each number. */
  --cd-w-ink-lo:    0;      --cd-w-ink-hi:    0.47;   /* accent as text        */
  --cd-w-ink-cmax:  0.5;                              /* chroma cap for text   */
  --cd-w-line-lo:   0;      --cd-w-line-hi:   0.60;   /* accent as border/icon */
  --cd-w-solid-lo:  0;      --cd-w-solid-hi:  1;      /* accent as a fill      */
  --cd-w-subtle-mix: 10%;   --cd-w-subtle-mix-2: 17%;
  --cd-w-subtle-lo: 0.83;   --cd-w-subtle-hi: 1;      /* the wash — guarantee 5 */

  /* The mark — guarantees 6 and 7. A fill lighter than L 0.645 cannot make
     3:1 against a bone surface (Y = 0.645³ ≈ 0.27 is the boundary), so it
     flips: the fill becomes page-ink lightness and the accent moves onto it
     as the label, floored at L 0.66 so it clears 4.5:1 on that ink even
     after chromatic drift. */
  --cd-w-flip: 0.645;       --cd-w-flip-sign: 1;
  --cd-w-markbg-l: 0.245;                             /* the flipped fill      */
  --cd-w-onmark-lo: 0.66;   --cd-w-onmark-hi: 1;      /* accent as its label   */
}


/* ═══ §4  DARK SCHEME ══════════════════════════════════════════════════════
   The brand's home ground, as of v2. Obsidian, bone, champagne.

   Two entry points, same payload:
     • [data-cd-scheme="dark"]  — explicit, works on any element
     • the media query          — automatic, unless something up the tree has
                                  opted out with data-cd-scheme="light"
   Only palette values and the four lightness windows live here. The accent
   derivations in §5 are written once and read these.

   This is still a full re-derivation rather than an inversion. The obsidian
   ramp lifts in tinted steps rather than by adding grey, so a card on the page
   reads as a lit surface rather than as a lighter rectangle — which is the
   entire difference between a dark theme that looks expensive and one that
   looks like a settings toggle.

   The two blocks below are byte-identical apart from the selector. That
   duplication is unavoidable: a media query cannot be folded into an attribute
   selector, and aliasing the payload through a second layer of custom
   properties would cost a resolution step on every token in the system. If you
   edit one, edit the other. */

[data-cd-scheme="dark"] {
  --cd-canvas-base:     var(--cd-brand-obsidian);
  --cd-surface:         var(--cd-brand-obsidian-raised);
  --cd-surface-2:       var(--cd-brand-obsidian-sunken);
  --cd-surface-inverse: var(--cd-brand-bone);

  --cd-ink:             var(--cd-brand-bone);     /* 17.7 : 1 on canvas */
  --cd-ink-2:           var(--cd-brand-bone-2);   /* 10.4 : 1 */
  --cd-ink-3:           var(--cd-brand-bone-3);   /*  6.1 : 1 */
  --cd-ink-4:           var(--cd-brand-bone-4);   /*  3.4 : 1 — never text */
  --cd-ink-on-inverse:  var(--cd-brand-obsidian);

  --cd-line:            var(--cd-brand-onyx);
  --cd-line-strong:     var(--cd-brand-onyx-strong);
  --cd-control-line:    #6e675b;   /*  3.5 : 1 */
  --cd-control-line-hover: #8b8474;

  --cd-brand-gold-ink:  var(--cd-brand-champagne);   /* 13.5 : 1 — layer 1 */

  --cd-success:         #86c79b;
  --cd-warning:         #dcae57;
  --cd-danger:          #f08a90;
  --cd-info:            #8ec4b8;
  --cd-on-status:       var(--cd-brand-obsidian);

  --cd-success-subtle:  #16281c;
  --cd-warning-subtle:  #2c2211;
  --cd-danger-subtle:   #331618;
  --cd-info-subtle:     #142926;

  --cd-disabled-bg:     #1a1815;
  --cd-disabled-ink:    #8e8778;   /* 5.0:1 on --cd-disabled-bg */

  --cd-focus-inner:     var(--cd-surface);
  --cd-focus-outer:     #f8f4ea;   /* 17.0:1 on a raised card */

  --cd-selection-bg:    #3a3122;
  --cd-selection-fg:    var(--cd-brand-bone);

  --cd-shade-toward:    #fdf8ec;
  --cd-shadow-rgb:      0 0 0;
  --cd-shadow-inset:    inset 0 1px 0 rgb(255 255 255 / 0.05);

  /* Dark flips every window. Accent-as-text must now be LIGHT, and a fill has
     a floor so a conservative navy does not vanish into the canvas. */
  --cd-w-ink-lo:    0.76;   --cd-w-ink-hi:    1;
  --cd-w-ink-cmax:  0.14;                       /* saturated hues vibrate on dark */
  --cd-w-line-lo:   0.58;   --cd-w-line-hi:   1;
  --cd-w-solid-lo:  0.42;   --cd-w-solid-hi:  1;
  --cd-w-subtle-mix: 16%;   --cd-w-subtle-mix-2: 24%;
  --cd-w-subtle-lo: 0;      --cd-w-subtle-hi: 0.28;

  /* The mark, mirrored: on obsidian it is the DARK fills that vanish, so the
     flip catches anything darker than L 0.61 and the flipped fill is bone.
     The accent-as-label window caps at 0.47 so a navy label still clears
     4.5:1 on that bone. */
  --cd-w-flip: 0.61;        --cd-w-flip-sign: -1;
  --cd-w-markbg-l: 0.93;
  --cd-w-onmark-lo: 0;      --cd-w-onmark-hi: 0.47;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-cd-scheme="light"]),
  .cd:not([data-cd-scheme="light"]) {
    --cd-canvas-base:     var(--cd-brand-obsidian);
    --cd-surface:         var(--cd-brand-obsidian-raised);
    --cd-surface-2:       var(--cd-brand-obsidian-sunken);
    --cd-surface-inverse: var(--cd-brand-bone);

    --cd-ink:             var(--cd-brand-bone);
    --cd-ink-2:           var(--cd-brand-bone-2);
    --cd-ink-3:           var(--cd-brand-bone-3);
    --cd-ink-4:           var(--cd-brand-bone-4);
    --cd-ink-on-inverse:  var(--cd-brand-obsidian);

    --cd-line:            var(--cd-brand-onyx);
    --cd-line-strong:     var(--cd-brand-onyx-strong);
    --cd-control-line:    #6e675b;
    --cd-control-line-hover: #8b8474;

    --cd-brand-gold-ink:  var(--cd-brand-champagne);

    --cd-success:         #86c79b;
    --cd-warning:         #dcae57;
    --cd-danger:          #f08a90;
    --cd-info:            #8ec4b8;
    --cd-on-status:       var(--cd-brand-obsidian);

    --cd-success-subtle:  #16281c;
    --cd-warning-subtle:  #2c2211;
    --cd-danger-subtle:   #331618;
    --cd-info-subtle:     #142926;

    --cd-disabled-bg:     #1a1815;
    --cd-disabled-ink:    #8e8778;   /* 5.0:1 on --cd-disabled-bg */

    --cd-focus-inner:     var(--cd-surface);
    --cd-focus-outer:     #f8f4ea;

    --cd-selection-bg:    #3a3122;
    --cd-selection-fg:    var(--cd-brand-bone);

    --cd-shade-toward:    #fdf8ec;
    --cd-shadow-rgb:      0 0 0;
    --cd-shadow-inset:    inset 0 1px 0 rgb(255 255 255 / 0.05);

    --cd-w-ink-lo:    0.76;   --cd-w-ink-hi:    1;
    --cd-w-ink-cmax:  0.14;
    --cd-w-line-lo:   0.58;   --cd-w-line-hi:   1;
    --cd-w-solid-lo:  0.42;   --cd-w-solid-hi:  1;
    --cd-w-subtle-mix: 16%;   --cd-w-subtle-mix-2: 24%;
    --cd-w-subtle-lo: 0;      --cd-w-subtle-hi: 0.28;

    --cd-w-flip: 0.61;        --cd-w-flip-sign: -1;
    --cd-w-markbg-l: 0.93;
    --cd-w-onmark-lo: 0;      --cd-w-onmark-hi: 0.47;
  }
}


/* ═══ §5  ACCENT DERIVATION ════════════════════════════════════════════════

   THE PROBLEM
   ───────────
   A practice hands us one colour. We have to build a whole interface out of
   it and it has to be legible whether they send #12294B or #C6F224. Eight
   distinct jobs, and one colour cannot do all eight:

     --cd-accent          the colour EXACTLY as supplied. Decorative surfaces,
                          the logo tint. Never carries text, never has to
                          clear a contrast bar.
     --cd-accent-solid    a FILL that carries a label. Lightness conditioned.
     --cd-on-accent       the label on that fill. Near-white or near-black.
     --cd-accent-ink      the accent used AS TEXT on a page surface.
     --cd-accent-line     the accent used as a BORDER or icon (needs 3:1).
     --cd-accent-subtle   a wash for selected/hovered backgrounds.
     --cd-accent-mark     a fill that IS the signal: the chosen slot or date,
                          a ticked checkbox, a stepper dot, a badge. Must
                          stand off the SURFACE as well as carry its label.
     --cd-on-mark         the tick or label on that fill. When the fill had
                          to flip to page ink (see guarantee 6), this is the
                          accent itself — the firm's colour becomes the
                          writing instead of the paper.

   THE GUARANTEE
   ─────────────
   For any --cd-accent in the sRGB gamut, with tier 2 active:

     1. contrast(--cd-on-accent, --cd-accent-solid)  ≥ 4.5:1
     2. contrast(--cd-accent-ink, --cd-surface)      ≥ 4.5:1
     3. contrast(--cd-accent-line, --cd-surface)     ≥ 3:1
     4. contrast(--cd-ink, --cd-accent-subtle)       ≥ 4.5:1
     5. hover and active states only ever INCREASE (1).
     6. contrast(--cd-accent-mark, --cd-surface)     ≥ 3:1
     7. contrast(--cd-on-mark, --cd-accent-mark)     ≥ 4.5:1

   Guarantee 6 is the one v2 shipped without, and the gap was visible from a
   metre away: a practice whose accent is a light yellow got a selected time
   tile filled with that yellow, on a bone card — black label perfectly
   legible (guarantee 1 held), the TILE itself all but invisible against the
   unchosen ones. --cd-accent-solid deliberately does not condition against
   the surface: a primary button lives inside a border and a layout slot that
   identify it regardless. A chosen tile in a grid of thirty identical tiles
   has nothing but its fill. Different job, so a different token — a light
   accent on a light scheme (or a dark accent on dark) flips the mark to page
   ink and promotes the accent to the label, which is how a yellow-brand
   practice gets an ink tile with yellow writing rather than a yellow tile
   that washes out.

   THE ARITHMETIC BEHIND THOSE NUMBERS
   ───────────────────────────────────
   For an achromatic colour, Oklab L = Y^(1/3) where Y is WCAG relative
   luminance. So Y = L³, and:

       contrast vs white = 1.05 / (L³ + 0.05)
       contrast vs black = (L³ + 0.05) / 0.05

   White clears 4.5:1 while L ≤ 0.568. Black clears 4.5:1 while L ≥ 0.559.
   The two windows overlap in a sliver, so a single threshold at ~0.5636 is
   optimal — for GREYS. Chromatic colours drift: reds and oranges report an
   Oklab L about 0.03 higher than Y^(1/3) predicts, greens and blues about
   0.03 lower. Straddling that drift needs headroom on both sides, so
   --cd-accent-solid pushes lightness out of the ambiguous middle to the
   nearest safe edge:

       L' = (l ≤ 0.59) ? min(l, 0.53) : max(l, 0.65)

   Worst case that is a 0.06 shift in perceptual lightness — one shade step —
   and ONLY for mid-tone accents where neither a white nor a black label would
   otherwise pass. Navy (L ≈ 0.28) and lime (L ≈ 0.87) are untouched. The
   firm's exact colour still appears, unmodified, as --cd-accent.

   --cd-accent-ink clamps to L ≤ 0.47 in light (Y ≤ 0.104, so ≥ 6.0:1 against
   the canvas even after the worst chromatic drift) and L ≥ 0.76 in dark
   (≥ 8.0:1). Nobody has ever complained that their link colour was one shade
   deeper. They do complain about illegible lime text, so this clamp is hard.

   SERVER-SIDE REFERENCE (authoritative — the wizard should emit these)
   ───────────────────────────────────────────────────────────────────
     const srgb = c => (c /= 255) <= 0.04045 ? c/12.92 : ((c+0.055)/1.055)**2.4;
     const lum  = ([r,g,b]) => 0.2126*srgb(r) + 0.7152*srgb(g) + 0.0722*srgb(b);
     const ratio = (a,b) => { const [x,y] = [lum(a),lum(b)].sort((m,n)=>n-m);
                              return (x + 0.05) / (y + 0.05); };
     // onAccent = ratio(WHITE, accent) >= ratio(BLACK, accent) ? '#ffffff' : '#141414'
     // If max(ratio(WHITE,accent), ratio(BLACK,accent)) < 4.5, REJECT the accent
     // in the setup wizard and offer the nearest passing shade. Do not silently
     // ship an illegible button.

   TIERS
   ─────
   tier 0 runs everywhere and is honest about being approximate.
   tier 1 needs color-mix(). tier 2 needs relative colour syntax.
   Later tiers override earlier ones at identical specificity. Palette blocks
   (§3/§4) never touch these properties, so the cascade stays untangled. */


/* ── tier 0 · static fallback (any browser) ──────────────────────────────
   v2 FLIPPED TWO OF THESE, and the reason is worth writing down.

   The default accent used to be a dark sienna, so a hard-coded WHITE label was
   the right guess for --cd-on-accent and the raw accent was a passable guess
   for --cd-accent-ink. The default accent is now a light champagne, and both
   of those guesses invert: white on champagne is 1.3:1, and champagne as text
   on bone paper is 1.4:1. Left alone, this block would have shipped an
   unreadable button and an invisible link to every browser without color-mix().

   So tier 0 now falls back to Crazy Duck's own conditioned pair. The cost is
   that a practice which supplied navy, on a browser older than color-mix
   (Safari < 16.2, Chrome < 111 — early 2023), sees our brass on links instead
   of their navy. That is a wrong colour rather than an illegible one, it only
   affects a browser three years out of date, and the setup wizard emits an
   explicit --cd-on-accent for exactly this reason (see the reference above).
   An accent that cannot be read is a bug; an accent that is the wrong hue on
   an ancient browser is a compromise. */
:root, .cd, [data-cd-scheme] {
  --cd-canvas:              var(--cd-canvas-base);
  --cd-accent-solid:        var(--cd-accent);
  --cd-accent-hover:        var(--cd-accent);
  --cd-accent-active:       var(--cd-accent);
  --cd-accent-shade:        var(--cd-shade-toward);
  --cd-on-accent:           var(--cd-brand-on-gold);
  --cd-accent-ink:          var(--cd-brand-gold-ink);
  --cd-accent-line:         var(--cd-accent);
  --cd-accent-subtle:       var(--cd-surface-2);
  --cd-accent-subtle-hover: var(--cd-surface-2);
  --cd-accent-ghost:        var(--cd-surface-2);
  /* The mark falls back to the labelled-fill pair: possibly washed out on an
     old browser, never illegible — the same compromise as the pair above. */
  --cd-accent-mark:         var(--cd-accent-solid);
  --cd-on-mark:             var(--cd-on-accent);
}

/* ── tier 1 · color-mix (Safari 16.2+, Chrome 111+, Firefox 113+) ───────
   Mixes are scheme-independent because they mix toward --cd-surface and
   --cd-shade-toward, which §3/§4 have already flipped. --cd-accent-ink here
   is pulled 26% toward the page ink, which is a good approximation for most
   accents and NOT a guarantee — that is what tier 2 is for. */
@supports (color: color-mix(in oklab, red, blue)) {
  :root, .cd, [data-cd-scheme] {
    --cd-canvas: color-mix(in oklab, var(--cd-canvas-base),
                           var(--cd-accent) calc(var(--cd-canvas-tint) * 5%));

    --cd-accent-shade:        var(--cd-shade-toward);
    --cd-accent-hover:        color-mix(in oklab, var(--cd-accent-solid) 90%, var(--cd-accent-shade));
    --cd-accent-active:       color-mix(in oklab, var(--cd-accent-solid) 82%, var(--cd-accent-shade));
    --cd-accent-ink:          color-mix(in oklab, var(--cd-accent) 74%, var(--cd-ink));
    --cd-accent-line:         color-mix(in oklab, var(--cd-accent) 86%, var(--cd-ink));
    --cd-accent-subtle:       color-mix(in oklab, var(--cd-accent) var(--cd-w-subtle-mix),   var(--cd-surface));
    --cd-accent-subtle-hover: color-mix(in oklab, var(--cd-accent) var(--cd-w-subtle-mix-2), var(--cd-surface));
    --cd-accent-ghost:        color-mix(in oklab, var(--cd-accent) 8%, transparent);
  }
}

/* ── tier 2 · relative colour syntax (Safari 16.4+, Chrome 119+, FF 128+) ──
   Where the guarantee actually comes from.

   k = clamp(0, (l − 0.59) × 1000, 1) is a step function: 0 for any accent
   darker than L 0.59, 1 for anything lighter. CSS has no branching, so the
   step is built out of a steep ramp and then used to blend the two arms of
   each piecewise expression. It appears three times below; it is the same k
   every time. */
@supports (color: oklch(from red l c h)) {
  :root, .cd, [data-cd-scheme] {

    /* FILL — pushed out of the ambiguous band, then floored/ceilinged so a
       dark accent stays visible on a dark canvas. */
    --cd-accent-solid: oklch(from var(--cd-accent)
        clamp(var(--cd-w-solid-lo),
              calc(
                (1 - clamp(0, calc((l - 0.59) * 1000), 1)) * min(l, 0.53)
                +    clamp(0, calc((l - 0.59) * 1000), 1)  * max(l, 0.65)
              ),
              var(--cd-w-solid-hi))
        c h);

    /* LABEL on that fill — near-white below the threshold, near-black above.
       Chroma 0: a tinted label reads beautifully and cannot be guaranteed,
       so it does not ship. */
    --cd-on-accent: oklch(from var(--cd-accent-solid)
        calc(1 - 0.88 * clamp(0, calc((l - 0.59) * 1000), 1)) 0 h);

    /* SHADE — the exact opposite of the label. Mixing the fill toward this
       always moves it AWAY from the label, so hover and active can only ever
       improve contrast. This is the trick that makes state changes safe on
       an accent we have never seen. */
    --cd-accent-shade: oklch(from var(--cd-accent-solid)
        clamp(0, calc((l - 0.59) * 1000), 1) 0 h);

    --cd-accent-hover:  color-mix(in oklab, var(--cd-accent-solid) 90%, var(--cd-accent-shade));
    --cd-accent-active: color-mix(in oklab, var(--cd-accent-solid) 82%, var(--cd-accent-shade));

    /* TEXT — hard lightness clamp. Non-negotiable. */
    --cd-accent-ink: oklch(from var(--cd-accent)
        clamp(var(--cd-w-ink-lo), l, var(--cd-w-ink-hi))
        min(c, var(--cd-w-ink-cmax)) h);

    /* BORDER / ICON — softer clamp, 3:1 rather than 4.5:1. */
    --cd-accent-line: oklch(from var(--cd-accent)
        clamp(var(--cd-w-line-lo), l, var(--cd-w-line-hi)) c h);

    /* THE MARK — guarantees 6 and 7.
       A second step function, same construction as k: call it f, 1 when the
       conditioned fill sits too close to the canvas to be seen against it
       (lighter than --cd-w-flip on a light scheme, darker on dark —
       --cd-w-flip-sign turns the same expression around), 0 otherwise.

       f = 0: the mark IS --cd-accent-solid, label and all. Navy on bone,
              champagne on obsidian — accents that already stand off the page
              are passed through untouched.
       f = 1: the fill flips to page-ink lightness with a whisper of the
              accent's hue left in it, and the accent itself becomes the
              label, floored/capped into the --cd-w-onmark window so it
              clears 4.5:1 on that ink. A yellow-brand practice gets an ink
              tile with yellow writing, not a yellow tile that washes out.

       Derived from --cd-accent-solid rather than --cd-accent so f reads the
       lightness the fill would actually have had — solid's own conditioning
       has already pushed mid-tones out of the ambiguous band, which is what
       lets one threshold decide this cleanly. */
    --cd-accent-mark: oklch(from var(--cd-accent-solid)
        calc(
          (1 - clamp(0, calc((l - var(--cd-w-flip)) * 1000 * var(--cd-w-flip-sign)), 1)) * l
          +    clamp(0, calc((l - var(--cd-w-flip)) * 1000 * var(--cd-w-flip-sign)), 1)  * var(--cd-w-markbg-l)
        )
        calc(c * (1 - 0.85 * clamp(0, calc((l - var(--cd-w-flip)) * 1000 * var(--cd-w-flip-sign)), 1)))
        h);

    --cd-on-mark: oklch(from var(--cd-accent-solid)
        calc(
          (1 - clamp(0, calc((l - var(--cd-w-flip)) * 1000 * var(--cd-w-flip-sign)), 1))
            * (1 - 0.88 * clamp(0, calc((l - 0.59) * 1000), 1))
          +    clamp(0, calc((l - var(--cd-w-flip)) * 1000 * var(--cd-w-flip-sign)), 1)
            * clamp(var(--cd-w-onmark-lo), l, var(--cd-w-onmark-hi))
        )
        calc(c * clamp(0, calc((l - var(--cd-w-flip)) * 1000 * var(--cd-w-flip-sign)), 1))
        h);

    /* THE WASH — guarantee 5, added in v2.
       The mix is the same one tier 1 makes; this clamps the RESULT's lightness.
       Necessary because v1's default accent was dark, so mixing 16% of it into a
       dark surface barely moved the surface. A champagne is L 0.875, and 16% of
       that lifts the wash far enough that --cd-ink-3 — the muted ink used for
       every secondary line inside a selected option — landed at 4.32:1.

       Guarantee 4 never caught it, because guarantee 4 measures the PRIMARY ink
       on the wash and primary ink had 12:1 to spare. The pair that actually
       failed was the muted one, so §5 now states it as its own guarantee.

       The fix is the same fix as everywhere else in this file: clamp the
       derivation rather than the firm's colour. Dark caps the wash at L 0.28,
       light floors it at 0.83, and a dark accent on a dark scheme is untouched —
       navy comes out at L 0.199 and never meets the ceiling.

       One accepted cost: for a LIGHT accent on a dark scheme, base and hover
       both clamp to nearly the same lightness, so the wash alone stops
       signalling hover. That is survivable because the wash was never the only
       hover signal — the border moves to --cd-accent-line as well — and §11
       forbids colour being the only signal for anything. */
    --cd-accent-subtle: oklch(from
        color-mix(in oklab, var(--cd-accent) var(--cd-w-subtle-mix), var(--cd-surface))
        clamp(var(--cd-w-subtle-lo), l, var(--cd-w-subtle-hi)) c h);
    --cd-accent-subtle-hover: oklch(from
        color-mix(in oklab, var(--cd-accent) var(--cd-w-subtle-mix-2), var(--cd-surface))
        clamp(var(--cd-w-subtle-lo), l, var(--cd-w-subtle-hi)) c h);
  }
}


/* ═══ §6  USER PREFERENCES ═════════════════════════════════════════════════ */

/* Reduced motion. Handled at the token layer so no component has to remember.
   --cd-motion: 0 is the important one — components multiply transform
   distances by it, so movement is REMOVED rather than merely sped up. */
@media (prefers-reduced-motion: reduce) {
  :root, .cd, [data-cd-scheme] {
    --cd-motion: 0;
    --cd-dur-1: 1ms;
    --cd-dur-2: 1ms;
    --cd-dur-3: 1ms;
    --cd-dur-4: 1ms;
    --cd-ease:        linear;
    --cd-ease-in-out: linear;
    --cd-ease-spring: linear;
  }
}

/* More contrast. Firms up the hairlines and widens the focus ring; the ink
   ramp collapses toward the primary so nothing sits at the 4.5:1 floor. */
@media (prefers-contrast: more) {
  :root, .cd, [data-cd-scheme] {
    --cd-ink-2:  var(--cd-ink);
    --cd-ink-3:  var(--cd-ink-2);
    --cd-line:   var(--cd-control-line);
    --cd-line-strong: var(--cd-control-line);
    --cd-border: 1.5px;
    --cd-border-strong: 2px;
    --cd-focus-w:   3px;
    --cd-focus-w-2: 5px;
    --cd-shadow-strength: 0;
  }
}
