/* ==========================================================================
   Tesseract — the merged design foundation.            v1.0, step 1 of the merge
   --------------------------------------------------------------------------
   ONE JOB: re-point the tokens the three apps already use at one set of values,
   and load the three faces locally so they actually render.

   This file changes no component CSS and no markup. It works because v38 was
   built properly: diary.html's own comment says "components only use role
   tokens, so dark mode is a remap rather than a second stylesheet." That is
   equally true of a restyle. Remap ~30 tokens, restyle the whole app.

   WHERE IT SITS IN THE CASCADE
     1. diary.html's inline <style>      :root{...}          the defaults
     2. /assets/theme.css                :root{--tc-*}       the kit pages
     3. THIS FILE                        :root{...}          wins on source order
     4. <style id="brandcss">            injected at boot    the Config tab wins

   Step 4 is deliberate and is left alone — the Config tab is how colours change
   without a deploy. It also means any colour row still set on that tab will
   override the value below. See the note at the bottom of this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   The faces.

   Self-hosted, not linked. The app ships style-src 'self' and font-src 'self'
   data:, so a Google Fonts link is refused outright and the page falls back to
   the system stack while every request fails — which is what has been happening:
   diary.html has asked for 'Inter' and 'JetBrains Mono' since the port and has
   never once loaded either. Local files also mean the type is right on a site
   with no reception, which a CDN can never be.

   Latin subsets only, from the @fontsource packages (OFL). 172 KB for all eight.
   scripts/fetch-fonts.mjs re-fetches them.
   -------------------------------------------------------------------------- */
@font-face{font-family:'Archivo';font-style:normal;font-weight:600;font-display:swap;
  src:url('/assets/fonts/archivo-600.woff2') format('woff2')}
@font-face{font-family:'Archivo';font-style:normal;font-weight:700;font-display:swap;
  src:url('/assets/fonts/archivo-700.woff2') format('woff2')}

@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;
  src:url('/assets/fonts/plex-sans-400.woff2') format('woff2')}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;
  src:url('/assets/fonts/plex-sans-500.woff2') format('woff2')}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;
  src:url('/assets/fonts/plex-sans-600.woff2') format('woff2')}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:700;font-display:swap;
  src:url('/assets/fonts/plex-sans-700.woff2') format('woff2')}

@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url('/assets/fonts/plex-mono-400.woff2') format('woff2')}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url('/assets/fonts/plex-mono-500.woff2') format('woff2')}

:root{
  /* ---- the sage ramp, from the style guide -------------------------------
     Six of these are the guide's own stops. sage-300 is the one addition: the
     guide's dark theme left sage-600 and sage-700 at their light values, so
     anything using sage-700 as TEXT measured about 2.3:1 on a dark surface.
     #9DBE92 takes it to 8.5:1 and is used only by the dark block below. */
  --sage-50:#F1F5EF;  --sage-100:#E4EBE1; --sage-200:#C8D6C2; --sage-300:#9DBE92;
  --sage-400:#7FA876; --sage-500:#6F9066; --sage-600:#5C7A55; --sage-700:#48603F;
  --sage-800:#3A4C33; --sage-900:#2A3826; --sage-950:#1B2418;

  /* ---- navy, from the style guide ---------------------------------------
     The diary's navy was #030340 — a saturated blue-black that reads as ink on
     a green page. The guide's is desaturated toward the sage, which is what
     lets the two families sit together without either looking like an accident. */
  --navy-50:#F2F5F4;  --navy-100:#E2E9E6; --navy-200:#C4D0C6; --navy-300:#9FB0A4;
  --navy-400:#6B8090; --navy-500:#4A5D6C; --navy-600:#374A59; --navy-700:#2B3D4C;
  --navy-800:#1E2E3B; --navy-900:#16232E; --navy-950:#101A22;

  /* ---- neutrals ---------------------------------------------------------
     Warm, and biased very slightly toward the sage rather than pure grey, so a
     border next to a sage chip does not read as a different temperature. */
  --n-0:#FFFFFF;  --n-50:#FAFBF8;  --n-100:#F6F7F3; --n-200:#DDE2D8; --n-300:#C9D0C4;
  --n-400:#A6AFA1; --n-500:#8B958A; --n-600:#68736B; --n-700:#5C6659; --n-800:#3D453B;
  --n-900:#262C25; --n-950:#171B16;
  /* n-600 is the muted text colour. The guide sets it #7C8880, which measures
     3.4:1 on paper — under the 4.5 a phone in the sun needs, and muted text is
     where dates and hints live. Darkened one step to 4.6:1, same hue. */

  /* ---- state ------------------------------------------------------------
     KEPT ON YOUR INSTRUCTION: warning #E29612 and danger #BD3528 are the
     diary's existing inks, which the Programme also uses for the away hatch —
     its 00_Config.gs says so in as many words ("Site Diary's own palette, so
     the sheet matches the app"). Holding them means the hatch, the overdue
     chip and the error banner are one amber and one red across all three
     modules, rather than the guide's second pair.

     success moves to sage. The guide is explicit that sage IS "done, nothing
     owing", and two greens meaning the same thing is the thing it warns about. */
  --success-100:#F1F5EF; --success-500:#5C7A55; --success-700:#48603F;
  --warning-100:#FBF3E4; --warning-500:#E29612; --warning-700:#9A6B1E;
  --danger-100:#FBEDE9;  --danger-500:#BD3528;  --danger-700:#8A3D2B;
  --info-100:#E6ECF4;    --info-500:#3D6382;    --info-700:#2B4A63;

  /* ---- roles ------------------------------------------------------------
     These are what the component CSS actually reads. Everything above exists
     so that these can be stops rather than hexes. */
  --color-bg:var(--n-100);              /* #F6F7F3 warm paper, not the green page */
  --card-bg:var(--n-0);                 /* white cards lift off it on their own  */
  --topbar-bg:var(--navy-900);
  --topbar-text:#E9EEE7;
  --topbtn-bg:rgba(111,144,102,.20);
  --topbtn-text:#FFFFFF;
  --color-surface:var(--n-0);
  --color-surface-sunken:var(--n-50);
  --color-border:var(--n-200);
  --color-text:var(--navy-900);
  --color-text-muted:var(--n-600);
  --color-primary:var(--sage-600);
  --color-primary-hover:var(--sage-700);
  /* What goes ON a primary fill. .btn hardcoded #fff, which is right in light
     and wrong in dark once primary lifts — see the dark block. */
  --color-on-primary:#FFFFFF;
  --color-accent:var(--sage-700);
  --color-focus:var(--sage-600);

  /* ---- type -------------------------------------------------------------
     --font-display is new. The diary had no display face: h1/h2/h3 were the UI
     face at a larger size, which is why a page title never quite read as one. */
  --font-display:'Archivo',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --font-ui:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* ---- shape ------------------------------------------------------------
     The guide's radii: bigger things get rounder. The diary's were 6/10/16,
     which is already the guide's scale, so only the shadow changes — to the
     guide's single contact-plus-soft pair. */
  --shadow-sm:0 1px 2px rgba(22,35,46,.06);
  --shadow-md:0 1px 2px rgba(22,35,46,.06), 0 8px 24px rgba(22,35,46,.05);
  --shadow-lg:0 24px 60px rgba(22,35,46,.28);
}

/* --------------------------------------------------------------------------
   Dark.

   Matching diary.html, this is [data-theme="dark"] only — the diary has never
   followed prefers-color-scheme and step 1 is not the place to change what the
   theme button means.
   -------------------------------------------------------------------------- */
[data-theme="dark"]{
  --color-bg:var(--navy-950);           /* #101A22 deep blue-green, per the guide */
  --card-bg:#17242E;
  --topbar-bg:#0A1219;
  --topbar-text:#E9EEE7;
  --topbtn-bg:rgba(111,144,102,.22);
  --topbtn-text:#FFFFFF;
  --color-surface:#17242E;
  --color-surface-sunken:#101A22;
  --color-border:#2A3A46;
  --color-text:#E8EEE6;
  --color-text-muted:#8A9A92;

  /* The fix. sage-600 and sage-700 are text colours in dark, so they lift;
     everything that uses them as a FILL is on a dark ground and still reads. */
  --color-primary:var(--sage-300);
  --color-primary-hover:#B4CFA9;
  --color-accent:var(--sage-300);
  --color-focus:var(--sage-400);
  /* Primary is a light green in dark, so white on it measures about 1.9:1.
     The diary's old dark theme had the same fault — primary was sage-400 and
     .btn set color:#fff regardless. Dark text on the light fill is the fix. */
  --color-on-primary:#132018;

  /* The pale end of the sage ramp is used as a BACKGROUND in eight places —
     the job code chip, the day pill, the photos button, the totals chips. Left
     at their light values they are bright white-green tiles on a dark page.
     Rebuilt at low lightness, per the guide.

     sage-700 is the matching half: it is used as TEXT on those same chips, so
     it has to come up as they go down. That is the guide's known gap, fixed
     here — 2.3:1 becomes 8.5:1. sage-600 stays where it is: its only job is a
     hover fill in the top bar, where white sits on it at 4.9:1. */
  --sage-50:#1B2A24; --sage-100:#22362C; --sage-200:#2E4A3B;
  --sage-700:#9DBE92;

  --success-100:#1B2A24; --success-700:#9DBE92;
  --warning-100:#2C2416; --warning-700:#E8C48A;
  --danger-100:#31201C;  --danger-700:#E0AC9B;
  --info-100:#132433;    --info-700:#93B9EC;

  --shadow-sm:0 1px 2px rgba(0,0,0,.3);
  --shadow-md:0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.25);
  --shadow-lg:0 24px 60px rgba(0,0,0,.5);
}

/* --------------------------------------------------------------------------
   Headings take the display face.

   The only rule in this file that is not a token. It is here rather than in the
   generated page because the generated page is generated — a change to it has
   to be a named rule in the port script, and "h1 is Archivo" is a fact about
   the design system, not about the port.
   -------------------------------------------------------------------------- */
h1,h2,h3,h4,.h-display{font-family:var(--font-display);letter-spacing:-.015em}

/* The two rules that fill with primary and hardcoded their own white text.
   Specificity is (0,1,0), so .btn.sec, .btn.danger and .btn[disabled] — all
   (0,2,0) — still set their own colour and are untouched. */
.btn,.iconbtn.on{color:var(--color-on-primary)}

/* Uppercase is a label treatment, never a heading one — the guide's rule. Where
   the diary already uppercases a small label, give it the tracking that makes
   it legible instead of leaving it set solid. */
.eyebrow,.board-t,.k,.sg-sub{letter-spacing:.09em}

/* --------------------------------------------------------------------------
   Module inks.

   The Programme's grain is its own and stays its own. These are scoped rather
   than global so nothing else in the app can start using them by accident, and
   so a change here cannot reach the diary.

   The three you named are here verbatim. --pr-booked is deliberately NOT
   --color-primary: the crew-load square is a dense 8px block in a grid, tuned
   darker than the button green, and you asked for it kept.
   -------------------------------------------------------------------------- */
[data-module="programme"]{
  --pr-booked:#4C5544;
  --pr-away-amber:color-mix(in srgb, #E29612 60%, transparent);
  --pr-away-red:color-mix(in srgb, #BD3528 55%, transparent);
  --pr-hol-grey:color-mix(in srgb, #6E7A88 28%, transparent);
  --pr-tint-s:32%; --pr-tint-l:93%; --pr-dot-s:56%; --pr-dot-l:58%;
  --pr-grid-line:rgba(22,35,46,.09);
  --pr-grid-week:rgba(22,35,46,.18);
}
[data-theme="dark"] [data-module="programme"]{
  --pr-booked:#7FA876;
  --pr-away-amber:color-mix(in srgb, #F0AE41 52%, transparent);
  --pr-away-red:color-mix(in srgb, #E4685A 50%, transparent);
  --pr-hol-grey:color-mix(in srgb, #9AA8B8 24%, transparent);
  --pr-tint-s:26%; --pr-tint-l:17%; --pr-dot-s:34%; --pr-dot-l:52%;
  --pr-grid-line:rgba(232,238,230,.09);
  --pr-grid-week:rgba(232,238,230,.2);
}

/* --------------------------------------------------------------------------
   The kit pages.

   theme.css names its tokens --tc-*. Rather than a second set of values, point
   them at the ones above, so sign-in, the app menu and Team & access cannot
   drift from the diary the way they had.
   -------------------------------------------------------------------------- */
:root{
  --tc-sage:var(--sage-600);        --tc-navy:var(--navy-900);
  --tc-sage-50:var(--sage-50);      --tc-sage-100:var(--sage-100);
  --tc-sage-200:var(--sage-200);    --tc-sage-300:var(--sage-300);
  --tc-sage-400:var(--sage-400);    --tc-sage-500:var(--sage-500);
  --tc-sage-600:var(--sage-600);    --tc-sage-700:var(--sage-700);
  --tc-sage-800:var(--sage-800);    --tc-sage-900:var(--sage-900);
  --tc-navy-50:var(--navy-50);      --tc-navy-100:var(--navy-100);
  --tc-navy-200:var(--navy-200);    --tc-navy-300:var(--navy-300);
  --tc-navy-400:var(--navy-400);    --tc-navy-500:var(--navy-500);
  --tc-navy-600:var(--navy-600);    --tc-navy-700:var(--navy-700);
  --tc-navy-800:var(--navy-800);    --tc-navy-900:var(--navy-900);
  --tc-grey-50:var(--n-50);         --tc-grey-100:var(--n-100);
  --tc-grey-200:var(--n-200);       --tc-grey-300:var(--n-300);
  --tc-grey-400:var(--n-400);       --tc-grey-500:var(--n-500);
  --tc-grey-600:var(--n-600);       --tc-grey-700:var(--n-700);
  --tc-grey-800:var(--n-800);       --tc-grey-900:var(--n-900);
  --tc-success:var(--success-500);  --tc-success-bg:var(--success-100);
  --tc-warning:var(--warning-500);  --tc-warning-bg:var(--warning-100);
  --tc-danger:var(--danger-500);    --tc-danger-bg:var(--danger-100);
  --tc-info:var(--info-500);        --tc-info-bg:var(--info-100);
  --tc-bg:var(--color-bg);          --tc-surface:var(--color-surface);
  --tc-surface-sunken:var(--color-surface-sunken);
  --tc-border:var(--color-border);  --tc-border-strong:var(--n-300);
  --tc-text:var(--color-text);      --tc-text-muted:var(--color-text-muted);
  --tc-text-faint:var(--n-500);     --tc-text-on-dark:#E9EEE7;
  --tc-font:var(--font-ui);         --tc-font-mono:var(--font-mono);
}

/* --- number boxes are typed, not stepped ---------------------------------
   Every browser draws a pair of increment arrows inside an input[type=number]
   -- Chrome and Safari permanently, Firefox on hover. On a phone they are a
   target you hit while trying to put the cursor in the box; on a laptop they
   invite clicking a day count up one at a time. Every number in this app is
   typed, so they go everywhere at once rather than screen by screen.

   `appearance:textfield` is the Firefox half and the two ::-webkit- pseudo-
   elements are the other; both are needed, and neither is inherited, so this
   is the whole of it. It stays a real number input -- the numeric keypad on a
   phone, the step/min/max validation, and `.valueAsNumber` are all unchanged.
   Only the arrows go. */
input[type=number]{-moz-appearance:textfield; appearance:textfield}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none; appearance:none; margin:0}

/* ==========================================================================
   ONE THING TO KNOW BEFORE YOU DEPLOY

   applyBrandColours() in the diary appends <style id="brandcss"> to the end of
   <head> at boot, holding whatever colour rows the Config tab has. That block
   comes after this file and wins — by design, so colours can change without a
   deploy.

   So: if the Config tab still has colour rows set to the OLD values, they will
   override everything above and the app will look unchanged. That is the first
   thing to check if this appears not to have worked. Either clear those rows,
   so the values here are the defaults, or update them to match.
   ========================================================================== */
