/* =============================================================================
   Ressourcenplanung — Design Tokens
   -----------------------------------------------------------------------------
   Derived by frequency analysis from the visual mockup
   docs/wireframes/260825_Portfolio Resource Management/
     Ressourcenplanung Bereichsleitung.dc.html
   Every primitive value below occurs literally in that file, except the
   pensum heat ramp and the bar ground, which were re-measured in CIE Lab
   when the two came to share a row (see section 12).

   Layer 1 = primitives (raw values), Layer 2 = semantic roles (var over them).
   Only ever reference the semantic layer from main.css.
   ============================================================================= */

:root {
  /* ==========================================================================
     1 · PRIMITIVES — neutral grey ramp
     The workhorse ramp: the seven most-used colours in the whole mockup.
     ========================================================================== */
  --grey-50:  #f9fafb;
  --grey-100: #f3f4f6;
  --line-subtle: #e3e9f3;   /* 1.18:1 — grid hairlines */
  --line:        #ced3dd;   /* 1.45:1 — dividers and card edges */
  --line-rule:   #a4a8b0;   /* structural rules — table head, totals, sheet     */
  --line-strong: #83878f;   /* 3.18:1 on the page ground — control outlines,
                               the level WCAG 1.4.11 asks of them            */
  --fill-chip:   #d9dee8;   /* 1.30:1 — a chip has to read as an object */
  --grey-200: #e5e7eb;
  --grey-300: #d1d5db;
  --grey-400: #9ca3af;
  --grey-500: #6b7280;   /* 4.8:1 on white — disabled text, and nothing lighter says a word */
  --grey-550: #636b7a;   /* 5.4:1 — clears AA, and was judged too light to read; borders only now */
  --grey-600: #4b5563;   /* 7.6:1 on white, 6.7:1 on the page ground */
  --grey-650: #414b5a;   /* 8.8:1 — one step under the body text, for headings and captions */
  --grey-700: #374151;
  --grey-800: #1f2937;
  --grey-900: #111827;
  --white:    #ffffff;

  /* ==========================================================================
     2 · PRIMITIVES — brand navy + accent blue
     ========================================================================== */
  --navy-900: #12213e;

  --blue-50:  #eff6ff;
  --blue-100: #dbeafe;
  --blue-200: #c7d2fe;
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;
  --blue-800: #1e40af;

  /* ==========================================================================
     3 · PRIMITIVES — "steel", a second blue-shifted neutral family
     Carries the app-frame surfaces and the pensum heat ramp.
     Deliberately NOT folded into --grey-*.
     ========================================================================== */
  --steel-25:  #fafbfd;
  --steel-50:  #f5f7fb;
  --steel-100: #f0f4fa;
  --steel-125: #eef1f6;
  --steel-500: #9cb8de;
  --steel-550: #76879f;

  /* ==========================================================================
     4 · PRIMITIVES — status hues
     ========================================================================== */
  --red-50:   #fef2f2;
  --red-100:  #f5dada;   /* greyscale 224 — the darkest status fill */
  --red-200:  #fecaca;
  --red-300:  #fca5a5;
  --red-600:  #dc2626;
  --red-700:  #b91c1c;
  --red-800:  #991b1b;

  --amber-50:  #fffbeb;
  --amber-100: #f5eac0;  /* greyscale 234 */
  --amber-200: #fde68a;
  --amber-600: #d97706;
  --amber-750: #8a4a0b;
  --amber-900: #78350f;

  --green-50:  #f0fdf4;
  --green-100: #dcfbe7;  /* greyscale 244 */
  --green-200: #bbf7d0;
  --green-600: #16a34a;
  --green-800: #166534;

  /* ==========================================================================
     5 · PRIMITIVES — alpha overlays
     ========================================================================== */
  --alpha-white-10: rgba(255, 255, 255, 0.10);
  --alpha-white-12: rgba(255, 255, 255, 0.12);
  --alpha-white-22: rgba(255, 255, 255, 0.22);
  --alpha-white-25: rgba(255, 255, 255, 0.25);
  --alpha-ink-28:   rgba(17, 24, 39, 0.28);

  /* ==========================================================================
     6 · SEMANTIC — text roles
     ========================================================================== */
  --color-text-strong:        var(--grey-900);
  --color-text:               var(--grey-700);
  --color-text-body:          var(--grey-800);
  /*
   * The two quiet tiers moved one step darker in the contrast review: muted
   * text sat at 5.4:1 on white and 4.7:1 on the page ground — AA, and still
   * the grey the users called too light, on IDs, zero values, captions and
   * notes, some 5 800 places on one screen. Both keep their rank: muted is
   * lighter than secondary, secondary lighter than the body text.
   */
  --color-text-secondary:     var(--grey-650);   /* 8.8:1 on white, 7.8:1 on the page ground */
  --color-text-muted:         var(--grey-600);   /* 7.6:1 on white, 6.7:1 on the page ground */
  --color-text-disabled:      var(--grey-500);   /* 4.8:1 — greyed, and still a word */
  --color-text-subtle:        var(--grey-400);   /* NON-TEXT ONLY — 2.5:1, for disabled glyphs and empty markers */
  --color-text-inverse:       var(--white);
  --color-text-link:          var(--blue-700);
  --color-text-link-hover:    var(--navy-900);

  /* ==========================================================================
     7 · SEMANTIC — borders
     ========================================================================== */
  --color-border-subtle:   var(--line-subtle);   /* inner grid column hairlines */
  --color-border:          var(--line);          /* default card / row divider  */
  --color-border-rule:     var(--line-rule);     /* table head, totals, sheet   */
  --color-border-strong:   var(--line-strong);   /* inputs, buttons             */
  /*
   * Every consumer of this is a boundary, and at grey-400 all four measured
   * below 3:1 — .btn:hover 2.24 on the page ground, the menu tickbox 2.54 on
   * white, the popover 1.70 over a heat-4 cell, the open diamond 2.24 on the bar
   * it sits on. Worse, .btn:hover went *lighter* than its own 3.18 rest: the one
   * state a reader is looking hardest at had the weakest edge.
   */
  --color-border-emphasis: var(--grey-550);   /* boundaries, 1.4.11: ≥ 3:1   */
  --color-border-contrast: var(--grey-900);   /* open / active menu button   */
  --color-border-accent:   var(--blue-600);   /* focused search field        */

  /* ==========================================================================
     8 · SEMANTIC — surfaces
     ========================================================================== */
  --color-page-bg:          var(--steel-125);
  --color-surface:          var(--white);
  --color-surface-alt:      var(--grey-50);
  --color-surface-sunken:   var(--grey-100);
  --color-surface-hover:    var(--steel-100);
  /*
   * Pressed. One magnitude for the whole family, because the previous value was
   * --color-surface-sunken — 1.003:1 from the hover it was supposed to follow,
   * which is to say no press at all on ten controls.
   */
  --color-surface-pressed:  var(--grey-300);

  --color-surface-selected: var(--blue-50);

  /*
   * A standing notice about the application itself — not about the plan, and
   * not a state a row can be in. Its own role rather than a borrowed one, so it
   * cannot drift into meaning something about the data.
   *
   * blue-200 rather than one of the paler blues, because the page ground is
   * itself a very light blue-grey: blue-50 measures 1.04:1 against it and
   * blue-100 1.08:1, which separate by hue alone and so not at all for a reader
   * who cannot see the hue. This one carries 1.32:1 as well as the hue, and
   * still leaves the text at 11.9:1.
   *
   * The rule on top is blue-600: 3.46:1 against the band and 4.57:1 against the
   * page, so the edge holds on both sides. blue-300 was the obvious choice and
   * measured 1.21:1 against the band — a border nobody would see.
   */
  --color-surface-frame:    var(--steel-50);   /* app frame + table header   */
  --color-scrim:            var(--alpha-ink-28);

  /* ==========================================================================
     9 · SEMANTIC — brand shell + accent
     Note: "on" states in this design are dark neutral, not blue.
     ========================================================================== */
  --color-brand:                       var(--navy-900);
  --color-brand-fg:                    var(--white);
  --color-brand-fg-muted:              var(--blue-200);
  --color-brand-control-bg:            var(--alpha-white-10);
  --color-brand-control-bg-strong:     var(--alpha-white-12);
  --color-brand-control-border:        var(--alpha-white-22);

  --color-accent:        var(--blue-600);
  --color-accent-fg:     var(--white);
  /* A filled control keeps a fill when pressed. Falling through to the neutral
     press left a white label on near-white: measured 1.101:1. */
  --color-accent-pressed: var(--blue-800);
  --color-accent-hover:  var(--blue-700);

  /*
   * A search hit. The reader's own query, not a state of the data — every
   * other hue on the palette already says something about a row: blue the
   * size of a pensum, red overload, amber a missing lead — so it wears the
   * accent tint the reader's own actions already wear, and the strong text
   * at a heavier weight, so it is not colour alone. It only lands in the
   * white text columns and the log, never on the blue value cells. grey-900
   * on blue-100 measures 14.5:1.
   */
  --color-mark-bg: var(--blue-100);
  --color-mark-fg: var(--color-text-strong);

  --color-toggle-on:      var(--grey-900);
  --color-toggle-on-fg:   var(--white);
  /* Same defect, worse: brightness(1.12) also applies while the pointer is down,
     so the chosen segment rendered pure #ffffff under a white label — 1.000:1. */
  /* grey-700, not grey-800: the on-state hover already brightens grey-900, so a
     press one step down measured only 1.21 from it. */
  --color-toggle-on-pressed: var(--grey-700);
  /* The white knob measured 1.47:1 against its own track, so the off switch read
     as a decorative pill rather than a control. */
  --color-toggle-off:     var(--line-strong);
  --color-toggle-knob:    var(--white);

  /* ==========================================================================
     10 · SEMANTIC — status pairs
     Capacity logic: > 100 % danger · >= 95 % warn · >= 80 % ok · else neutral
     ========================================================================== */
  --color-danger-bg:            var(--red-100);
  --color-danger-fg:            var(--red-800);
  --color-danger-fg-strong:     var(--red-700);
  --color-danger-border:        var(--red-300);
  --color-danger-solid:         var(--red-600);

  --color-warn-bg:        var(--amber-100);
  --color-warn-fg:        var(--amber-900);
  --color-warn-fg-alt:    var(--amber-750);
  --color-warn-border:    var(--amber-200);
  --color-warn-solid:     var(--amber-600);
  --color-warn-bg-subtle: var(--amber-50);    /* "ohne Projektleitung" row   */

  --color-ok-bg:        var(--green-100);
  --color-ok-fg:        var(--green-800);
  --color-ok-solid:     var(--green-600);


  --color-neutral-bg:     var(--grey-50);   /* greyscale 251 — the lightest */
  --color-neutral-fg:     var(--grey-600);
  --color-neutral-bg-alt: var(--grey-200);
  --color-neutral-solid:  var(--grey-400);

  /* ==========================================================================
     11 · Ampel — the project lead's own utilisation
     Wired to the status ramp so the four states keep its tuned luminances.
     Shape, not hue, is what separates them: disc / ring / diamond / outline.
     ========================================================================== */
  --ampel-ok-bg:        var(--color-ok-bg);
  --ampel-ok-border:    var(--color-ok-solid);
  --ampel-tight-bg:     var(--color-surface);
  --ampel-tight-border: var(--color-warn-solid);
  --ampel-over-bg:      var(--color-danger-bg);
  --ampel-over-border:  var(--color-danger-solid);

  /* A planned milestone is structure, not status. */
  --color-milestone:    var(--grey-600);

  /* ==========================================================================
     12 · Pensum heat ramp — blue only encodes the SIZE of a pensum
     0 % · 1–39 % · 40–79 % · 80–119 % · >= 120 %, plus no-value and negative
     ========================================================================== */
  /*
   * Three colour jobs meet on one surface: the ramp encodes a quantity, and
   * the phase bar's ground is structure that must never read as one. Measured
   * in CIE Lab, the old ground (steel-150) sat dE 2.2 from heat-1 and 2.6
   * from heat-2 — a step of the ramp, not a grey beside it — so a bar could
   * read as a low pensum value. Turning the ground grey does not fix it on
   * its own: the bottom of the ramp was itself all but colourless (heat-1 at
   * a chroma of 2.8), and a plain neutral at that lightness measured dE 1.9
   * from it. So both ends moved. The ramp keeps its hue and its lightness
   * ladder and gains a chroma floor; the ground becomes a true neutral.
   *   ground to nearest ramp step   dE 2.2 → 5.7
   *   adjacent ramp steps           4.0 4.4 5.5 6.7 → 5.7 6.0 6.5 6.8
   */
  --heat-0-bg:    var(--white);      --heat-0-fg:    var(--color-text-muted);
  --heat-1-bg:    #eef8ff;           --heat-1-fg:    var(--grey-800);
  --heat-2-bg:    #dfefff;           --heat-2-fg:    var(--grey-800);
  --heat-3-bg:    #cee4fd;           --heat-3-fg:    var(--grey-900);
  --heat-4-bg:    #b9d6f6;           --heat-4-fg:    var(--grey-900);
  --heat-null-bg: var(--steel-25);   --heat-null-fg: var(--color-text-muted);
  --heat-neg-bg:  var(--red-100);    --heat-neg-fg:  var(--red-800);

  --color-bar-bg:     #eeeeee;   /* a true neutral — see the ramp above */
  /*
   * The edge of a phase bar, and the only thing separating one phase from the
   * next where two abut. At steel-400 it measured 1.38:1 against the bar and
   * read as missing on half the bars; this clears 3:1 on all four variants,
   * which 1.4.11 asks of a boundary that carries meaning.
   */
  --color-bar-border: var(--steel-550);


  /* Hatched fills: a delayed bar, and a bar with no project lead */
  --pattern-delay:   repeating-linear-gradient(135deg, #fca5a5 0 5px, #fef2f2 5px 10px);
  --pattern-no-lead: repeating-linear-gradient(135deg, #fde68a 0 5px, #fffbeb 5px 10px);

  /* ==========================================================================
     13 · Typography
     ========================================================================== */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;

  --text-2xl:  24px;   /* page title                       */
  --text-xl:   22px;   /* KPI value, section heading       */
  --text-lg:   18px;   /* stepper glyph, strong numeric    */
  --text-sub:  16px;   /* sub-section heading              */
  --text-tab:  15px;   /* tab labels, list item titles     */
  --text-btn:  14px;   /* button labels                    */
  --text-base: 13px;   /* DEFAULT body / table cell        */
  --text-sm:   12px;   /* secondary text, table header     */
  --text-xs:   11px;   /* badges, captions                 */
  --text-2xs:  10px;   /* notification count, tiny tag     */

  --font-regular:  400;
  /*
   * No --font-medium. Segoe UI — the platform this ships on — has no Medium, so
   * 500 resolves to Semibold and rendered pixel-identically to 600 across 874
   * instances. Three weights are declared because three is what renders.
   */
  --font-semibold: 600;
  --font-bold:     700;

  --leading-snug:    1.3;
  --leading-compact: 1.4;
  --leading-normal:  1.5;
  --leading-relaxed: 1.55;

  --tracking-h2: -0.015em;
  --tracking-h3: -0.01em;
  --tracking-caption: 0.02em;   /* 10px badges — tiny text set solid reads as a blur */

  /* The «not available» texture. An overlay, so it works over every heat step
     and leaves the value's own colour alone. */
  /* ==========================================================================
     14 · Spacing
     ========================================================================== */
  --space-1:  2px;
  --space-2:  4px;
  --space-3:  6px;
  --space-4:  8px;
  --space-5:  10px;   /* the default gap */
  --space-6:  12px;
  --space-7:  14px;
  --space-8:  16px;
  --space-10: 20px;
  --space-11: 24px;
  --space-12: 28px;
  --space-13: 32px;

  /* ==========================================================================
     15 · Radii
     ========================================================================== */
  /*
   * A radius says what kind of thing something is, not how big it is: a mark
   * inside a control, a control, a surface, or a thing that is round by
   * nature. Four steps carry that. A fifth would only be a variant of one of
   * them, and a variant reads as an inconsistency rather than a decision.
   */
  --radius-xs:   2px;    /* hairline detail — focus ring, sparkline, Ampel tip */
  --radius-sm:   3px;    /* a mark inside a control — tickbox, track, bar     */
  --radius:      6px;    /* controls — buttons, inputs, tabs, menu items      */
  --radius-lg:   8px;    /* surfaces — cards, panels, popovers, modals        */
  --radius-pill: 9999px; /* round by nature — avatars, badges, switches       */

  /* ==========================================================================
     16 · Borders, elevation, focus
     ========================================================================== */
  /* ==========================================================================
     Motion
     --------------------------------------------------------------------------
     Two durations carry the whole app: one for a control answering a pointer,
     one for something entering or leaving the page. A third would be a guess.
     The reduced-motion block at the end of main.css overrides all of them.
     ========================================================================== */
  --dur-fast:  .12s;   /* a control answers: hover, press, toggle, caret     */
  --dur:       .16s;   /* something enters or leaves: toast, search, banner  */
  --dur-spin:  .7s;    /* the boot spinner, the only continuous motion       */
  --ease:      ease;
  --ease-in:   ease-in;

  /* The WCAG 2.2 minimum for a pointer target. Named because it is a rule the
     design has to keep, not a measurement someone picked. */
  --target-min: 24px;

  --border-hairline: 1px;
  --border-control:  1.5px;
  --border-emphasis: 2px;

  --shadow-menu:  0 20px 25px -5px rgba(0, 0, 0, 0.18);
  --shadow-menu-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.18),
                    0 8px 10px -6px rgba(0, 0, 0, 0.1);
  /* Content cards sit on the page ground with a soft lift instead of a border. */
  /* A card that lifts on hover needs somewhere to lift to. */
  --shadow-raised: 0 1px 2px rgba(16, 24, 40, 0.04), 0 4px 12px rgba(16, 24, 40, 0.06);
  /*
   * The edge of a scrolling card. A gradient rather than a box-shadow, because
   * a shadow with a negative spread stops short of the box it belongs to — the
   * right-hand one ended 8px inside the card. This lands exactly on the edge,
   * and the two sides are the same ramp mirrored.
   */
  /*
   * The ramp at a scrolling edge. At .055 it was there in the stylesheet and not
   * on the screen — on a laptop panel in a lit meeting room it read as nothing
   * at all, and the one thing it has to say is that the plan continues.
   */
  --scroll-edge: rgba(17, 24, 39, 0.09);
  --scroll-edge-w: 22px;
  --shadow-modal: 0 24px 48px rgba(0, 0, 0, 0.18);

  --rail-danger: inset 3px 0 0 var(--red-600);
  --rail-warn:   inset 3px 0 0 var(--amber-600);

  /* blue-700, not blue-500: the ring is painted onto the neighbouring heat
     cell, where 500 measured 2.46:1. 700 clears 3:1 on every ground it meets. */
  --focus-ring:        3px solid var(--blue-700);
  --focus-ring-offset: 2px;
  --ring-cell-edit:    inset 0 0 0 2px var(--blue-600);

  /* ==========================================================================
     17 · Layout metrics
     ========================================================================== */
  --layout-width:    1440px;   /* prose and cards: a readable measure */
  --layout-width-grid: 1800px;  /* the two planning grids: at this width no
                                   project name truncates any more */
  --shell-pad-x:     28px;
  --header-height:   60px;
  --tabbar-height:   40px;

  /* Pensum grid */
  --grid-quarter:      72px;    /* one quarter column        */
  --grid-quarter-max:  96px;    /* and its ceiling: past this a wider window
                                   should lengthen the project name, not the
                                   space around a two-digit number */

  /*
   * One time column, whatever the scale is measuring. Both grids use these, so
   * a column is the same width in Übersicht and in Termine and the frozen block
   * does not move when the reader switches tab.
   *
   * A year is given room for four of them to fill a small laptop, because that
   * is as much of a ten-year plan as can be read at once; the rest is reached
   * by panning, the way every other overflow in these grids is. The whole plan
   * at one glance is what the A0 report is for.
   */
  --grid-period:       var(--grid-quarter);
  --grid-period-max:   var(--grid-quarter-max);
  /*
   * The same at every scale. Narrower months fitted more of them on screen but
   * left the sum rows too tight for their own figures — "4415 %" broke onto a
   * second line in a 52px column, and a total that wraps reads as two numbers.
   * What the scale changes is what a column means and how many there are.
   */
  /*
   * One column of a dashboard chart. Derived, not chosen: the widest value a
   * chart carries sets 37px and the widest axis label 31px, so anything below
   * this breaks the label onto a second line. Charts scroll past it rather than
   * squeezing, exactly as the grids do.
   */
  --chart-col:          40px;

  --grid-col-id:        62px;
  --grid-col-title:     285px;   /* the floor; the column takes the slack */
  --grid-col-title-max: 460px;   /* and its ceiling — the width at which the
                                    longest project name fits */
  --grid-col-phase:     152px;  /* «33 Bewilligungsverfahren» in full, 144px + padding */
  --grid-col-lead:      140px;   /* «Dario Beispielmann» with 8px of air on each side */
  --grid-col-portfolio: 110px;
  --grid-col-organisation: 112px;  /* «PM Inland III», the longest short form, plus its padding */
  --grid-col-credit:    112px;

  /* The person table has its own five lead columns. */
  --person-col-name:       150px;
  --person-col-employment: 96px;   /* «Anstellung» in full, with its sort arrow */
  --person-col-projects:   84px;   /* «Projekte», likewise */
  --person-col-peak:       76px;

  /* Rows and controls */
  --row-height:         38px;
  --row-height-sum:     34px;
  --row-height-load:    42px;   /* the Auslastung row under the totals */

  /* Popovers and the dialog: one width each, read by the stylesheet and by
     the code that places them (tokenPx), so the two cannot drift apart. */
  --pop-width:          308px;  /* the pensum editor */
  --pop-assign-width:   336px;  /* the Bearbeitender picker */
  --modal-width:        760px;

  /* The milestone diamond's hit area. Every diamond sits in a band, so there
     is one size; the printed sheet scales its own down. */
  --gate-size:          20px;
  --row-height-list:    48px;
  --bar-height:      24px;
  /* The bar plan inside a pensum row: a strip under the figures, tall enough
     for the sub-phase number and no more. */
  --band-height:     14px;

  --control-height-sm: 26px;
  --control-height:    32px;
  --control-height-lg: 34px;
  --control-height-xl: 36px;
  --control-height-2xl: 38px;

  --switch-width:  34px;
  --switch-height: 19px;
  --switch-knob:   15px;
  --avatar-size:   32px;
  /* ==========================================================================
     Paper
     --------------------------------------------------------------------------
     The printed sheet is its own design at absolute sizes, because a page is a
     fixed physical thing and does not scale with the viewport. Naming the
     scale keeps it reviewable next to the screen one.
     ========================================================================== */
  --sheet-text:    10px;     /* column heads, footnotes, metadata line       */
  --sheet-lead:    11px;     /* sender block and subtitle                    */
  --sheet-title:   16px;     /* the document title                           */
  --color-paper:   var(--white);

  /* The HTTP method badges of the embedded Swagger UI. They are not part of the
     app palette — they are the widget's own colours, darkened until the white
     text on them clears AA. Named so the contrast decision stays reviewable. */
  --method-get:    #1b6ca8;   /* 4.87:1 on white text */
  --method-post:   #1f7a4d;   /* 4.62:1 */
  --method-patch:  #14707c;   /* 4.55:1 */
  --method-put:    #9a5b12;   /* 4.63:1 */
  --method-delete: #a12b2b;   /* 6.83:1 */
  --method-neutral: var(--grey-600);
  --method-auth:   #1f6f43;   /* the authorise button, on white */
  --shadow-sheet:  0 8px 24px rgba(0, 0, 0, 0.14);

  --dot-size:      10px;

  /* ==========================================================================
     18 · Stacking order
     ========================================================================== */
  --z-base:    1;
  --z-raised:  2;
  --z-sticky:  5;
  --z-label:   6;
  /* Drawn over the plan: the today marker and the frozen pane's shadow. */
  --z-overlay: 7;
  /* The frozen pane itself, above everything that scrolls underneath it. */
  --z-frozen:  8;
  --z-popover: 70;
  --z-scrim:   79;
  --z-modal:   80;
  --z-toast:   90;
}

