/* citywire — token source (SITE CHROME — Citywire's public web brand)
 *
 * A concept build for the Citywire Digital & Email Production Coordinator role. This
 * pack carries Citywire's REAL brand tokens, read on 2026-09-07 from citywire.com's
 * own stylesheets (`css/themes/default.css`, `css/themes/ftf.css`,
 * `css/sponsored-native.css`, `css/output.min.css`) and recorded with occurrence
 * counts in _factory/kb/companies/citywire/research-design.md. The factory's
 * "adjacent-but-distinct" rule is deliberately OVERRIDDEN here (DESIGN.md B1/B2): a
 * sponsored email that does not wear Citywire's own frame proves nothing. The
 * override, the Proxima Nova -> Red Hat Display substitution and the unaffiliated
 * disclaimer are stated in DESIGN.md. Not affiliated with or endorsed by Citywire.
 *
 * Load order on every page: system/tokens.contract.css -> THIS FILE ->
 * system/components.css -> system/portfolio.css. Components reference the SEMANTIC
 * tokens below, never a primitive, never a literal.
 *
 * WHY CYAN IS NEVER BOUND TO A TEXT ROLE. On citywire.com, 56% of the cyan text
 * renders on white or light grounds at 2.24 to 2.36:1: the 10px category tags, the
 * nav chip and both button styles. That fails WCAG AA at every size. This pack fixes
 * it from Citywire's own scale rather than inventing a colour: text and button fills
 * take #0D6180 (`--site-primary-700`, 6.91:1 with white), and the cyan #01B6EB
 * carries rules, large marks and text on the dark band (7.56:1 on #0F172A) only.
 * That is rule B6: the brand hex stays as the primitive, the tuned variant ships for
 * the text role, both marked with the computed ratio.
 *
 * Every ratio below is computed by script (WCAG 2.1 relative luminance), never typed
 * from memory, and color-mix values are composited over their real ground before
 * measuring. Every shipped text pair clears AA.
 *
 * Fonts: citywire.com runs Red Hat Text and Red Hat Display, both Open Font Licence,
 * so both ship here as the real faces (fonts/fonts.css). Proxima Nova, Citywire's
 * corporate face, is licensed and is not shipped; Red Hat Display stands in for it.
 */

/* Self-hosted faces (bundled woff2). @import must precede all rules. */
@import url("../fonts/fonts.css");

:root {
  /* ============================================================
     1. PRIMITIVES — Citywire's web palette
     (research-design.md; OBSERVED unless marked DERIVED)
     ============================================================ */

  /* Primary ramp — verbatim from citywire.com/css/themes/default.css,
     `--site-primary-50` … `--site-primary-900`, converted from its rgb triplets. */
  --color-cyan-50:  #E5F6FC;   /* pale tint band — ink on it 16.08:1 */
  --color-cyan-100: #B2E4F7;   /* content on the dark band — 13.04:1 on #0F172A */
  --color-cyan-200: #7FD2F2;
  --color-cyan-300: #4BC0ED;   /* primary-300 and primary-400 carry the same value */
  --color-cyan-500: #01B6EB;   /* Citywire primary cyan — 561 class uses. RULE / LARGE
                                  MARK / FILL only: 2.36:1 on white fails all text.
                                  As text on the dark band 7.56:1; ink on it 7.56:1 */
  --color-cyan-600: #1287B4;   /* their observed link hover, 267 uses. 4.08:1 on white,
                                  which is large-text only, so the chrome hover is one
                                  step darker (see --color-accent-hover) */
  --color-cyan-700: #0D6180;   /* the accessible cyan-family text colour — 6.91:1 on white */
  --color-cyan-800: #083A4D;   /* 12.19:1 on white; also their <meta theme-color> */
  --color-cyan-900: #052A38;   /* Citywire's dark teal — white on it 15.06:1. Carries
                                  the pressed accent, the email masthead and the favicon */

  /* Slate neutrals. #0F172A and #64748B are literal in citywire.com's
     sponsored-native.css; #475569, #CBD5E1 and #F1F5F9 are Tailwind slate, the scale
     citywire.com's `cw-` build remaps `neutral` onto (research-design §2.6). */
  --color-ink:        #0F172A;   /* slate-900 — headings, and the dark surface itself
                                    (190 class uses). 17.85:1 on white */
  --color-ink-body:   #475569;   /* Tailwind slate-600 — 557 class uses, the most-used
                                    colour class on the site. 7.58:1 on white */
  --color-ink-muted:  #64748B;   /* slate-500 — the sponsored-native disclosure line,
                                    260 class uses. 4.76:1 on white, so it is AA at any
                                    size but has no headroom: captions only */
  --color-paper:      #ffffff;   /* page ground */
  --color-surface:    #F1F5F9;   /* Tailwind slate-100 as used by their build — the
                                    measured page band (nav chip fill, mobile drawer,
                                    20 uses). 1.10:1 vs white: a whisper. Ink on it 16.30:1 */
  --color-hairline:   #CBD5E1;   /* Tailwind slate-300 — the site's separator of record,
                                    407 uses (241 divide + 166 border). 1.48:1 vs white:
                                    a rule, never a boundary that carries meaning alone */

  /* Coral — the paid-content fence. Verbatim stroke colour of
     citywire.com/images/random/sponsor-border.svg, the wavy rule that fences off
     sponsored content top and bottom. */
  --color-coral:      #f58674;   /* RULE AND MARK ONLY — 2.46:1 on white, fails all text */
  --color-coral-text: #B06054;   /* DERIVED: R, G and B scaled by 0.72 until AA. 4.52:1
                                    on white. Multiplicative, so the channel ratio and
                                    the muted coral character survive; an HLS darken
                                    lands on #E32E10, a vivid red indistinguishable
                                    from the error colour below */

  /* Fix The Future edition orange — citywire.com/css/themes/ftf.css swaps the whole
     primary ramp to orange for that edition, which is the proof that a Citywire theme
     is a per-edition colour override on one shared component library. Recorded as a
     primitive; nothing in the semantic map binds to it. */
  --color-ftf: #F9A525;   /* ftf primary-500. FILL with dark text: ink on it 8.87:1.
                             2.01:1 on white, so never a text colour, never a hairline */

  /* Citywire's own role-named semantic tokens (their vocabulary, read from their
     Tailwind build: .cw-text-error-500/-600, .cw-text-success-500, .cw-bg-warning-300/-600). */
  --color-error:        #DC2626;   /* error-600 — 4.83:1 on white, AA as text */
  --color-error-mark:   #EF4444;   /* error-500 — 3.76:1 on white: large text and marks only */
  --color-success:      #10b981;   /* success-500 — 2.54:1 on white: MARK / FILL only */
  --color-success-text: #0C875E;   /* DERIVED: R, G and B scaled by 0.732 until AA.
                                      4.52:1 on white. The text-bearing green */
  --color-warning:      #d97706;   /* warning-600 — 3.19:1 on white: large text and marks only */
  --color-warning-text: #B36205;   /* DERIVED: R, G and B scaled by 0.827 until AA.
                                      4.50:1 on white. The text-bearing amber */
  --color-warning-fill: #FCD34D;   /* warning-300 — a FILL: ink on it 12.38:1,
                                      1.44:1 on white so never a text colour */

  /* Fonts — self-hosted Red Hat Text and Red Hat Display, Citywire's real web faces.
     Red Hat Display also stands in for Proxima Nova, which is licensed and not
     shipped (substitution flagged in fonts/fonts.css and DESIGN.md B2). */
  --font-display: "Red Hat Display", Helvetica, Arial, sans-serif;
  --font-body:    "Red Hat Text", Helvetica, Arial, sans-serif;

  /* Spacing scale (8 steps, 4px base — unchanged) */
  --spacing-xs:  4px;
  --spacing-sm:  8px;
  --spacing-md:  16px;
  --spacing-lg:  24px;
  --spacing-xl:  32px;
  --spacing-2xl: 48px;
  --spacing-3xl: 64px;
  --spacing-4xl: 96px;

  /* Radius — measured class counts on citywire.com run 4 / 6 / 8 / 12 / 16:
     cw-rounded 32 and cw-rounded-md 65 at the small end, cw-rounded-xl 53 on both
     button styles, cw-rounded-2xl 185 on cards. Citywire is a rounder brand than the
     chassis default: small 6px, buttons 12px, cards 16px. */
  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 16px;

  /* Shadows — Citywire separates with hairlines, not shadows (407 divide/border uses
     against a handful of shadow declarations), so shadows stay quiet: ink-tinted, low
     alpha, hover lift and overlay surfaces only. */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 4px 6px rgba(15, 23, 42, 0.08);
  --shadow-lg: 0 10px 15px rgba(15, 23, 42, 0.10);

  /* Layout — measured: the main column caps at 1400px (2xl:cw-max-w-[1400px]),
     the nav at 1335px. 1400px is the shell of record. */
  --maxw:   1400px;
  --gutter: 24px;

  /* Type ramp — generic modular scale (unchanged). The EMAIL type scale is resolved
     for inline compilation in tokens.json -> "email", not here. */
  --type-display: clamp(40px, 6vw, 76px);
  --type-h1:      clamp(32px, 4vw, 56px);
  --type-h2:      clamp(24px, 2.5vw, 34px);
  --type-h3:      20px;
  --type-lead:    clamp(18px, 1.5vw, 22px);
  --type-body:    16px;
  --type-caption: 13px;
  --type-eyebrow: 12px;

  /* ============================================================
     2. SEMANTIC MAP — the contract, bound to the Citywire palette.
     ============================================================ */

  /* Foreground / surface (light context) */
  --color-fg:            var(--color-ink);        /* #0F172A — 17.85:1 on white — AA */
  --color-fg-muted:      var(--color-ink-body);   /* #475569 — 7.58:1 on white — AA */
  --color-bg:            var(--color-paper);
  --color-bg-surface:    var(--color-paper);      /* white cards; #F1F5F9 is a page-level
                                                     band, so it stays a primitive */
  --color-border:        var(--color-hairline);   /* 1.48:1 — a rule, not a boundary */
  --color-border-strong: var(--color-ink);        /* 17.85:1 — the boundary that carries state */

  /* Accent — the accessible end of Citywire's own ramp. Their OBSERVED hover is
     #1287B4 (267 uses, every one a hover on a headline link), but that is 4.08:1 on
     white and fails AA for normal text, so the chrome hover ships one step darker
     and the observed value stays as the primitive (B6). */
  --color-accent:           var(--color-cyan-700);   /* #0D6180 — 6.91:1 on white for links/CTA text */
  --color-accent-hover:     var(--color-cyan-800);   /* #083A4D — 12.19:1 on white */
  --color-accent-active:    var(--color-cyan-900);   /* #052A38 — 15.06:1 on white */
  --color-accent-fg:        var(--color-paper);      /* white on #0D6180 6.91:1 — AA */
  --color-accent-secondary: var(--color-ink-body);   /* #475569 — 7.58:1 on white */

  /* Brand — the cyan itself, declared in the contract per S3. STRUCTURE, not text on
     white: rules, large marks, and cyan text on the dark band. */
  --color-brand: var(--color-cyan-500);   /* #01B6EB — as text on #0F172A 7.56:1 (AA);
                                             ink on a cyan fill 7.56:1 (AA);
                                             2.36:1 on white, so decorative there */

  /* Extended roles (declared in the contract per S3) */
  --color-loyalty:      var(--color-cyan-100);     /* Citywire runs no loyalty programme, so
                                                      the email layer's status-chip role takes
                                                      the pale cyan FILL: ink on it 13.04:1 */
  --color-urgent:       var(--color-error);        /* #DC2626, their own error-600 — 4.83:1 */
  --color-sponsor:      var(--color-coral);        /* the fence rule and mark — 2.46:1, non-text */
  --color-sponsor-text: var(--color-coral-text);   /* the same role in words — 4.52:1 on white */
  --color-confirm-text: var(--color-success-text);  /* #0C875E, 4.52:1 on white (DERIVED above) */
  --color-caution-text: var(--color-warning-text);  /* #B36205, 4.50:1 on white (DERIVED above) */

  /* Inverse (content on the dark surface — the Citywire chrome). #0F172A is their own
     dark surface: the pre-header band and the glass cards, 190 class uses. */
  --color-bg-inverse:           var(--color-ink);        /* #0F172A */
  --color-fg-on-inverse:        var(--color-cyan-100);   /* #B2E4F7 — 13.04:1 on #0F172A — AA */
  --color-fg-on-inverse-strong: var(--color-paper);      /* white — 17.85:1 on #0F172A */
  /* muted carries small de-emphasised labels on the dark surface (section labels,
     meta, the wordmark tag), so it is calibrated UP from the neutral 50% (which
     composites to #607E90 = 4.15:1 and fails) to 58% cyan-100 over #0F172A =
     #6E8EA1 = 5.14:1, clearing AA for small text. soft (82%) = #95BFD2 = 9.06:1. */
  --color-fg-on-inverse-muted:  color-mix(in srgb, var(--color-fg-on-inverse) 58%, transparent);
  --color-fg-on-inverse-soft:   color-mix(in srgb, var(--color-fg-on-inverse) 82%, transparent);
  --color-inverse-line:         color-mix(in srgb, var(--color-fg-on-inverse) 12%, transparent);
  --color-inverse-wash:         color-mix(in srgb, var(--color-fg-on-inverse) 6%,  transparent);
  --color-on-dark-border:       color-mix(in srgb, var(--color-white) 50%, transparent);
  /* on-dark-border composites to #878B94 = 5.23:1 on #0F172A, clearing 1.4.11 for a
     control boundary. inverse-line (#233043) and inverse-wash (#192336) are washes at
     1.34:1 and 1.13:1 and never carry meaning on their own. */
}
