/* ============================================================================
   P2 CATALOG -- THE TOKEN LAYER.  CMD-012 Slice 1.

   PROVENANCE, AND ITS ONE GAP. The brief says "every value below comes from
   homepage.html; take them from there rather than retyping from this table if
   they disagree." homepage.html was never delivered (asked for twice; see
   content/design-v3/BRIEF.md). So the brief's own table IS the source here, and
   where the two could disagree nobody can tell. Every value in this file is
   traceable to that table or is derived from it by a stated rule below -- there
   are no eyeballed values, because a guessed token on a site whose selling point
   is verifiability is the same defect as a guessed specification figure.

   HOW THIS REPLACES THE OLD SYSTEM RATHER THAN JOINING IT. The theme carried a
   mature token layer (v2.15.1): a ten-step neutral ramp, an eight-step type
   scale, a nine-step space scale, roughly a thousand var() call sites. The brief
   says "do not leave two systems running side by side". Rewriting a thousand
   call sites with a script is precisely what rule 13 and ADR-015 forbid -- the
   last scripted replace in this theme deleted 121 lines and php -l passed on the
   result. So the NEW palette is declared canonical here, and the legacy ramp is
   REDEFINED IN TERMS OF IT at the bottom of this file. One source of colour
   truth, no call site touched, and the substitution is provable by diffing
   computed styles rather than by reading a diff.

   CONTRAST IS MEASURED, NOT ASSUMED. Ratios below were computed, not estimated;
   the script is content/design-v3/bin/contrast.py and the verifier re-runs it.
   Two findings that the brief's own assertion 10 would have failed on the
   brief's own palette are recorded at the stage block.
   ============================================================================ */

/* ---- FACES. Self-hosted: the brief forbids a live Google Fonts request, and
        verifier assertion 8 checks for one. Both Inter families ship as ONE
        variable file each covering 400-700, which is every weight the brief asks
        for (Inter Tight 500/600/700, Inter 400/500/600) in two requests rather
        than six. Files verified wOF2 BY MAGIC BYTES before install, not by
        extension -- the Quoty reference once declared a WOFF 1.0 file as
        format('woff2') and Chrome happened to forgive it.

        unicode-range is carried over unchanged from the block these replace. It
        is not boilerplate: it covers the micro sign (U+00B5) and the en/em
        dashes (U+2000-206F), without which these specification tables cannot be
        set. ---------------------------------------------------------------- */
@font-face{
  font-family:'Inter Tight';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('../fonts/inter-tight-latin-var.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,
    U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Inter';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('../fonts/inter-latin-var.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,
    U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
/* IBM Plex Mono is RETAINED, and this is a deviation the report names. The brief
   replaces the two SANS families and is silent on the mono. Plex Mono sets the
   article numbers and the specification figures -- 60 call sites through
   --face-data -- and Slice 5 says the sizes table and the citation treatment are
   to be kept "exactly as they are". Retiring the mono would change them. A
   proportional face cannot set a part number honestly, which is the reason the
   mono was introduced in the first place (v2.24). */
@font-face{
  font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url('../fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,
    U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;
  src:url('../fonts/ibm-plex-mono-600-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,
    U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root{
  /* ======================= THE BRIEF'S PALETTE ============================ */
  /* Ratios are against --paper unless noted. */
  --ink:#0B1220;      /* 18.72:1  headings, body, the one dark CTA            */
  --slate:#525C6B;    /*  6.77:1  secondary text that still has to be read    */
  --soft:#8A93A2;     /*  3.10:1  SEE THE WARNING BELOW -- not body text      */
  --line:#E7EAEF;     /*  1.21:1  hairline. decorative only                   */
  --line-2:#D7DCE4;   /*  1.38:1  stronger hairline. decorative only          */
  --mist:#F6F7F9;     /*  1.07:1  the one tinted surface                      */
  --link:#1F4FCB;     /*  6.91:1  links ONLY, per the approved direction      */
  --paper:#FFFFFF;

  /* --soft FAILS WCAG AA FOR NORMAL TEXT at 3.10:1, and the approved mockup
     sets real content in it -- the per-stage product counts, the hero's three
     proof bullets. That is a defect in the specification, not in this file, and
     it is reported rather than silently fixed: the token keeps the approved
     value, and the RULE applied across the theme is that --soft may set only
     text that is decorative or redundant with an adjacent label. Anything a
     buyer has to read is --slate. Assertion 10 covers stage colours only, so no
     verifier would have caught this; contrast.py checks it now. */

  --link-ink:#193FA2;  /* 9.05:1 -- hover/visited and link-on-mist, derived by
                          darkening --link, hue and saturation held            */
  --link-soft:#EEF2FD;  /* FILL ONLY, 1.06:1. never text, never a border       */
  --link-line:#C8D5F6;

  /* ======================= STAGE, THE ORGANISING IDEA ===================== */
  /* The brief's five. Colour is information here and never decoration, so each
     stage owns exactly one hue and it follows the stage onto every surface. */
  --cut:#C4423A;
  --mount:#C68A14;
  --grind:#1E7A57;
  --polish:#2A5BD7;
  --carry:#6F7887;

  /* TEXT-SAFE STAGE INKS, and why they exist. Assertion 10 requires 4.5:1 for
     text on every stage colour used behind text. Measured on the brief's own
     palette against --paper:

         cut     5.01  PASS      polish  5.87  PASS
         grind   5.28  PASS      carry   4.46  FAIL
         mount   2.98  FAIL

     and the approved mockup sets the stage LABEL in the stage colour, so mount
     and carry would have failed the brief's own gate. Rather than re-open the
     aesthetic -- which the brief forbids -- each stage keeps its hue for dots,
     bars, rails and fills, and gains an ink for when it sets text. Derived by
     reducing HLS lightness with hue and saturation held until the ratio clears
     4.6; cut, grind and polish already passed and are therefore UNCHANGED, so
     three of the five inks are the hue itself and nothing moved. This is the
     same pattern the theme already used for --accent / --accent-ink and
     --c-titanium / --c-titanium-ink. */
  --cut-ink:#C4423A;     /* 5.01 -- unchanged */
  --mount-ink:#9B6C10;   /* 4.62 -- darkened from #C68A14 (2.98) */
  --grind-ink:#1E7A57;   /* 5.28 -- unchanged */
  --polish-ink:#2A5BD7;  /* 5.87 -- unchanged */
  --carry-ink:#6D7584;   /* 4.64 -- darkened from #6F7887 (4.46) */

  /* WHITE ON THE HUE, for badges and filled chips. mount is 2.98 and therefore
     may never carry white text; it takes --ink instead (6.28). The others clear
     4.5 with white. Encoded so a template cannot get it wrong by hand. */
  --on-cut:#FFFFFF; --on-mount:var(--ink); --on-grind:#FFFFFF;
  --on-polish:#FFFFFF; --on-carry:#FFFFFF;

  /* ======================= TYPE =========================================== */
  --face:'Inter',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,"Noto Sans",sans-serif;
  --face-display:'Inter Tight','Inter',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --face-data:'IBM Plex Mono',ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;

  /* The brief's scale. Mobile values are applied in the media query at the foot
     of this file, so a template never chooses a breakpoint value by hand. */
  --t-h1:52px;        /* 29px mobile */
  --t-h2:32px;        /* 24px mobile */
  --t-body:16.5px;
  --t-card:16.5px;
  --t-small:13.5px;   /* the absolute floor for rendered text */
  --lh-body:1.6;

  /* THE FLOOR, stated as a token so it is checkable. The brief sets two
     different minimums -- 13.5px for anything, 14px for body copy -- and
     verifier assertion 5 checks the first. They are separate tokens because
     collapsing them is how the 14px floor quietly becomes 13.5. */
  --t-floor:13.5px;
  --t-floor-body:14px;

  /* ======================= GEOMETRY ======================================= */
  /* "Radius: 10px controls, 16-22px containers. Only these two families." */
  --radius:10px;        /* controls: buttons, inputs, chips  */
  --radius-lg:18px;     /* containers: cards, panels, sheets */
  --radius-pill:999px;  /* retained: pills cannot wrap, so they are not a third
                           family -- the rule from v2.16 is unchanged */
  --radius-data:0;      /* RETAINED EXCEPTION, reported. Tables and the dark
                           instrument panel stay square: a rounded corner on a
                           datasheet reads as an app widget, and Slice 5 says the
                           sizes table is to be kept exactly as it is. A square
                           corner is the absence of a radius, not a third family. */

  /* ======================= SHADOW ========================================= */
  /* One token. "Nothing heavier anywhere." */
  --shadow:0 1px 2px rgba(11,18,32,.04);

  /* ======================= SPACE ========================================== */
  /* 4px base scale -- already the shape of the legacy ramp, so the steps below
     are the existing values and nothing re-spaces. */
  --s-1:4px;--s-2:8px;--s-3:12px;--s-4:16px;--s-5:24px;
  --s-6:32px;--s-7:48px;--s-8:64px;--s-9:96px;
  --maxw:1216px;

  /* ============ THE LEGACY RAMP, REDEFINED ONTO THE ABOVE ================= */
  /* Every token below is an ALIAS now, not a value. This is what makes the two
     systems one system without touching a thousand call sites. Where the map is
     not one-to-one it is stated, and in every case the substitution moves
     contrast UP or leaves it alone -- no call site gets less readable. */
  --n-0:var(--paper);
  --n-1:var(--mist);      /* was #fafafa */
  --n-2:var(--mist);      /* was #f5f5f5 -- collapses with --n-1; the brief has
                             ONE tinted surface and two were never distinguishable */
  --n-3:var(--line);      /* was #e5e5e5 */
  --n-4:var(--line-2);    /* was #d4d4d4 */
  --n-5:var(--soft);      /* was #a1a1a1 (2.58) -> 3.10. Still never text, and
                             --n-5's own comment already said so. */
  --n-6:var(--slate);     /* was #737373 (4.74) -> 6.77. The brief carries three
                             text tones where the ramp carried four; n-6 and n-7
                             both land on --slate. Deliberate: the distinction
                             between "secondary" and "emphasis" grey was not
                             legible at 4.74 vs 7.81 anyway. */
  --n-7:var(--slate);     /* was #525252 (7.81) -> 6.77. The ONE place the map
                             moves contrast down. 6.77 clears AA for body at any
                             size and AAA for large; accepted and recorded. */
  --n-8:var(--ink);       /* was #404040 -> 18.72 */
  --n-9:var(--ink);       /* was #0a0a0a (19.80) -> 18.72. The dark surface and
                             the ink are one token in the brief, as they were. */

  --accent:var(--link);           /* teal->owner blue->the brief's blue. 6.91 */
  --accent-ink:var(--link-ink);
  --accent-soft:var(--link-soft);
  --accent-line:var(--link-line);
  --accent-on-dark:#7FA3F5;       /* 7.36:1 on --ink. Re-derived from --link
                                     rather than kept at the old #00a6f4, which
                                     belonged to a blue that no longer exists. */

  /* On the dark panel. Alpha values are hue-independent, so these carry over
     unchanged; only the ink beneath them moved. */
  --d-ink:#ffffff;
  --d-ink-2:rgba(255,255,255,.72);
  --d-ink-3:rgba(255,255,255,.55);
  --d-line-strong:rgba(255,255,255,.28);
  --d-line:rgba(255,255,255,.16);
  --d-fill:rgba(255,255,255,.08);
  --veil:rgba(255,255,255,.94);

  /* CHART RAMPS ARE SEALED OFF and deliberately NOT folded into the stage
     palette. A chart that borrows stage hues makes "polishing" and "ferrous"
     the same blue on a page that shows both. The ordinal ramp is re-expressed
     on the new neutrals; the categorical hues are untouched. */
  --o-1:var(--line-2);--o-2:var(--slate);--o-3:var(--slate);--o-4:var(--ink);--o-5:var(--ink);
  --c-ferrous:#2a78d6;
  --c-nonferrous:#eb6834;
  --c-titanium:#1baf7a;
  --c-titanium-ink:#0e7d57;

  /* Legacy type steps, onto the brief's scale. */
  --t1:var(--t-h1);   /* 48 -> 52, hero h1            */
  --t2:36px;          /* RETAINED: inner-page h1. The brief's table describes the
                         homepage; a 52px h1 on a product page is not what it
                         asks for, and 36 is the step that already sat there. */
  --t3:var(--t-h2);   /* 27 -> 32, section h2         */
  --t4:21px;          /* RETAINED: editorial h3       */
  --t5:var(--t-body); /* 17.5 -> 16.5, body           */
  --t6:15px;          /* RETAINED: nav, footer, small body */
  --t7:var(--t-floor-body);  /* 14 -- table cells, the body floor */
  --t8:var(--t-floor-body);  /* 14 -- eyebrows and table headers  */

  --lh1:1.06; --lh2:1.14; --lh3:1.25; --lh4:1.35;
  --lh5:var(--lh-body); --lh6:1.55; --lh7:1.5; --lh8:1.4;

  /* The bottom app bar's height, needed by Slice 4 both to draw the bar and to
     pad the body out from under it. One token so the two cannot disagree --
     which is the whole of assertion 6's "no page content is occluded by it". */
  --appbar-h:60px;
}

/* ============================================================================
   STAGE PLUMBING. One rule per stage, and nothing anywhere else in the theme
   names a stage colour again.

   "Each stage owns a colour, and that colour follows the stage onto every
   surface: the homepage rail, the catalogue index, category headers, product
   breadcrumbs, guide step bars." The way that is kept true with one declaration
   rather than six is that a surface carries data-stage and then paints with
   var(--stage); it never names --cut or --polish. So adding a sixth stage is a
   token and a line here, not a search across the stylesheet.

   --stage      the hue. fills, dots, bars, rails.
   --stage-ink  the same stage, safe to set text in. USE THIS FOR TEXT.
   --stage-on   what may be set ON the hue -- white for four, --ink for mount,
                which is 2.98:1 and can never carry white text.
   ============================================================================ */
[data-stage="cut"]   {--stage:var(--cut);   --stage-ink:var(--cut-ink);   --stage-on:var(--on-cut)}
[data-stage="mount"] {--stage:var(--mount); --stage-ink:var(--mount-ink); --stage-on:var(--on-mount)}
[data-stage="grind"] {--stage:var(--grind); --stage-ink:var(--grind-ink); --stage-on:var(--on-grind)}
[data-stage="polish"]{--stage:var(--polish);--stage-ink:var(--polish-ink);--stage-on:var(--on-polish)}
[data-stage="carry"] {--stage:var(--carry); --stage-ink:var(--carry-ink); --stage-on:var(--on-carry)}

/* The icons. No container tile, no outline, no background -- "icons are the
   objects themselves". They carry the stage colour and nothing else, and they
   are the one place on the page where boldness is spent. */
.p2i{display:block;flex:none}
.p2i-cat{width:26px;height:26px}

/* MOBILE STEPS. The brief gives h1 and h2 two values each; they live here rather
   than in each template so that no template picks a breakpoint size by hand. */
@media (max-width:700px){
  :root{
    --t-h1:29px;
    --t-h2:24px;
  }
}
