/* ====================================================================
   tokens.css - FARTBURN design tokens.

   The vocabulary every other stylesheet in this site is written in. It
   defines names; it styles nothing. Loaded FIRST on all three layouts
   (dashboard, landing, print) so the four stylesheets finally share one
   set of words.

   Two rules for anyone extending this file:

     1. Ink tokens (--c-ink*) are for `color:`. Line and surface tokens
        (--c-line*, --c-surface*) are for borders and fills and must
        NEVER appear in a `color:` declaration -- that is exactly how the
        grey ramp drifted below AA in the first place. Every --c-ink step
        is >= 4.5:1 on --c-bg; --c-line-3 is 1.4:1.
     2. THIS IS NO LONGER ONLY A NAMING PASS. It was, up to the depth
        wave; the depth wave added a whole palette layer (see THE DEPTH
        SYSTEM below) and re-pointed the ground, the ink ramp, the line
        ramp and the brand red at it. Every legacy name still resolves
        and every legacy name still measures at or above the contrast it
        promised -- that is the constraint the new layer had to satisfy,
        and it is the constraint the NEXT change has to satisfy too. If
        you add a colour, add it to the depth block with the job it does
        written next to it, and check it against --void.
     3. Only four things carry a hue with meaning: --chrome, --phosphor,
        --classify and --threat. Before inventing a fifth, read the four
        rules at the top of public/css/depth.css. There is almost
        certainly not a fifth.

   Ordering note: this file is linked BEFORE app.css / landing.css /
   print.css. Those files may still carry a :root block of their own, and
   because they load later theirs wins on any name defined twice. That is
   deliberate in exactly one place -- landing.css keeps its translucent
   --c-panel -- and is documented there.
   ==================================================================== */

:root {

  /* ------------------------------------------------------------------
     TYPEFACES

     --font-heading was referenced 21 times across 11 view files and
     defined NOWHERE. An undefined custom property with no fallback is
     invalid at computed-value time, and font-family inherits, so all 21
     elements were inheriting Courier Prime from body -- recipe step
     numbers, the ingredient table header, admin stat figures, forum
     titles, trip titles, search result titles and message sender names
     were all rendering in the monospace body face. It is an alias for
     the UI face here (all 21 call sites are display/UI text, none of
     them want the glitch face).

     --font-head is the OTHER legacy name, used by .nav-brand. Both
     legacy names survive as aliases so not one existing declaration in
     app.css or the views has to change for this file to land.

     Fallback stacks are new. There were none: the Google Fonts request
     is render-blocking and any failure dropped the whole site to the
     browser default.
     ------------------------------------------------------------------ */
  --font-display: 'Rubik Glitch', cursive;
  --font-ui:      'Bebas Neue', 'Arial Narrow', sans-serif;
  --font-mono:    'Courier Prime', ui-monospace, 'Courier New', monospace;
  --font-head:    var(--font-display);   /* legacy alias - .nav-brand    */
  --font-heading: var(--font-ui);        /* THE FIX - 21 call sites      */

  /* ==================================================================
     THE DEPTH SYSTEM
     ==================================================================

     Added by ST-1. Everything above this block is the vocabulary the
     site was already written in; everything in this block is the layer
     the depth pass added, and the two are welded together immediately
     below (the ink, line, surface and ground ramps now RESOLVE to these
     names, so no existing declaration had to change to move the whole
     site onto the new ground).

     The reference implementation is docs/design/direction.html. It is a
     working page, not a description. Read it before changing a number
     here, and read the four rules at the top of depth.css before adding
     one.

     ------------------------------------------------------------------
     GROUND - blue-black, never pure black.

     Pure black kills glow: a bloom laid over #000 has nowhere to go but
     up, so it reads as a grey smear rather than as light. #06070C has
     just enough blue in it that a phosphor or a classification glow sits
     IN the surface instead of on top of it. This is the single change
     with the widest reach on the site -- --c-bg resolves here, and every
     sheet in public/css paints its page with --c-bg.
     ------------------------------------------------------------------ */
  --void: #06070C;   /* the room                                        */
  --deep: #0A0C14;   /* the floor of a container sitting in the room    */

  /* ------------------------------------------------------------------
     GLASS PANES - three levels, brightening as they rise toward the
     light. These are TRANSLUCENT on purpose: a pane is a sheet of glass
     over the ground and the bloom behind it, not a grey rectangle.

     They are only half of an elevation. See --edge-*, --gloss-*,
     --blur-* and --shadow-* below: depth is four properties moving
     together and depth.css never moves one of them alone.
     ------------------------------------------------------------------ */
  --pane-1: rgba(146, 180, 255, 0.035);
  --pane-2: rgba(146, 180, 255, 0.055);
  --pane-3: rgba(146, 180, 255, 0.085);

  /* Opaque stand-ins for the same three levels, for the surfaces that
     must NOT be glass -- long lists, table rows, anything repeated a
     hundred times. Composited over --void they land on the same
     luminance as the translucent pair, so a flat row and a glass card
     read as the same material. */
  --pane-1-solid: #0B0D16;
  --pane-2-solid: #0E111C;
  --pane-3-solid: #131725;

  /* ------------------------------------------------------------------
     EDGES - the light is ABOVE AND BEHIND. Always.

     A raised surface catches light on its TOP edge and falls into
     shadow on its bottom edge. --edge-e1/2/3 are the top-edge border
     colours for the three elevations; --edge-dim is every other edge on
     every elevation. --edge-lit is the reference's name for the
     brightest of them and is kept as an alias so markup copied out of
     direction.html works unaltered.
     ------------------------------------------------------------------ */
  --edge-dim: rgba(120, 150, 200, 0.09);
  --edge-e1:  rgba(190, 215, 255, 0.14);
  --edge-e2:  rgba(190, 215, 255, 0.20);
  --edge-e3:  rgba(190, 215, 255, 0.28);
  --edge-lit: var(--edge-e3);

  /* The specular line ON the top edge - an inset 1px highlight, which is
     the difference between a surface with a thickness and a coloured
     rectangle. Brightens with elevation, like the border does. */
  --gloss-e1: rgba(255, 255, 255, 0.07);
  --gloss-e2: rgba(255, 255, 255, 0.10);
  --gloss-e3: rgba(255, 255, 255, 0.14);

  /* Backdrop blur, the fourth property. It costs GPU and it compounds -
     see rule 4 in depth.css. */
  --blur-e1: 10px;
  --blur-e2: 14px;
  --blur-e3: 20px;

  /* The cast shadow. Large, soft, offset DOWNWARD and pulled in by a
     negative spread so it stays under the object instead of haloing it.
     The hairline `0 0 0 1px` at the end is what stops a pale pane
     dissolving into a pale backdrop. */
  --shadow-e1: 0 18px 44px -18px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(0, 0, 0, 0.35);
  --shadow-e2: 0 30px 70px -24px rgba(0, 0, 0, 0.90), 0 0 0 1px rgba(0, 0, 0, 0.40);
  --shadow-e3: 0 46px 100px -30px rgba(0, 0, 0, 0.95), 0 0 0 1px rgba(0, 0, 0, 0.45);

  /* ------------------------------------------------------------------
     THE FOUR SIGNALS. Each has exactly one job, and the jobs do not
     overlap. This is the rule that keeps the page from reading as a
     screensaver -- see rule 3 in depth.css.

       --chrome    the machine itself: UI, structure, focus, wayfinding.
                   It is the ONLY one of the four that is allowed on
                   something the user merely clicks.
       --phosphor  LIVE SYSTEM DATA ONLY. Counts, timers, measurements,
                   state read out of the running system. The 80s
                   artifact. If it is not a fact the server just
                   computed, it is not green.
       --classify  classification ink. CLASSIFIED / EYES ONLY, and the
                   holes classification leaves behind.
       --threat    the threat readout, and nothing else on the site.

     Each also has an -rgb triple, so a component can compose its own
     alpha without hard-coding the hex a fourth time:
         background: rgba(var(--phosphor-rgb), .09);
     ------------------------------------------------------------------ */
  --chrome:   #7DD3FC;
  --phosphor: #5BF2A8;
  --classify: #FF3B5C;
  --threat:   #FFB020;

  --chrome-rgb:   125, 211, 252;
  --phosphor-rgb: 91, 242, 168;
  --classify-rgb: 255, 59, 92;
  --threat-rgb:   255, 176, 32;

  /* ------------------------------------------------------------------
     THE THREE GLOWS, NAMED.

     Naming them is what makes rule 3 enforceable by reading: a glow that
     is not one of these three tokens is a glow somebody invented, and
     the reviewer can see that in the diff. --glow-chrome is the
     exception that proves it -- it is for the FOCUS RING and for a
     hover lift, never for resting state.
     ------------------------------------------------------------------ */
  --glow-phosphor: 0 0 14px rgba(var(--phosphor-rgb), 0.42);
  --glow-classify: 0 0 18px rgba(var(--classify-rgb), 0.55);
  --glow-threat:   0 0 16px rgba(var(--threat-rgb), 0.45);
  --glow-chrome:   0 0 22px rgba(var(--chrome-rgb), 0.35);

  /* The keyboard focus ring, as one token. Two rings: a dark one that
     separates the bright one from whatever is underneath, then the
     bright one, then its bloom. It is a box-shadow rather than an
     outline so it survives a clip-path or an overflow:hidden -- the bug
     025_theme_contract_test.php already guards on the landing page. */
  --ring: 0 0 0 2px var(--void), 0 0 0 4px var(--chrome), var(--glow-chrome);

  /* ------------------------------------------------------------------
     TEXT RAMP. The ink ramp below resolves to these, so the whole site
     moved from neutral grey onto this cool ramp in one edit.

     Measured on --void (#06070C), which is the ground every page paints:
       --text        17.1:1     --text-3      6.0:1
       --text-2      12.7:1     --text-faint  4.8:1
       --text-dim     7.2:1
     ------------------------------------------------------------------ */
  --text:       #E6EDF7;
  --text-2:     #C3CEE0;
  --text-dim:   #8C9BB5;
  --text-3:     #7E8DA6;
  --text-faint: #6E7D96;

  /* --text-faint is #6E7D96 and NOT direction.html's #5A6880, which is
     the one number in this file that deliberately departs from the
     reference. #5A6880 measures 3.6:1 on --void: fine for a rule or a
     bracket, below AA for the metadata lines the reference actually
     uses it on. Two steps of luminance buys 4.8:1 and nothing else on
     the page changes. */

  /* ------------------------------------------------------------------
     IDENTITY COLOURS.

     --c-red IS THE CLASSIFICATION INK NOW. It has moved #ff2a00 ->
     #FF3B5C, which is the whole of the change: the site had one red and
     it was already doing the classification job everywhere it appeared
     (CLASSIFIED chips, the withheld markers, the distribution control).
     Naming it --classify and pointing --c-red at it means the ~90
     existing `var(--c-red)` declarations become the classification
     signal without one of them being edited, and there is exactly one
     red on the screen instead of two. It measures 5.8:1 on the new
     ground, up from 5.4:1.

     --c-yellow is NOT --threat and must not be pointed at it. It is the
     legacy accent (links, pinned posts, the star rating) and it is
     #ffcc00, 13.5:1. --threat is amber, it is reserved for threat levels
     4 and 5, and a link that borrows it is a link that claims somebody
     is in danger. New work uses --chrome for interface colour.
     ------------------------------------------------------------------ */
  --c-red:     var(--classify);
  --c-red-dim: #5E1526;   /* a BORDER/FILL colour. 1.5:1 as text - never use it as one */
  --c-yellow:  #ffcc00;
  --c-bg:      var(--void);

  /* ------------------------------------------------------------------
     INK RAMP - text only. Every step still passes AA on --c-bg.

     The four steps are ALIASES onto the text ramp above now, so the
     hundreds of `color: var(--c-ink-3)` declarations across nine
     stylesheets moved from neutral grey onto the cool ramp without one
     of them being touched. The measured ratios are re-stated against
     the new ground (--void) and every one of them went UP or held:

       --c-ink   17.6 -> 17.1   --c-ink-3   7.3 -> 7.2
       --c-ink-2 12.6 -> 12.7   --c-ink-4   5.9 -> 6.0
     ------------------------------------------------------------------ */
  --c-ink:   var(--text);       /* 17.1:1 - body                        */
  --c-ink-2: var(--text-2);     /* 12.7:1 - prose, table cells          */
  --c-ink-3: var(--text-dim);   /*  7.2:1 - metadata, labels            */
  --c-ink-4: var(--text-3);     /*  6.0:1 - the faintest text permitted */

  /* ------------------------------------------------------------------
     LINE + SURFACE RAMP - borders and fills only. Never `color:`.

     Now blue-black rather than neutral, for the same reason the ground
     is: a neutral #111 panel sitting on a blue-black ground reads as a
     dirty patch, and a glow crossing the seam changes hue. Measured on
     --void: --c-line-3 1.4:1, --c-line 1.6:1, --c-line-2 2.1:1 - the
     same ladder the neutral ramp had.

     The surfaces are OPAQUE and are what a non-glass container uses.
     Glass is --pane-1/2/3 up in the depth block, and it is not
     interchangeable with these: see rule 4 in depth.css for which of the
     two a given surface is allowed to be.
     ------------------------------------------------------------------ */
  --c-line:      #2A3145;
  --c-line-2:    #3A4560;
  --c-line-3:    #212840;
  --c-surface-1: var(--deep);
  --c-surface-2: var(--pane-2-solid);
  --c-surface-3: var(--pane-3-solid);
  --c-panel:     var(--pane-2-solid);

  /* ------------------------------------------------------------------
     SPACING - one ramp, in rem, derived from the 4/5/6/8/10/12/15/20/
     25/30/40/60px values already in the file. Three of those drift by
     1-2px in the mapping (15->16, 25->24, 30->32). That drift is the
     only visible consequence of this ramp and it is what makes the
     vertical rhythm regular.
     ------------------------------------------------------------------ */
  --space-1: 0.25rem;   /*  4px */
  --space-2: 0.5rem;    /*  8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px - was 15px */
  --space-5: 1.25rem;   /* 20px */
  --space-6: 1.5rem;    /* 24px - was 25px */
  --space-7: 2rem;      /* 32px - was 30px */
  --space-8:  2.5rem;   /* 40px */
  --space-9:  3.75rem;  /* 60px */
  --space-10: 5.5rem;   /* 88px - ADDED. The depth pass puts real air
                           between sections; --space-9 was the ceiling
                           and 60px is a gap, not a breath. */

  /* direction.html is written in a --s1..--s6 vocabulary. These are
     ALIASES onto the ramp above, not a second scale: a site with two
     spacing scales has none. Anyone copying technique out of the
     reference gets working spacing, and it lands on the same rhythm
     everything else on the site is already on. */
  --s1: var(--space-2);    /* 0.5rem  */
  --s2: var(--space-3);    /* 0.75rem */
  --s3: var(--space-5);    /* 1.25rem */
  --s4: var(--space-7);    /* 2rem    */
  --s5: var(--space-9);    /* 3.75rem */
  --s6: var(--space-10);   /* 5.5rem  */

  /* ------------------------------------------------------------------
     TYPE SCALE - roughly a 1.2 modular ramp. The two display steps are
     fluid, which is what lets .section-title stop being overridden to
     eight different pixel sizes across nine views.
     ------------------------------------------------------------------ */
  --fs-100: 0.75rem;
  --fs-200: 0.8125rem;
  --fs-300: 0.875rem;
  --fs-400: 1rem;
  --fs-500: 1.125rem;
  --fs-600: 1.375rem;
  --fs-700: 1.75rem;
  --fs-800: clamp(1.75rem, 1.2rem + 2.2vw, 3rem);   /* .section-title - caps at today's 3rem */
  --fs-900: clamp(2.5rem, 1.5rem + 4vw, 4rem);      /* page hero titles */

  /* Bebas Neue is condensed all-caps and reads about 15% smaller than
     Courier Prime at the same px. The UI-face steps are therefore each
     one step up the ramp, so a Bebas label and a Courier body line
     optically match instead of merely measuring the same. */
  --fs-ui-100: var(--fs-200);
  --fs-ui-200: var(--fs-300);
  --fs-ui-300: var(--fs-400);
  --fs-ui-400: var(--fs-500);
  --fs-ui-500: var(--fs-600);
  --fs-ui-600: var(--fs-700);

  --lh-tight: 1.1;
  --lh-base:  1.6;
  --lh-prose: 1.7;

  /* Measure. .dash-content has no max-width, so on a 2560px display a
     recipe description runs 2000+ characters to the line. */
  --measure-page:  1400px;
  --measure-prose: 78ch;

  /* ------------------------------------------------------------------
     BORDER, RADIUS, SHADOW
     --radius-0 exists so that nobody "helpfully" adds rounding: this
     theme is deliberately square and the corner brackets are the motif.
     ------------------------------------------------------------------ */
  --radius-0:    0;
  --border-1:    1px solid var(--c-line);

  /* GLASS IS ROUNDED, CHROME IS SQUARE, and that is not a contradiction
     of the note above. The corner-bracket motif stays exactly where it
     is -- on the tactical chrome, which is still --radius-0. A pane is a
     different material: a physical sheet of glass has a machined edge,
     and a hard 90-degree corner on a blurred translucent surface is the
     one place this theme's squareness reads as unfinished rather than
     deliberate. Three steps, and nothing on the site gets rounded by
     accident because nothing picks these up without asking. */
  --radius-pane: 14px;   /* cards, panels, sheets                       */
  --radius-2:    10px;   /* rows inside a pane, the threat ladder       */
  --radius-1:    5px;    /* chips, stamps, the redaction bar            */

  --shadow-card: 0 5px 15px rgba(0, 0, 0, 0.5);
  --shadow-drop: 0 10px 30px rgba(0, 0, 0, 0.8);

  /* ------------------------------------------------------------------
     MOTION - the three durations already in the file, named. Naming
     them is what lets the prefers-reduced-motion block in app.css kill
     every transition on the site in one rule.
     ------------------------------------------------------------------ */
  --dur-fast: 0.15s;
  --dur-base: 0.2s;
  --dur-slow: 0.3s;
  --ease:     ease;

  /* The depth pass adds two. --ease-lift is the reference's curve: it
     leaves fast and arrives slowly, which is what makes a card feel like
     an object with mass rather than a div with a transition. --dur-sweep
     is the redaction scan, and it is deliberately far too slow to watch
     -- it is the one place the 80s artifact is allowed to MOVE, and it
     has to be something you catch out of the corner of your eye. */
  --dur-lift:  0.34s;
  --ease-lift: cubic-bezier(0.2, 0.7, 0.3, 1);
  --dur-sweep: 5.5s;

  /* ------------------------------------------------------------------
     LAYERS - replaces 17 ad-hoc z-index values across three files.

     Read this as documentation of what stacks over what:

       card 10  <  sticky 100  <  scanline film 900  <  drawer 1100
            <  dropdown 1200  <  modal 3000  <  lightbox 5000  <  toast

     Worth knowing, because it is a real behaviour and not an accident
     any more: .dash-content::after is the fixed CRT scanline film. Both
     the mobile nav drawer and the notification dropdown sit ABOVE it,
     so they are the two surfaces on the site that lose the texture.
     These numbers preserve that ordering exactly as it is today. Moving
     either one under the film means giving it a value below
     --z-scanlines, which is a deliberate visual change, not a rename.
     ------------------------------------------------------------------ */
  --z-base:      0;
  --z-card:      10;
  --z-sticky:    100;
  --z-scanlines: 900;
  --z-drawer:    1100;
  --z-dropdown:  1200;
  --z-modal:     3000;
  --z-lightbox:  5000;
  --z-toast:     6000;
}
