/* ============================================================================
   The Design Hub - design tokens
   ----------------------------------------------------------------------------
   Palette derived from the live brand systems of the two accounts this team
   serves. Colours sampled from the public sites on 2026-09-17:

     RR Donnelley (rrd.com)
       navy #002449 (dominant) - azure #009DDB - mid-navy #004677 - teal #69CBD0
     White & Case (whitecase.com)
       --bs-primary #0099CC - black #010101 - dark #28292F
       greys #D8D8D8 #595959 #A9A9A9 #828282 - blue tints #CCEBF5 #99D6EB #66C2E0

   Both brands independently centre on a bright azure of near-identical hue
   (#009DDB vs #0099CC) paired with a very dark neutral. That overlap is the
   spine of this palette: one azure ramp reads as native to both, and RRD's
   navy gives dark mode a base that isn't flat black.

   This is an internal tool's palette, brand-ADJACENT by design. It is not
   either firm's identity and must not be presented as such.

   Four colour roles are kept strictly separate, per PLAN.md:
     1. brand / UI     - chrome, primary actions
     2. status         - workflow state (always paired with a text label)
     3. urgency        - deadline pressure (the team's existing categories)
     4. member accent  - personal identity only (avatars, owner chips)
   Colour is never the sole carrier of meaning; every state also has text.
   ========================================================================== */

:root {
  /* --- Brand azure ramp -------------------------------------------------- */
  --az-50:  #E8F6FC;
  --az-100: #CCEBF5;  /* W&C blue20 */
  --az-200: #99D6EB;  /* W&C blue40 */
  --az-300: #66C2E0;  /* W&C blue60 */
  --az-400: #2BA9D6;
  --az-500: #009BD4;  /* bridge tone between RRD #009DDB and W&C #0099CC */
  --az-600: #007FAE;
  --az-700: #00658C;
  --az-800: #004677;  /* RRD mid-navy */
  --az-900: #002449;  /* RRD navy anchor */

  /* --- Cool neutral ramp (navy-tinted: bridges RRD navy + W&C charcoal) -- */
  --n-0:   #FFFFFF;
  --n-25:  #F7F9FB;
  --n-50:  #F1F4F8;
  --n-100: #E4EAF1;
  --n-200: #DDE3EA;   /* decorative hairline only, not a control boundary */
  --n-300: #C2CCD8;
  --n-400: #96A5B8;
  --n-450: #808FA4;   /* lightest step clearing 3:1 on card AND page (1.4.11) */
  --n-500: #647285;
  --n-600: #47566B;
  --n-700: #2E3C50;
  --n-800: #1B2839;
  --n-850: #122234;
  --n-900: #0C1626;
  --n-950: #060D18;
  --n-ink: #0E1A2B;

  /* --- Semantic surfaces: LIGHT (default) -------------------------------- */
  /* Cooler and a shade deeper than the n-25 step. The workspace has to sit
     BEHIND white dockets and still read as a surface, not as paper itself.
     (Comments here must avoid "token" + colon - design/contrast_check.py
     parses this file with a regex and would read it as a declaration.)      */
  --bg:            #F3F6FC;
  --surface:       var(--n-0);
  --surface-2:     var(--n-50);
  --surface-3:     var(--n-100);
  --surface-inset: #EDF1F6;
  --border:        var(--n-200);
  --border-strong: var(--n-450);  /* control boundaries: 3.29 card / 3.12 page */
  --divider:       #E9EEF4;

  --text:          var(--n-ink);
  --text-2:        var(--n-700);
  /* One step off the n-500 ramp. Muted text sits on all four surfaces, and on
     the two deepest fills the ramp step landed at 4.04 and 4.44 - readable to
     most people, short of AA for everyone. Darkened by the least that clears
     4.5 on the worst of them (raised fill) with the hue held. */
  --text-3:        #3F4E63;
  --text-inverse:  #FFFFFF;

  --accent:        var(--az-600);  /* interactive fills / primary button    */
  --accent-hover:  var(--az-700);
  --accent-text:   var(--az-700);  /* azure used AS text (AA on --surface)  */
  --accent-quiet:  var(--az-50);   /* tinted backgrounds                    */
  --accent-border: var(--az-200);
  --focus-ring:    var(--az-600);

  /* --- Navigation rail: RRD navy in BOTH themes -------------------------- */
  /* The rail is the one piece of chrome that never changes colour. It is the
     product's spine, so it stays navy whether the workspace is light or dark;
     only the two fills darken at night so it doesn't glare on a 2am screen. */
  --rail-bg:          #002449;  /* RRD navy anchor                          */
  --rail-bg-2:        #00305F;  /* hover / active row fill                  */
  --rail-text:        #C9D8E8;  /* 10.4:1 on --rail-bg                      */
  --rail-text-strong: #FFFFFF;
  --rail-muted:       #8FA9C4;  /* 5.3:1 on --rail-bg - group headings      */
  --rail-border:      rgba(255, 255, 255, .10);
  --rail-accent:      #009DDB;  /* active marker bar only, never as text    */

  /* --- Current-job slab (the one thing "on the desk") -------------------- */
  --slab-bg:     #002449;
  --slab-bg-2:   #003062;  /* inset areas inside the slab                   */
  --slab-edge:   #009DDB;  /* the azure leading edge                        */
  --slab-text:   #FFFFFF;
  --slab-text-2: #B9CCE0;  /* 8.3:1 on --slab-bg                            */
  --slab-rule:   rgba(255, 255, 255, .14);

  /* --- Workflow status (PLAN.md "Workflow rules") ------------------------ */
  --st-queued-fg:    #41506A;  --st-queued-bg:    #EDF0F5;  --st-queued-bd:    #D3DAE5;
  --st-progress-fg:  #00618A;  --st-progress-bg:  #E2F3FB;  --st-progress-bd:  #A8D8EC;
  --st-progress-solid-ink: #FFFFFF;   /* text on a pill FILLED with the fg */
  --st-paused-fg:    #8A5300;  --st-paused-bg:    #FDF2DF;  --st-paused-bd:    #F0D4A0;
  --st-hold-fg:      #58399E;  --st-hold-bg:      #F0EBFB;  --st-hold-bd:      #D6C9F2;
  --st-clarify-fg:   #9C2C5E;  --st-clarify-bg:   #FCEAF2;  --st-clarify-bd:   #F1C3D8;
  --st-handover-fg:  #7A4A12;  --st-handover-bg:  #F8EEDF;  --st-handover-bd:  #E6CFA8;
  --st-proofing-fg:  #0A6E73;  --st-proofing-bg:  #E0F4F4;  --st-proofing-bd:  #A6DBDD;
  --st-completed-fg: #15683F;  --st-completed-bg: #E4F4EA;  --st-completed-bd: #A9DCBE;
  --st-cancelled-fg: #5C6878;  --st-cancelled-bg: #F2F4F7;  --st-cancelled-bd: #DCE1E8;

  /* --- Urgency (the deadline categories the team already works to) ------- */
  --ur-urgent-fg:   #A81E14;  --ur-urgent-bg:   #FDECEA;  --ur-urgent-bd:   #F3BDB7;
  --ur-today-fg:    #9B4B06;  --ur-today-bg:    #FDEFE3;  --ur-today-bd:    #F4CBA6;
  --ur-tomorrow-fg: #7A5A08;  --ur-tomorrow-bg: #FAF3DD;  --ur-tomorrow-bd: #E8D69B;
  --ur-nextweek-fg: #1F6A8C;  --ur-nextweek-bg: #E6F2F8;  --ur-nextweek-bd: #B3D6E6;
  --ur-unknown-fg:  #5C6878;  --ur-unknown-bg:  #F2F4F7;  --ur-unknown-bd:  #DCE1E8;

  /* --- Calendar year heatmap --------------------------------------------- */
  /* Three completion densities. These were mixed from the completed status
     pair at render time, which meant no checker could resolve them and nobody
     noticed the busiest day printed its number at 2.52 in light and 3.72 in
     dark. Written out per theme instead, so design/contrast_check.py reads
     them like any other pairing.

     Level 3 inverts on purpose: it is the one that carries a filled accent,
     and the fill runs dark in light mode and bright in dark mode, so the text
     on it has to run the other way in each. */
  --heat-1-bg: #E4F4EA;  --heat-1-fg: #15683F;
  --heat-2-bg: #C8E2D4;  --heat-2-fg: #15683F;
  --heat-3-bg: #15683F;  --heat-3-fg: #FFFFFF;

  /* --- Feedback ---------------------------------------------------------- */
  --ok-fg:   #15683F;  --ok-bg:   #E4F4EA;
  --warn-fg: #8A5300;  --warn-bg: #FDF2DF;
  --err-fg:  #A81E14;  --err-bg:  #FDECEA;
  --info-fg: #00618A;  --info-bg: #E2F3FB;

  /* --- Member accents ---------------------------------------------------- */
  /* Seven hues spread round the wheel at matched chroma so they read as one
     family. Deliberately offset from the status hues above, and used only for
     identity (avatar, owner chip) - never for state.                       */
  --m-1: #1F5FA8;  /* indigo-blue  */
  --m-2: #0F6E62;  /* teal-green   */
  --m-3: #A04B14;  /* rust         */
  --m-4: #6A3C9E;  /* purple       */
  --m-5: #A62E3C;  /* crimson      */
  --m-6: #4C6E1C;  /* olive        */
  --m-7: #973271;  /* magenta      */
  --m-1-quiet: #EAF1F9;
  --m-2-quiet: #E3F3F1;
  --m-3-quiet: #FAEDE4;
  --m-4-quiet: #F1EBF9;
  --m-5-quiet: #FAEAEC;
  --m-6-quiet: #EEF4E4;
  --m-7-quiet: #F9EAF3;
  --avatar-fg: #FFFFFF;

  /* --- Elevation --------------------------------------------------------- */
  --shadow-sm:    0 1px 2px rgba(14, 26, 43, .06), 0 1px 1px rgba(14, 26, 43, .04);
  --shadow-md:    0 2px 4px rgba(14, 26, 43, .06), 0 4px 12px rgba(14, 26, 43, .08);
  --shadow-lg:    0 8px 24px rgba(14, 26, 43, .12), 0 2px 6px rgba(14, 26, 43, .06);
  --shadow-panel: -8px 0 24px rgba(14, 26, 43, .10);

  /* --- Type -------------------------------------------------------------- */
  /* IBM Plex, self-hosted from assets/fonts (see assets/css/fonts.css and
     assets/SOURCES.md). Open source, so it ships with the repo - no CDN, no
     build step. The system stack stays behind it as the fallback, so the app
     is still readable if the woff2 files fail to load.                      */
  --font-sans: "IBM Plex Sans", "Segoe UI", -apple-system, BlinkMacSystemFont,
               "Helvetica Neue", Arial, sans-serif;
  /* Mono is for identifiers, timers, durations and clock times ONLY.        */
  --font-mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas,
               "SF Mono", Menlo, monospace;
  --fs-xs:   .75rem;    /* 12px - the floor; nothing readable goes below it  */
  --fs-sm:   .8125rem;  /* 13px */
  --fs-base: .875rem;   /* 14px */
  --fs-md:   1rem;      /* 16px */
  --fs-lg:   1.125rem;  /* 18px - section h2                                 */
  --fs-xl:   1.25rem;   /* 20px */
  --fs-2xl:  1.75rem;   /* 28px - page h1                                    */
  --fs-3xl:  2.5rem;    /* 40px - the shift timer, and nothing else          */
  --lh-tight:  1.25;
  --lh-normal: 1.5;

  /* --- Geometry / motion ------------------------------------------------- */
  --r-sm: 4px;  --r-md: 6px;  --r-lg: 10px;  --r-pill: 999px;
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px;
  /* fast = hover and press. base = an in-place state change.
     panel = something arriving from off-screen (the detail panel).          */
  --t-fast: 120ms; --t-base: 180ms; --t-panel: 220ms;
  --ease: cubic-bezier(.4, 0, .2, 1);

  color-scheme: light;
}

/* ============================================================================
   DARK MODE
   Surfaces sit in RRD's navy family rather than neutral black: it keeps the
   brand relationship legible at night and stops large dark areas looking dead.
   Matters here - this team works overnight shifts.
   ========================================================================== */

:root[data-theme="dark"] {
  --bg:            var(--n-950);
  --surface:       var(--n-900);
  --surface-2:     var(--n-850);
  --surface-3:     #17293D;
  --surface-inset: #0A1322;
  --border:        #1E3247;
  --border-strong: #4A6B88;  /* control boundaries: 3.24 card / 3.48 page */
  --divider:       #17293C;

  --text:          #E8EFF6;
  --text-2:        #C4D1DF;
  /* Lifted a shade: on the raised fill this sat at 4.29, just under AA. */
  --text-3:        #A4B4C6;
  --text-inverse:  #071120;

  --accent:        var(--az-500);
  --accent-hover:  var(--az-400);
  --accent-text:   var(--az-300);
  --accent-quiet:  #0B2438;
  --accent-border: #1C4D6F;
  --focus-ring:    var(--az-300);

  /* The rail stays navy at night, just deeper: only the two fills move. */
  --rail-bg:   #061427;
  --rail-bg-2: #0C2138;
  --slab-bg:   #0A1E36;
  --slab-bg-2: #0F2A49;

  --st-queued-fg:    #B3C0D2;  --st-queued-bg:    #162435;  --st-queued-bd:    #2B3D52;
  --st-progress-fg:  #7FCDEA;  --st-progress-bg:  #0A2436;  --st-progress-bd:  #1B4F6E;
  --st-progress-solid-ink: #071120;
  --st-paused-fg:    #E8B765;  --st-paused-bg:    #2A1F0C;  --st-paused-bd:    #5A4415;
  --st-hold-fg:      #BFA8EE;  --st-hold-bg:      #1E1735;  --st-hold-bd:      #3D2F63;
  --st-clarify-fg:   #F2A3C6;  --st-clarify-bg:   #33142A;  --st-clarify-bd:   #5E2748;
  --st-handover-fg:  #E5BE85;  --st-handover-bg:  #2C2012;  --st-handover-bd:  #57401F;
  --st-proofing-fg:  #6FCBCF;  --st-proofing-bg:  #0A2628;  --st-proofing-bd:  #174C50;
  --st-completed-fg: #6ECF9B;  --st-completed-bg: #0C2519;  --st-completed-bd: #1C5134;
  --st-cancelled-fg: #8A98AA;  --st-cancelled-bg: #141F2D;  --st-cancelled-bd: #26364A;

  --ur-urgent-fg:   #FF9A8F;  --ur-urgent-bg:   #2E1210;  --ur-urgent-bd:   #5E2620;
  --ur-today-fg:    #F2A968;  --ur-today-bg:    #2B1A0B;  --ur-today-bd:    #573416;
  --ur-tomorrow-fg: #DCC067;  --ur-tomorrow-bg: #26200A;  --ur-tomorrow-bd: #4D4116;
  --ur-nextweek-fg: #7FC0DE;  --ur-nextweek-bg: #0B2331;  --ur-nextweek-bd: #1A475F;
  --ur-unknown-fg:  #8A98AA;  --ur-unknown-bg:  #141F2D;  --ur-unknown-bd:  #26364A;

  /* Heatmap, dark. Level 3 is the bright fill here, so its text goes dark. */
  --heat-1-bg: #0C2519;  --heat-1-fg: #6ECF9B;
  --heat-2-bg: #24503A;  --heat-2-fg: #6ECF9B;
  --heat-3-bg: #6ECF9B;  --heat-3-fg: #071120;

  --ok-fg:   #6ECF9B;  --ok-bg:   #0C2519;
  --warn-fg: #E8B765;  --warn-bg: #2A1F0C;
  --err-fg:  #FF9A8F;  --err-bg:  #2E1210;
  --info-fg: #7FCDEA;  --info-bg: #0A2436;

  /* Member accents lifted for dark surfaces, same hue order as light mode. */
  --m-1: #7CB2E8;  --m-2: #4FC4B2;  --m-3: #E2914F;
  --m-4: #B091DE;  --m-5: #E88A95;  --m-6: #A3C563;
  --m-7: #DE85B8;
  --m-1-quiet: #11263A;
  --m-2-quiet: #0B2A26;
  --m-3-quiet: #2A1B0D;
  --m-4-quiet: #1F1733;
  --m-5-quiet: #2C1418;
  --m-6-quiet: #1C2711;
  --m-7-quiet: #2A1322;
  --avatar-fg: #071120;

  --shadow-sm:    0 1px 2px rgba(0, 0, 0, .40);
  --shadow-md:    0 2px 4px rgba(0, 0, 0, .40), 0 4px 12px rgba(0, 0, 0, .34);
  --shadow-lg:    0 8px 24px rgba(0, 0, 0, .50), 0 2px 6px rgba(0, 0, 0, .34);
  --shadow-panel: -8px 0 24px rgba(0, 0, 0, .44);

  color-scheme: dark;
}

/* Follow the OS when the user has not chosen explicitly. The :not() guard
   keeps an explicit light choice winning over a dark OS preference. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            var(--n-950);
    --surface:       var(--n-900);
    --surface-2:     var(--n-850);
    --surface-3:     #17293D;
    --surface-inset: #0A1322;
    --border:        #1E3247;
    --border-strong: #4A6B88;  /* control boundaries: 3.24 card / 3.48 page */
    --divider:       #17293C;

    --text:          #E8EFF6;
    --text-2:        #C4D1DF;
    /* Lifted a shade: on the raised fill this sat at 4.29, just under AA. */
    --text-3:        #A4B4C6;
    --text-inverse:  #071120;

    --accent:        var(--az-500);
    --accent-hover:  var(--az-400);
    --accent-text:   var(--az-300);
    --accent-quiet:  #0B2438;
    --accent-border: #1C4D6F;
    --focus-ring:    var(--az-300);

    /* The rail stays navy at night, just deeper: only the two fills move. */
    --rail-bg:   #061427;
    --rail-bg-2: #0C2138;
    --slab-bg:   #0A1E36;
    --slab-bg-2: #0F2A49;

    --st-queued-fg:    #B3C0D2;  --st-queued-bg:    #162435;  --st-queued-bd:    #2B3D52;
    --st-progress-fg:  #7FCDEA;  --st-progress-bg:  #0A2436;  --st-progress-bd:  #1B4F6E;
  --st-progress-solid-ink: #071120;
    --st-paused-fg:    #E8B765;  --st-paused-bg:    #2A1F0C;  --st-paused-bd:    #5A4415;
    --st-hold-fg:      #BFA8EE;  --st-hold-bg:      #1E1735;  --st-hold-bd:      #3D2F63;
    --st-clarify-fg:   #F2A3C6;  --st-clarify-bg:   #33142A;  --st-clarify-bd:   #5E2748;
    --st-handover-fg:  #E5BE85;  --st-handover-bg:  #2C2012;  --st-handover-bd:  #57401F;
    --st-proofing-fg:  #6FCBCF;  --st-proofing-bg:  #0A2628;  --st-proofing-bd:  #174C50;
    --st-completed-fg: #6ECF9B;  --st-completed-bg: #0C2519;  --st-completed-bd: #1C5134;
    --st-cancelled-fg: #8A98AA;  --st-cancelled-bg: #141F2D;  --st-cancelled-bd: #26364A;

    --ur-urgent-fg:   #FF9A8F;  --ur-urgent-bg:   #2E1210;  --ur-urgent-bd:   #5E2620;
    --ur-today-fg:    #F2A968;  --ur-today-bg:    #2B1A0B;  --ur-today-bd:    #573416;
    --ur-tomorrow-fg: #DCC067;  --ur-tomorrow-bg: #26200A;  --ur-tomorrow-bd: #4D4116;
    --ur-nextweek-fg: #7FC0DE;  --ur-nextweek-bg: #0B2331;  --ur-nextweek-bd: #1A475F;
    --ur-unknown-fg:  #8A98AA;  --ur-unknown-bg:  #141F2D;  --ur-unknown-bd:  #26364A;

    /* Heatmap, dark. Level 3 is the bright fill here, so its text goes dark. */
    --heat-1-bg: #0C2519;  --heat-1-fg: #6ECF9B;
    --heat-2-bg: #24503A;  --heat-2-fg: #6ECF9B;
    --heat-3-bg: #6ECF9B;  --heat-3-fg: #071120;

    --ok-fg:   #6ECF9B;  --ok-bg:   #0C2519;
    --warn-fg: #E8B765;  --warn-bg: #2A1F0C;
    --err-fg:  #FF9A8F;  --err-bg:  #2E1210;
    --info-fg: #7FCDEA;  --info-bg: #0A2436;

    --m-1: #7CB2E8;  --m-2: #4FC4B2;  --m-3: #E2914F;
  --m-4: #B091DE;  --m-5: #E88A95;  --m-6: #A3C563;
  --m-7: #DE85B8;
  --m-1-quiet: #11263A;
  --m-2-quiet: #0B2A26;
  --m-3-quiet: #2A1B0D;
  --m-4-quiet: #1F1733;
  --m-5-quiet: #2C1418;
  --m-6-quiet: #1C2711;
  --m-7-quiet: #2A1322;
  --avatar-fg: #071120;

    --shadow-sm:    0 1px 2px rgba(0, 0, 0, .40);
    --shadow-md:    0 2px 4px rgba(0, 0, 0, .40), 0 4px 12px rgba(0, 0, 0, .34);
    --shadow-lg:    0 8px 24px rgba(0, 0, 0, .50), 0 2px 6px rgba(0, 0, 0, .34);
    --shadow-panel: -8px 0 24px rgba(0, 0, 0, .44);

    color-scheme: dark;
  }
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  -webkit-font-smoothing: antialiased;
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

@media (prefers-reduced-motion: reduce) {
  /* A .01ms duration on a LOOPING animation does not stop it - it strobes at
     the frame rate, which is exactly what someone asking for reduced motion
     is trying to avoid. So: one-shot animations and transitions collapse to
     nothing, and anything set to repeat is switched off outright. The `.beat`
     dot then simply sits there as a static dot, which is all it has to be. */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
  .beat,
  [class*="pulse"],
  [data-loop] {
    animation: none !important;
  }
}
