/* ==========================================================================
   Build a Drone, design token layer
   --------------------------------------------------------------------------
   Owner:      design session D1
   Approved:   2026-09-04 (see design/tokens.md)
   Amended:    2026-09-04 by D3, --font only
   Amended:    2026-09-04 by D3b, --advice and --nosig added
   Consumed by: every later design session (D2, D3, D4) and every frontend
                cluster that builds from their specs.

   HOW TO USE THIS FILE
   Link it, do not copy values out of it. Every mockup starts with:

       <link rel="stylesheet" href="tokens.css">

   If a screen needs a colour, a size or a spacing value that is not in here,
   that is a gap in this file, not a licence to invent one locally. Add it
   here with a comment saying what it is for, and say so in that session's
   spec so the next session knows it moved.

   WHAT IS DELIBERATELY NOT HERE
   Component CSS. This file is values only. Primitives live in
   d1-design-system.html and are specified in d1-design-system-spec.md.

   THE FOUR RULES THAT MUST NOT BE QUIETLY REVERSED
   The full numbered list is at the end of the spec. These four are the ones
   that will look like arbitrary detail to a build session, so they are
   restated here where the values are:

     1. --brand is a FILL colour only. It measures about 1.8:1 against white.
        As a border or as text it is invisible. Links, focus rings and text
        actions use --brand-text. Stock and compatibility pills use --ok.
        Three greens, three jobs, never swapped.
     2. --line is decorative (table rules, dividers) and is exempt from
        contrast rules. --border draws control boundaries and must clear 3:1.
        Collapsing them into one token fails an audit later.
     3. An unknown value renders as the word "Unknown" in the unknown
        treatment. Never blank, never a dash, never 0. Build-plan hard rule 2.
     4. Severity is never carried by colour alone. Every level also has a
        word and a glyph.

   CONTRAST
   Every pair below has been through the project's own checker:

       python3 check_wcag_contrast.py --pairs design/tokens.contrast.json

   That file is the machine-readable record. Re-run it after changing any
   colour here, and do not change a colour without re-running it.
   ========================================================================== */

:root{

  /* --- Neutrals, the shop -------------------------------------------------
     Page is a light warm grey and cards are pure white, because supplier
     photography is almost always shot on white and needs to sit on the
     ground it was shot on rather than float on a tinted panel. */
  --page:#F6F7F5;          /* page ground                                   */
  --surface:#FFFFFF;       /* cards, table body, product images             */
  --surface-2:#FAFAF9;     /* zebra rows, table heads, inset wells          */
  --ink:#16191C;           /* 17.65:1 on surface                            */
  --ink-soft:#3C434B;      /* 10.02:1 on surface, secondary copy            */
  --muted:#5C6570;         /* 5.91:1 on surface, labels and metadata        */

  /* Two border tokens on purpose. See rule 2 above. */
  --line:#E4E6E3;          /* decorative separators, contrast-exempt        */
  --border:#868D96;        /* control boundaries, 3.35:1 on surface         */

  /* --- Brand, three greens, three jobs ------------------------------------
     Green is the brand because of the competitive position: of the UK stores
     reviewed at D1, Flying Tech owns yellow, Drones Direct owns navy and
     Unmanned Tech owns near-monochrome. Nobody owns green.

     Green appears on the ACTION and the HIGHLIGHT, never as chrome
     upholstery. The nav is white with a 6px green underline on the active
     item, not a green bar. */
  --brand:#00DE7A;         /* FILL ONLY. Buttons, brand mark, active marker */
  --brand-hover:#00C86E;
  --brand-ink:#04231A;     /* 9.31:1 on --brand. The ink that goes on it    */
  --brand-text:#06774A;    /* 5.61:1 on surface. Links, text actions, focus */
  --brand-tint:#E8F6EE;    /* active nav background, chip selected state    */
  --brand-line:#A9D9C0;
  --brand-deep:#0F6B4A;    /* 6.52:1 on surface. Footer, heavier accents    */

  --hot:#B23C12;           /* 5.92:1 on surface. Sale and urgency ONLY, so  */
  --hot-tint:#FBEDE7;      /* it never competes with the primary action     */

  /* --- Severity, one scale used everywhere --------------------------------
     Traffic light is the spine. L3 and unknown are deliberate additions,
     approved 2026-09-03, not slippage:

       L1 blocker  red    the build does not work. Checkout blocked.
       L2 warning  amber  it works, something is off. Can proceed.
       L3 advice   cyan   nothing is wrong, something is missing to buy.
       L4 pass     green  checked and fine. Used sparingly.
       unknown     slate  cannot be judged. Never a pass and never a fail.

     L3 exists because a shopping prompt is not a fault, and styling it like
     one trains people to ignore the real ones. Unknown exists because of
     hard rule 2: a spec nobody published must not quietly pass a check it
     was never tested against. */
  --sev1:#A3170F; --sev1-tint:#FCD9D5; --sev1-line:#D45B50;
  --sev2:#8A4310; --sev2-tint:#FDE4C4; --sev2-line:#C97A1F;
  --sev3:#14607D; --sev3-tint:#D6EDF6; --sev3-line:#4A9CBC;
  --sev4:#0A5F30; --sev4-tint:#C9F2DB; --sev4-line:#2E9E64;

  /* Semantic aliases. Use these in component CSS so the meaning is readable
     at the point of use; they resolve to the severity scale above. */
  --danger:var(--sev1); --danger-tint:var(--sev1-tint); --danger-line:var(--sev1-line);
  --warn:var(--sev2);   --warn-tint:var(--sev2-tint);   --warn-line:var(--sev2-line);
  --info:var(--sev3);   --info-tint:var(--sev3-tint);   --info-line:var(--sev3-line);
  --ok:var(--sev4);     --ok-tint:var(--sev4-tint);     --ok-line:var(--sev4-line);

  /* Unknown is a first-class token, not a shade of muted. It is separated
     from muted by a dotted edge as well as by hue, so it survives greyscale
     and colour-blind viewing. See rule 3. */
  --unknown:#2F4E6B; --unknown-tint:#DCE8F2; --unknown-line:#6892B5;

  /* --- The storefront's advice and unknown roles --------------------------
     Amended 2026-09-04 (D3b): approved by Dylan in session, having been left
     proposed and unapproved at D3 part one.

     --info cyan and --unknown slate both pass on their own, at 7.00:1 and
     8.67:1. The problem is that they sit next to each other in the product
     page's four-state fit traffic light, where at badge size they both read
     as "blue" and a customer cannot tell advice from unknown at a glance.
     That distinction is the whole point of the traffic light, so the two
     roles are separated by hue on the storefront:

        --advice  violet   8.26:1 on --surface, the L3 advice role
        --nosig   graphite 8.24:1 on --surface, the unknown role

     The line value shipped here is #84909C, not the #8D99A5 that D3 part one
     proposed. That one measures 2.90:1 on --surface and fails the 3:1 that
     --border must clear, which nobody caught because part one recorded the
     text ratio and never checked the edge. #84909C is 3.26:1, within a
     hair of --border's own 3.35:1, so a dashed unknown edge reads at the
     same weight as a real control boundary.

     Scope is the customer-facing storefront. These do NOT replace --sev3 or
     --unknown, which stay exactly as they are: D2's builder and D5's admin
     surface are built against those, the workbench has its own dark ramp,
     and re-pointing a severity level under two finished specs is not this
     session's call. Whether the admin surface should adopt them too is an
     open question in d3b-theme-supporting-spec.md section 7. */
  --advice:#5B3A9E; --advice-tint:#EDE6FA; --advice-line:#9B7FD4;
  --nosig:#44505C;  --nosig-tint:#E8EBEE;  --nosig-line:#84909C;

  /* Neutral badge, for states with no severity (out of stock, archived). */
  --neutral-tint:#E9ECEF; --neutral-ink:#4A525C; --neutral-line:#B9C0C7;

  /* Focus. Deliberately NOT --brand: a focused green button needs a ring
     that is visible against green. */
  --focus:#06774A;

  /* --- Type ---------------------------------------------------------------
     Root 16px. Interface default 15px, shop reading copy 16px. Every UK
     store reviewed at D1 reads at 15 to 16px body; an earlier 14px pass read
     as an admin tool rather than a shop.

     Numeric columns use font-variant-numeric: tabular-nums on the interface
     face rather than switching to a monospace font, so figures align without
     the typeface changing mid-row. */
  /* Amended 2026-09-04 (D3): Inter added as the first named face, approved by
     Dylan in session. Served by Shopify's font picker or a self-hosted woff2 in
     the theme's assets; the existing system stack remains the fallback, so any
     file opened offline renders in it. No contrast pair changes. */
  --font:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;

  --t-2xs:0.75rem;    /* 12px, badges and column heads. The floor.          */
  --t-xs:0.8125rem;   /* 13px, metadata, hints, badge text                  */
  --t-sm:0.875rem;    /* 14px, dense list rows, field labels                */
  --t-base:0.9375rem; /* 15px, interface default                            */
  --t-md:1rem;        /* 16px, shop reading copy, button text               */
  --t-lg:1.1875rem;   /* 19px, card and panel titles                        */
  --t-xl:1.5rem;      /* 24px                                              */
  --t-2xl:1.875rem;   /* 30px, page titles                                  */
  --t-3xl:2.5rem;     /* 40px, hero only                                    */

  --lh-tight:1.3;     /* headings, table cells                              */
  --lh-normal:1.5;    /* interface copy                                     */
  --lh-prose:1.65;    /* long reading copy                                  */

  /* --- Space, 4px base ---------------------------------------------------- */
  --s-1:2px;   --s-2:4px;   --s-3:6px;   --s-4:8px;   --s-5:12px;
  --s-6:16px;  --s-7:20px;  --s-8:24px;  --s-9:32px;  --s-10:40px;
  --s-11:48px; --s-12:64px;

  --r-sm:6px; --r-md:8px; --r-lg:12px; --r-pill:999px;
  --shadow:0 1px 2px rgba(20,24,28,.05), 0 2px 8px rgba(20,24,28,.05);
  --shadow-lift:0 4px 16px rgba(20,24,28,.10);

  /* --- Controls -----------------------------------------------------------
     52px is deliberate. A primary action on a shop is the single most
     important target on the page, and 44px still read as an interface
     control rather than something you press. */
  --control-h:52px;
  --control-h-sm:42px;

  /* --- Density ------------------------------------------------------------
     Two densities, flipped by [data-density="dense"] on a REGION, not the
     page. Shopping pages stay comfortable; data-heavy customer-facing views
     (the component list view, search results) go dense.

     Measured, not estimated: a dense row is 44px and a comfortable row is
     57px with a two-line name cell. An earlier plan claimed 30px for dense;
     it is not, because the SKU sublabel makes every name cell two lines. */
  --d-text:var(--t-base);
  --d-row-y:var(--s-5);
  --d-cell-x:var(--s-6);
  --d-control-h:var(--control-h);
}

[data-density="dense"]{
  --d-text:var(--t-sm);
  --d-row-y:var(--s-3);
  --d-cell-x:var(--s-5);
  --d-control-h:var(--control-h-sm);
}

/* ==========================================================================
   THE WORKBENCH SCOPE
   --------------------------------------------------------------------------
   Applied to a REGION with class .wb, never to the page. This is the builder
   surface: the one place a dark ground earns its keep, and the only large
   dark surface on the site. The shop stays light.

   Three things define its character, all carried over from the builder
   preview the concept was validated on:

     1. A NEUTRAL grey-black ramp, not a green-black one. A green tint makes
        the workbench read as more shop chrome; grey lets amber, cyan and the
        action green all sit cleanly on top of it.
     2. MONOSPACE, scoped. Headings, labels, tags and figures only. Body copy
        stays in the interface face. This is where the technical feel comes
        from and it costs nothing.
     3. A GRID GROUND behind the diagram, so it reads as a workbench mat
        rather than an empty black rectangle.

   AMBER IS THE SELECTION COLOUR HERE, and only here. Amber as a brand was
   rejected at D1: it is close to Amazon's, it fails as text on white, and
   Flying Tech already owns yellow in this category. Amber as "the option you
   picked" on a dark technical surface is a different job, it was right in
   the original builder, and it is kept. Selection is a 2px border plus a
   tint plus a bolder label, never colour on its own.
   ========================================================================== */
.wb{
  --wb-bg:#0F1113;          /* the workbench ground                         */
  --wb-surface:#16191C;     /* panels, cards, option chips                  */
  --wb-surface-2:#1C2024;   /* raised or inset within a panel               */
  --wb-well:#0A0C0D;        /* the diagram mat                              */
  --wb-line:#262B30;        /* decorative separators                        */
  --wb-border:#6A737C;      /* control boundaries, 3.66:1 on --wb-surface   */
  --wb-grid:rgba(233,236,239,.055); /* the mat's grid rule                  */

  --wb-ink:#E9ECEF;         /* 14.88:1 on --wb-surface                      */
  --wb-ink-soft:#C2C8CE;    /* 10.46:1                                      */
  --wb-muted:#8B939B;       /* 5.67:1                                       */

  --wb-select:#F0A339;      /* 8.41:1. THE PICKED OPTION. Nothing else.     */
  --wb-select-tint:#241C10;
  --wb-info:#4CB8D9;        /* 7.70:1. Slot filled, advice, L3.             */
  --wb-info-tint:#0E2229;
  --wb-pass:#57C98A;        /* 8.51:1. L4 pass. A pill, never a fill.       */
  --wb-pass-tint:#10241A;
  --wb-block:#FF6B5E;       /* 6.32:1. L1 blocker.                          */
  --wb-block-tint:#2A1512;
  --wb-notideal:#B79CF0;    /* 7.59:1. L2 "Not ideal", decision #190. Never */
  --wb-notideal-tint:#221B34; /* --wb-select (decision #27, amber is the   */
                            /* picked option only) and never --wb-block    */
                            /* (freed 2026-09-15 for a real Does-not-fit   */
                            /* verdict, decision #190 - it had been doing  */
                            /* an empty required slot's job since cluster  */
                            /* 2.1, which nobody noticed until this        */
                            /* cluster put a real verdict on the same      */
                            /* screen). Matches --advice's ROLE, not its   */
                            /* hex - the storefront's violet is dark text  */
                            /* on light tints, this is bright text on a    */
                            /* dark ground, the same relationship --wb-    */
                            /* info/--wb-pass/--wb-block already have to   */
                            /* their light-side counterparts.              */
  --wb-unknown:#9FB6C6;     /* 8.39:1. Never a pass and never a fail.       */
  --wb-unknown-tint:#182126;

  --wb-action:#00DE7A;      /* buttons only, same rule as --brand           */
  --wb-action-ink:#04231A;

  /* Ink that goes ON a solid severity fill, for remedy buttons. */
  --wb-block-ink:#2A0B08;
  --wb-select-ink:#241404;
  --wb-info-ink:#06222B;
}

/* ==========================================================================
   NAMING
   --------------------------------------------------------------------------
   Component classes carry a component prefix. During D1 a slot indicator
   named .sdot.empty silently inherited 48px of padding from the unrelated
   .empty empty-state block and rendered a 9px dot as a large oval. Generic
   state words (.empty, .open, .active, .small) must never appear unprefixed.
   ========================================================================== */
