/* The design system, layer one: tokens.

   Every value the interface is drawn with is named here and nowhere else - every
   colour, every shadow, every layer, every duration and curve. A rule anywhere else
   names a token; it does not pick a number. tests/frontend/test_the_design_system_holds.py
   reads every stylesheet and fails the build on a raw colour, shadow, z-index or
   duration outside this file, which is what keeps it true after today.

   Three tiers, read top to bottom, and a rule should only ever reach for the last two:

     1. Primitives - the raw palette, named for what they look like (--mist-100,
        --night-850, --blue-600). Nothing outside this file names one. They exist so
        a theme is a mapping and not a second copy of forty hex values, and so the
        same blue is visibly the same blue in both places it is used.
     2. Semantic tokens - named for what they mean (--surface, --ink-3, --accent,
        --danger, --line-soft). This is the layer a page is written in. A theme is a
        block that re-points these at other primitives, and nothing more.
     3. Component tokens - the handful of decisions a component makes that a page may
        want to lean on (a control's height, the focus ring, a card's corner). These
        point at semantic tokens, so they follow the theme without being told.

   Plus the scales that are not colours: space, type, weight, radius, border, shadow
   and elevation, the z-index layers, motion, control and icon sizes, and the
   breakpoints, which CSS cannot read from a variable and are therefore written down
   here and checked by the test instead.

   Loaded first, before base.css, by the app and by every page served before the gate
   (gate.html, invite.html, share.html, swap.html), which is why it lives under
   /assets/ds/: that prefix is open to the door, the rest of /assets is not. */

/* ======================================================= 1. primitives
   Order in this file: primitives, the light semantic layer, the scales, the component
   tokens, then the night theme and print, each of which only re-points tokens
   declared above it. */
:root {
  /* Neutrals for the light page: a cool mist from white to near-black ink. */
  --white: #ffffff;
  --black: #000000;
  --mist-25: #f8fafd;
  --mist-50: #f4f6fb;
  --mist-75: #eef2f9;
  --mist-100: #e9edf5;
  --mist-125: #e8ecf5;
  --mist-150: #dde3ee;
  --mist-500: #7b869f;
  --mist-700: #46506a;
  --mist-950: #0d1424;

  /* Neutrals for the night page: the same steps, inverted, a shade of blue in each. */
  --night-50: #eef1f8;
  --night-200: #a8b2c8;
  --night-500: #6f7a93;
  --night-700: #262e42;
  --night-725: #1e2537;
  --night-750: #1d2434;
  --night-800: #171d2d;
  --night-850: #121724;
  --night-900: #0a0d16;
  --night-950: #060810;

  /* The app's blue, by day and by night, and its washes. */
  --blue-50: #e5ecff;
  --blue-300: #8fa6ff;
  --blue-400: #6d8cff;
  --blue-600: #2f5bea;
  --blue-900: #1a2340;
  --blue-975: #070c1c;

  /* State colours, a day and a night step of each. */
  --red-400: #ff6b60;
  --red-600: #d92d20;
  --amber-300: #f5b544;
  --amber-700: #b25e00;
  --green-300: #3ddc97;
  --green-700: #067647;
  --violet-400: #9b85ff;
  --violet-500: #7c5cff;

  /* Gold, three ways: an open shift (a job to do), a swap being handed over, and the
     burnished gold of a round of requests. Kept apart because they mean apart. */
  --gold-open: #ffc400;
  --gold-open-edge: #c98a00;
  --gold-open-edge-night: #a06f00;
  --gold-open-ink: #3d2800;
  --gold-open-ink-night: #2e1e00;
  --gold-swap: #ffe02e;
  --gold-swap-night: #ffd60a;
  --gold-swap-edge: #c9a000;
  --gold-swap-edge-night: #a98a00;
  --gold-swap-ink: #3a2d00;
  --gold-swap-ink-night: #241c00;
  --gold-ask-a: #cf9a24;
  --gold-ask-b: #f6d57e;
  --gold-ask-c: #dfaa3c;
  --gold-ask-ink: #3b2803;
  --gold-ask-text: #8d6206;
  --gold-ask-text-night: #f2c862;

  /* The build stage: a deep panel lit from inside. */
  --deep-0: #070b1f;
  --deep-1: #111a3d;
  --deep-ink: #e8ecff;

  /* The categorical hues - for tiles and markers that need telling apart. */
  --hue-gold: #c8911a;
  --hue-green: #0e9f6e;
  --hue-blue: #2563eb;
  --hue-purple: #a855f7;
  --hue-red: #dc2626;
  --hue-red-deep: #b91c1c;
  --hue-indigo: #4f46e5;
  --hue-amber: #d97706;
  --hue-yellow: #facc15;
  --on-yellow: #3a2c00;       /* text on the yellow: white is lost on it */
  --hue-sky: #0ea5e9;
  --hue-slate: #64748b;
  --hue-amber-deep: #b45309;
  --hue-pink-deep: #be185d;
  --hue-indigo-deep: #4338ca;
  --hue-teal-deep: #0e7490;

  /* Other companies' colours, which stay theirs. */
  --brand-google: #1a73e8;
  --brand-outlook: #0f6cbd;
  --brand-m365: #6b46c1;
  --brand-apple: #e11d48;

  /* How hard a day is to give, as washes, lines and inks: the request calendar's
     heat and its key. Light in both themes - they are read as a printed key. */
  --heat-easy-bg: #ecfdf5;
  --heat-easy-line: #a7f3d0;
  --heat-mild-bg: #fef9c3;
  --heat-mild-line: #fde047;
  --heat-mild-ink: #713f12;
  --heat-tight-bg: #fed7aa;
  --heat-tight-line: #fb923c;
  --heat-tight-ink: #7c2d12;
  --heat-hard-bg: #fecaca;
  --heat-hard-line: #f87171;
  --heat-hard-ink: #7f1d1d;
  /* The ink on the two washes that have no ink of their own: the day page's ink, in
     both themes, because the washes are light in both. Without it the night theme's
     pale ink went on the pale green, and a calm day's date could not be read. */
  --heat-ink: var(--mist-950);
  --warn-bg: #fef3c7;
  --warn-line: #fcd34d;
  --warn-ink: #7c2d12;

  /* What shadows are made of - the ink's own blue-black - and the backdrop behind a dialog or the rail drawn over a phone's page. */
  --shadow-ink: 16 24 40;
  --scrim-ink: 6 9 18;
}

/* ======================================================= 2. semantic, light
   On :root, and again on anything with a data-theme of its own: a theme is something
   any element can be put in (the style guide shows its specimens in either), and the
   tokens that are worked out from others (--mark-*, --ask-grad) have to be worked
   out again where the theme changes, or they would carry the page's down into it. */
:root, [data-theme] {
  --font: "Montserrat", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;

  /* Colour by meaning. Three families, and each means something, so a new page picks
     by meaning:
       - the accent (blue, per theme) is the app itself - where you are, what to press;
       - ask, a burnished gold, is anything to do with a round of requests: the
         REQUESTS row, the questions, the tile that counts them;
       - the subscribe pair, green into blue, is the calendar leaving for somebody's
         phone. */
  --bg: var(--mist-50);
  --bg-deep: var(--mist-125);
  --surface: var(--white);
  --surface-2: var(--mist-25);
  --surface-3: var(--mist-75);
  --line: var(--mist-150);
  --line-soft: var(--mist-100);
  --ink: var(--mist-950);
  --ink-2: var(--mist-700);
  --ink-3: var(--mist-500);
  --accent: var(--blue-600);
  --accent-ink: var(--white);
  --accent-soft: var(--blue-50);
  --danger: var(--red-600);
  --warn: var(--amber-700);
  --ok: var(--green-700);
  /* Info is the accent: the app has no fourth colour for "for your information",
     and a notice that is neither good nor bad news reads as the app talking. */
  --info: var(--accent);

  --on-fill: var(--white);    /* text and strokes laid on a coloured fill */
  /* Text and strokes on a state's own fill - a toast, a count, a disc in --ok, --danger
     or --warn at full strength. White by day; at night those three turn bright and
     white on them could not be read (a "Saved" toast was white on mint), so the
     night's darkest ink, as --accent-ink is for the accent. */
  --on-state: var(--white);
  --shade: var(--black);      /* what a fill is mixed toward to darken it */

  /* An open shift in a draft under review. Gold, because it is a job to do. */
  --open: var(--gold-open);
  --open-edge: var(--gold-open-edge);
  --open-ink: var(--gold-open-ink);
  /* The shift being handed over, against --ok for the shifts offered back. Yellow,
     and worn as a fill rather than a ring: a tinted chip with a coloured outline sat
     in the same family as the forty other coloured chips around it, which is the one
     distinction this screen exists to make. Nothing else on the roster is yellow -
     --open is the nearest, and that is an empty cell in a draft, with no name on it
     and only ever in front of an admin. */
  --swap: var(--gold-swap);
  --swap-edge: var(--gold-swap-edge);
  --swap-ink: var(--gold-swap-ink);

  /* The round's gold. */
  --ask-a: var(--gold-ask-a);         /* the burnished end */
  --ask-b: var(--gold-ask-b);         /* where the light catches it */
  --ask-c: var(--gold-ask-c);
  --ask-ink: var(--gold-ask-ink);     /* text and strokes on a gold fill */
  --ask-text: var(--gold-ask-text);   /* gold as text, dark enough to read */
  --ask-grad: linear-gradient(120deg, var(--ask-a) 0%, var(--ask-b) 52%, var(--ask-c) 100%);
  --ask-grad-ink: linear-gradient(120deg, var(--ask-text), var(--ask-a));
  --sub-a: var(--hue-green);
  --sub-b: var(--hue-blue);

  /* The build stage at night. The light theme draws its own from the page's tokens
     (see .bx in calendar.css); these stay dark in both for what they also are, the
     shade behind a dialog and the tour's spotlight. */
  --stage-0: var(--deep-0);
  --stage-1: var(--deep-1);
  --stage-ink: var(--deep-ink);

  /* What a day can be marked as. Named here so the four kinds keep the same colour
     everywhere a day turns up - the preferences calendar, the roster header, the rota
     cell, the key - and so recolouring one is one line. */
  --mark-prefernot: var(--warn);
  --mark-night: var(--violet-500);
  --mark-night-ink: var(--violet-400);
  --mark-day: var(--ok);
  --mark-leave: var(--danger);
  /* Days the admin blocked out. Deliberately not one of the four: it is not yours to
     change, so it reads as greyed out rather than as something you asked for, and it
     leaves red to mean leave. */
  --mark-off: var(--ink-3);

  /* How much a service's colour bleeds into a chip's background and edge. */
  --tint: 12%;
  --tint-edge: 30%;

  /* The backdrop behind a dialog, and behind the rail when it is drawn over a phone's
     page - a touch lighter, since the rail covers most of what it dims. */
  --scrim: rgb(var(--scrim-ink) / .55);
  --scrim-soft: rgb(var(--scrim-ink) / .5);

  /* Two people, as a mask: the mark beside a count of colleagues. */
  --people-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='9' cy='8' r='3.5'/%3E%3Cpath d='M2.5 20a6.5 6.5 0 0 1 13 0'/%3E%3Cpath d='M16 4.5a3.5 3.5 0 0 1 0 7M18 14a6 6 0 0 1 3.5 6'/%3E%3C/svg%3E");
}

/* ======================================================= the scales */
:root {
  /* Space. Every padding, margin and gap is one of these, not a number picked for the
     rule in front of it. They had drifted to forty-three spacings, each a pixel off
     its neighbour, which no eye can tell apart and no new rule could follow.

     A 4px grid. The half step is for the inside of small things - a badge, a pip, a
     hairline's clearance - where a whole step is a visible lump. A negative margin
     pulling something into a gutter is written in pixels, still on the grid. */
  --sp-half: 2px;
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  /* Type. Whole pixels, since a half-pixel size renders as one or the other anyway.
     The small end is close-set on purpose: a roster is dense, and the difference
     between a day's number and the label under it is one or two pixels there. The
     splash numerals are artwork, sized where they are drawn. */
  --fs-3xs: 9px;
  --fs-2xs: 10px;
  --fs-xs: 11px;
  --fs-sm: 12px;
  --fs-md: 13px;
  --fs-base: 14px;
  --fs-lg: 16px;
  --fs-xl: 20px;
  --fs-2xl: 24px;
  --fs-3xl: 32px;
  --fs-4xl: 40px;
  --fs-5xl: 52px;

  /* Three weights: text, emphasis, and the heading and figure weight. */
  --fw-medium: 500;
  --fw-semi: 650;
  --fw-bold: 800;

  /* Corners, on the same grid: a pip, a control, a card, a panel, a sheet. */
  --r-xs: 4px;
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 20px;
  --r-pill: 999px;
  --radius: var(--r-lg);
  --radius-sm: var(--r-sm);

  /* Borders: a hairline, and the weight a selected or focused thing is ringed in. */
  --bw: 1px;
  --bw-2: 2px;

  /* Elevation. Three shadows for things that float - a card at rest, something
     lifted under the pointer or open over the page, and a sheet or dialog - made of
     the ink's own colour. The night theme has its own three, further down. */
  --shadow-xs: 0 1px 2px rgb(var(--shadow-ink) / .04);
  --shadow-sm: 0 1px 2px rgb(var(--shadow-ink) / .06), 0 1px 3px rgb(var(--shadow-ink) / .05);
  --shadow-md: 0 8px 24px -8px rgb(var(--shadow-ink) / .18), 0 2px 6px rgb(var(--shadow-ink) / .06);
  --shadow-lg: 0 32px 64px -24px rgb(var(--shadow-ink) / .32), 0 8px 20px -8px rgb(var(--shadow-ink) / .12);
  /* A card standing alone on an empty page - the door, a shared link: one long soft
     shadow under it rather than a sheet's. */
  --shadow-float: 0 24px 48px -32px rgb(var(--shadow-ink) / .35);
  /* A drop shadow for a glyph laid on a fill (filter: drop-shadow), not a box. */
  --drop-sm: drop-shadow(0 1px 1px rgb(0 0 0 / .25));
  --drop-md: drop-shadow(0 1px 2px rgb(0 0 0 / .35));

  /* Glows: a shadow in a colour, under a thing that is that colour - a tile, an
     avatar, the button that ends a step. The offsets only; the rule names the colour,
     as in `box-shadow: var(--glow-md) var(--t)`. */
  --glow-sm: 0 6px 14px -8px;
  --glow-md: 0 10px 24px -14px;
  --glow-lg: 0 16px 32px -18px;
  --glow-xl: 0 18px 48px -24px;
  --glow-soft: 0 0 24px -8px;     /* all round, no direction: a thing lit from inside */
  --halo: 0 2px 10px;
  /* Auras: a glow with no offset at all, for a mark lit from inside (filter:
     drop-shadow, text-shadow) - the build stage's core and its count. */
  --aura-sm: 0 0 6px;
  --aura-lg: 0 0 18px;
  /* The light round the tour's spotlight: spread out past the hole it rings. */
  --spot-glow: 0 0 24px 6px;

  /* Rings and bars: outlines drawn as a shadow, so they take no room and follow the
     corner. The geometry only, the colour from the rule, the way a glow is written:
     `box-shadow: var(--ring-2) var(--accent)`, or `inset var(--ring-1) var(--line)`
     for a ring inside the edge. A bar is a line along one side, always inside. */
  --ring-1: 0 0 0 1px;
  --ring-1h: 0 0 0 1.5px;
  --ring-2: 0 0 0 2px;
  --ring-3: 0 0 0 3px;
  --ring-4: 0 0 0 4px;
  --ring-5: 0 0 0 5px;
  --ring-6: 0 0 0 6px;
  --ring-8: 0 0 0 8px;
  /* As wide as anything could be: the tour's spotlight, dimming all but one hole. */
  --ring-flood: 0 0 0 9999px;
  --bar-start-1: inset 1px 0 0;
  --bar-start-2: inset 2px 0 0;
  --bar-start-3: inset 3px 0 0;
  --bar-start-4: inset 4px 0 0;
  --bar-end-2: inset -2px 0 0;
  --bar-top-2: inset 0 2px 0;
  --bar-bottom-2: inset 0 -2px 0;
  --bar-bottom-3: inset 0 -3px 0;
  /* A bar that is only a sliver of an edge: a 1px line, pulled in from a 3px one. */
  --bar-start-sliver: inset 3px 0 0 -2px;

  /* Layers. Two kinds. Inside a component, a few small steps for what sits over
     what (a hovered chip over its neighbours, a badge over its card). Across the
     page, one named layer per kind of thing that floats, in the order they stack -
     a new floating thing takes a layer from this list, or adds one here, rather
     than picking a number big enough to win today. */
  --z-below: -1;
  --z-flat: 0;
  --z-lift-1: 1;
  --z-lift-2: 2;
  --z-lift-3: 3;
  --z-lift-4: 4;
  --z-lift-5: 5;
  --z-lift-6: 6;
  --z-sticky: 20;       /* a toolbar stuck to the top of what scrolls */
  --z-frame: 39;        /* the frame's rounded corner, just under the bar */
  --z-header: 40;       /* the top bar */
  --z-tip: 40;          /* an inline (i) tip, over its neighbours */
  --z-panel: 45;        /* the shift panel, over the page but under the bar's menus */
  --z-rail-scrim: 54;   /* the page dimmed behind the rail on a phone */
  --z-rail: 55;         /* the rail itself, drawn over the page on a phone */
  --z-bar: 60;          /* a floating action bar at the foot of the screen */
  --z-scrim: 60;        /* the backdrop behind a dialog */
  --z-tooltip: 60;      /* a tooltip that follows the pointer */
  --z-modal: 61;        /* the dialog */
  --z-toast: 80;        /* toasts, above everything a person can be in the middle of */
  --z-tour: 400;        /* the help tour, which is about everything else */

  /* Motion. Durations by what is moving, not by the millisecond; curves by how it
     should feel. The house curve is --ease-out: quick to start, long to settle,
     which is how a thing arriving looks. Durations were thirty different values,
     .14s next to .15s next to .16s; they are eight now and two sets of loops.

       flick     a press: a button going down under the finger
       fast      a colour or an opacity answering the pointer
       base      most transitions: hover, focus, a border lighting up
       moderate  something that moves a short way: a chip lifting, a menu opening
       slow      something that moves across: a panel sliding, a page arriving
       slower    an entrance that wants to be seen
       gentle    a settle, a fade that should not be noticed starting
       linger    the longest a person should ever wait on decoration */
  --dur-flick: .06s;
  --dur-fast: .12s;
  --dur-base: .15s;
  --dur-moderate: .22s;
  --dur-slow: .3s;
  --dur-slower: .42s;
  --dur-gentle: .6s;
  --dur-linger: .9s;
  /* Loops: the period of something that keeps moving - a pulse, a shimmer, a demo
     playing on a settings page. And the three slow drifts of the build stage, whose
     periods are deliberately not multiples of each other, so the pattern never
     visibly repeats. */
  --loop-1: 1.4s;
  --loop-2: 1.8s;
  --loop-3: 2.8s;
  --loop-4: 4s;
  --loop-5: 5s;
  --loop-6: 6s;
  --drift-1: 14s;
  --drift-2: 18s;
  --drift-3: 22s;
  /* Reduced motion: as near nothing as still fires the end event. */
  --dur-none: .01ms;

  --ease-out: cubic-bezier(.2, .8, .3, 1);       /* arriving: the house curve */
  --ease-move: cubic-bezier(.4, 0, .2, 1);       /* going from one place to another */
  --ease-spring: cubic-bezier(.2, 1.4, .4, 1);   /* arriving with a small overshoot */
  --ease-pop: cubic-bezier(.2, .9, .3, 1.2);     /* a pop: a check landing */

  /* Breakpoints. A media query cannot read a custom property, so these are written
     out in each @media and listed here so there is one list to read; the test fails
     on a width that is not one of them, and the JavaScript that asks matchMedia uses
     the same numbers (see BP in core.js).

       --bp-xs    480px   a small phone: one column for everything
       --bp-sm    560px   a phone: forms stack, tiles go two-up
       --bp-md    640px   the phone layout proper: the chrome tightens
       --bp-lg    760px   a small tablet: side-by-side panels stack
       --bp-xl    900px   the swap panel and the shift panel go full-screen
       --bp-rail  1180px  the rail becomes a sheet over the page (min-width: 1181px
                          for the wide layout)
       --bp-wide  1460px  room for a third column */
  --bp-xs: 480px;
  --bp-sm: 560px;
  --bp-md: 640px;
  --bp-lg: 760px;
  --bp-xl: 900px;
  --bp-rail: 1180px;
  --bp-wide: 1460px;

  /* The chrome's fixed measures. The rail, and the width it takes while a shift is
     open in it - tokens rather than two numbers in two rules, because the shift panel
     is laid over the rail and the two have to agree to the pixel. And wider still
     while a swap is being asked for: a list of trades needs more room than one shift. */
  --rail: 258px;
  --rail-wide: 344px;
  --rail-ask: 440px;
  --header-h: 68px;
}

/* ======================================================= 3. component tokens */
:root, [data-theme] {
  /* Controls: buttons, fields, selects and segmented controls line up when they
     share a row, because they share these. */
  --ctl-h-sm: 30px;
  --ctl-h-md: 36px;
  --ctl-h-lg: 44px;
  --ctl-radius: var(--r-md);
  --ctl-bg: var(--surface-2);
  --ctl-line: var(--line);
  /* Icons: a glyph in a pill, in a button, in a heading, in a chip. */
  --icon-xs: 14px;
  --icon-sm: 16px;
  --icon-md: 18px;
  --icon-lg: 20px;
  --icon-xl: 24px;
  /* Focus. The ring a focused field wears, and the outline a focused thing that is not
     a field wears - the outline for anything reached by the keyboard. */
  --focus-ring: var(--ring-3) color-mix(in srgb, var(--accent) 22%, transparent);
  --focus-outline: var(--bw-2) solid var(--accent);
  /* Surfaces a component sits on. */
  --card-bg: var(--surface);
  --card-line: var(--line);
  --card-radius: var(--radius);
  --panel-bg: var(--surface-2);
  --panel-line: var(--line-soft);
  /* The logo on the page: printed on by day (multiply drops its white), knocked out
     to white by night. */
  --logo-blend: multiply;
  --logo-filter: none;
  /* The door: the blue the pages before the gate wear across their heads - an
     invitation, an approval from an email - running from the day accent into the
     night one and on to indigo. */
  --door-a: var(--blue-600);
  --door-b: var(--blue-400);
  --door-c: var(--hue-indigo);
  --door-ink: var(--on-fill);
  --door-text: var(--blue-600);
}

/* ======================================================= the night theme
   Last, so it wins over everything above it on the same element. The night theme is a re-pointing of the semantic tokens and nothing else. It is set
   by data-theme on <html>: app.js puts it there from the reader's choice, or from the
   system's when they have made none, and the pages before the gate do the same from
   the same stored choice (see the small script at the head of each). */
[data-theme="dark"] {
  --bg: var(--night-900);
  --bg-deep: var(--night-950);
  --surface: var(--night-850);
  --surface-2: var(--night-800);
  --surface-3: var(--night-725);
  --line: var(--night-700);
  --line-soft: var(--night-750);
  --ink: var(--night-50);
  --ink-2: var(--night-200);
  --ink-3: var(--night-500);
  --accent: var(--blue-400);
  --accent-ink: var(--blue-975);
  --accent-soft: var(--blue-900);
  --on-state: var(--night-950);
  --ask-text: var(--gold-ask-text-night);
  --danger: var(--red-400);
  --warn: var(--amber-300);
  --ok: var(--green-300);
  --open: var(--gold-open);
  --open-edge: var(--gold-open-edge-night);
  --open-ink: var(--gold-open-ink-night);
  --swap: var(--gold-swap-night);
  --swap-edge: var(--gold-swap-edge-night);
  --swap-ink: var(--gold-swap-ink-night);
  /* Night's shadows are deeper and blacker rather than the day's re-coloured: on a
     dark page a soft blue-black shadow does not show at all. */
  --shadow-sm: 0 1px 2px rgb(0 0 0 / .5);
  --shadow-md: 0 12px 28px -12px rgb(0 0 0 / .7);
  --shadow-lg: 0 40px 80px -32px rgb(0 0 0 / .85);
  --shadow-float: 0 24px 48px -32px rgb(0 0 0 / .7);
  --tint: 20%;
  --tint-edge: 45%;
  --logo-blend: screen;
  --logo-filter: invert(1) grayscale(1) brightness(2.4);
  --door-text: var(--blue-300);
}

/* The browser's own parts - scrollbars above all, which Firefox draws itself - follow
   the theme. Nothing said which scheme the page was in, so a dark page had pale
   scrollbars down the edge of the rail and the calendar. */
:root { color-scheme: light; scrollbar-color: color-mix(in srgb, var(--ink-3) 40%, transparent) transparent; }
[data-theme="light"] { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }

/* ======================================================= print
   A printer has no theme. Left alone it takes the dark palette's pale ink and lays it
   on white paper, and the sheet comes out blank. */
@media print {
  :root, [data-theme="dark"], [data-theme="light"] {
    --bg: #ffffff; --bg-deep: #ffffff; --surface: #ffffff;
    --surface-2: #f6f8fc; --surface-3: #eef2f9;
    --line: #c8d0e0; --line-soft: #dfe5f0;
    --ink: #0d1424; --ink-2: #3c4664; --ink-3: #5c6680;
    --accent: #1f47cc; --accent-soft: #e5ecff;
    --danger: #b42318; --warn: #8a4700; --ok: #05603a; --swap: #5b21b6;
    --open: #ffc400; --open-edge: #c98a00; --open-ink: #3d2800;
  }
}
