/* The token layer. Every colour, radius, space and weight in the app resolves
   to a variable defined in this file, and nowhere else.

   WHY A TOKEN FILE AND NOT JUST CSS
   Dark mode is not a feature you add later. A hex literal written into a rule
   is a value that cannot be re-themed, so the day dark mode arrives every one
   of them has to be hunted down - and the ones that get missed are the ones
   nobody looks at, which on this app means a red failure indicator that turns
   invisible on a dark card. Tokens from day one costs nothing now and makes
   the theme a two-block change forever after.

   THE RULES THIS FILE EXISTS TO ENFORCE
   - No hex literal lives outside this file. tests/test_design_system.py fails
     the build if one does.
   - Three font weights: 400, 500, and 600 for headings, labels and buttons
     only (D-045). A NUMBER is never heavier than 500: a figure set heavy
     reads as an alarm, and on a page where most numbers are fine that is a
     lie.
   - Semantic names only. `--danger`, never `--red`.
   - Tabular figures on every number, so a column of dollars lines up.
   - Hairline borders. A 1px border at 2x is a heavy line; 0.5px is the line a
     printed statement has.
   - No box-shadows. Depth comes from the border and the bg/surface contrast.
     The canvas draws a faint shadow under the active rail item; it is
     rendered here as a hairline border instead, and nothing is lost.

   THREE THEME STATES, and the middle one is the one people forget:
     :root                                   -> light, always defined
     prefers-color-scheme: dark (no override) -> dark by system setting
     [data-theme="dark"] / [data-theme="light"] -> an explicit choice wins
   A colour whose only definition sits inside a media query has no value at
   all in the state that query does not match.

   ------------------------------------------------------------------------
   THREE PLACES THIS FILE DOES NOT MATCH THE BRIEF, AND WHY

   The brief said: if the tokens fight the images, follow the images and say
   which token was overridden. The screenshots did not arrive, so the written
   tokens are the only source and they are followed exactly - except where a
   value would break something that already works. Those three:

   1. --t-input stays 16px. The brief sets body to 13px, which is right for a
      data tool, but a FORM CONTROL under 16px makes mobile Safari zoom the
      page on focus. The brief also says the phone must work for upload and
      review, and both are forms. So body is 13px as specified and inputs
      alone hold 16px.

   2. The allocation hues survive. The brief says one accent per screen, and
      it is right, but Business / Personal / Transfer are three answers to one
      question and have to be told apart at a glance without reading as a
      ranking. They are categorical, not accent: the accent stays reserved for
      the primary action on each screen.

   3. Inter IS NOW SERVED, from static/fonts (D-044). The note below described
      the old state, where it was requested first in the stack and never
      fetched. Kept because the reasoning for not using a CDN is unchanged and
      is why the files are vendored: loading it from a font CDN adds a
      third-party request to a page showing bank data. Two latin subsets, 400
      and 500, 44 KB together, committed to the repo - no build step, which
      is what the old note was protecting and is still true.
   ------------------------------------------------------------------------ */

/* ===================================================================== D-036
   THREE DELIBERATE DEPARTURES FROM THE WRITTEN SPEC, each with its reason,
   each agreed with the owner before it was built. They are recorded here
   rather than in a commit message because this is the file somebody reads
   when they wonder why the value is not what the spec says.

   1. FONT WEIGHTS STAY 400 AND 500. The spec says 600. At 13px in a dense
      financial table 600 reads as emphasis on everything, which is emphasis
      on nothing - and a number set heavy reads as an alarm, which on a page
      where most numbers are fine is a lie. tests/test_design_system.py pins
      400/500 and that test stays.

   2. --t-input STAYS 16px. Mobile Safari zooms the viewport when a field
      smaller than 16px takes focus, and the phone is this app's upload
      surface. A 15px input is a page that jumps every time somebody taps a
      filter.

   3. ROW HEIGHT 44px, 52px ON A COARSE POINTER. The spec's 40-44px range,
      taken at the top: 40px is a comfortable row for a mouse and a cramped
      one for a thumb, and the media query is on the POINTER rather than the
      viewport - a small desktop window still has a mouse and a large tablet
      still has a thumb.

   COLOUR IS MEANING, AND THIS IS NOW A RULE RATHER THAN A PREFERENCE.
   --positive is for something financially good that ACTUALLY HAPPENED: debt
   paid down, interest saved, income received. It is never for "this screen
   loaded correctly" and never for "there is nothing here". Five empty states
   in this app used to render as green success cards, which congratulated the
   owner for a screen where the app had done nothing and he had work to do.
   An empty state is a muted sentence (.empty). Green is earned.
*/

/* ===================================================== Geist, SELF-HOSTED
   (D-044, amended by D-045)
   The canvas design (docs/design/canvas/) is set in Geist, with Geist Mono
   for figures. Inter was the face before it, and the reasoning that got
   Inter served still holds word for word: NOT a font CDN, because a page
   showing bank data must not announce itself to a third party on every
   load, and a CDN is a dependency that can be slow, blocked or gone.

   VARIABLE, NOT ONE FILE PER WEIGHT - and that reverses the old note here.
   The canvas uses 400, 500 and 600. Three static Geist weights plus two Mono
   weights come to about 123 KB; the two variable latin subsets carry every
   weight in 52 KB together - smaller than the two static Inter files they
   replace (44 KB for only two weights). The brief's budget was ~120 KB.
   The font-weight RANGE in each face is what tells the browser not to fake
   a bold.

   Licence: SIL Open Font License 1.1, shipped beside the files as
   geist.LICENSE (tests/test_design_system.py checks it is there).

   font-display: swap, so the text is readable in the system font from the
   first paint and reflows once, rather than a blank page while a font
   downloads - on a screen whose job is showing somebody their own money. */
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/geist-latin-wght.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/geist-mono-latin-wght.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+FEFF, U+FFFD;
}

:root {
  /* ------------------------------------------------------------- surfaces
     Warm off-white, never pure white: a page of white cards on a white page
     has no structure, and pure white next to a dense table is glare. */
  --bg:              #F2F2F0;   /* the canvas's warm neutral ground */
  --surface:         #FFFFFF;
  --surface-alt:     #F5F5F3;   /* table header, hover, inset rows */
  --surface-inverse: #141414;

  /* ----------------------------------------------------------------- text */
  --text:            #141414;
  /* MEASURED, NOT CHOSEN (D-039). Both of these clear 4.5:1 against the
     worst surface they land on (--surface-alt), with a margin so rounding
     cannot put them back on the line. --text-faint was #9a9a94 and measured
     2.57:1 - which is what rendered .foot, the line where this product says
     what it does not know, almost invisible. */
  --text-muted:      #6A6A66;   /* labels, secondary lines, empty states */
  --text-faint:      #6A6A66;   /* timestamps, hints, placeholder */
  --text-inverse:    #FFFFFF;

  /* -------------------------------------------------------------- borders */
  --border:          #E6E6E3;

  /* ------------------------------------------------------------------ rail
     THE RAIL NOW THEMES (D-045). It was fixed dark chrome in both modes
     (D-036); the canvas rail is a quiet warm grey one step darker than the
     page, so it has a dark value like every other surface and the
     UNTHEMED_BY_DESIGN allowlist in tests/test_design_system.py is empty. */
  --rail:            #FFFFFF;
  --rail-text:       #141414;
  --rail-text-muted: #4A4A48;
  --rail-hover:      #F2F2F0;
  --rail-active:     #F2F2F0;
  --rail-border:     #F2F2F0;

  /* Text on a saturated status FILL.
     THIS USED TO BE WHITE IN BOTH THEMES, and the comment here said so
     confidently: "--danger and --positive are saturated in both and white is
     legible on both". Measured, that is false. The dark palette lightens both
     fills, so white on them comes out at 3.26:1 and 2.24:1 - the second being
     the worst contrast anywhere in the app.
     It is now themed: white on the light fills, near-black ink on the dark
     ones. Removed from UNTHEMED_BY_DESIGN accordingly (D-039). */
  --on-status:       #FFFFFF;
  --border-strong:   #D6D6D2;
  --border-focus:    #1F5A48;

  /* ---------------------------------------------------------------- accent
     ONE brand colour. Deep green. If two things on a screen are both this
     colour, one of them is wrong. */
  --accent:          #1F5A48;
  --accent-hover:    #153F32;
  --accent-soft:     #E4EEEA;
  --accent-text:     #FFFFFF;

  /* ------------------------------------------------- semantic status only
     Named for what it MEANS, never for what colour it happens to be. */
  --danger:          #8A2E1F;   /* money out, problems */
  --danger-bg:       #F7E9E6;
  --danger-border:   #EBCFC9;

  --positive:        #1F5A48;   /* paid off, saved - NOT every credit */
  --positive-bg:     #E4EEEA;
  --positive-border: #CBDDD6;

  --warn:            #875800;   /* estimated, partial - solved for 4.5:1 on the warmer --surface-alt (D-045) */
  --warn-bg:         #FBF3E4;
  --warn-border:     #EBDDBE;

  --info:            #1F5A48;
  --info-bg:         #E4EEEA;
  --info-border:     #CBDDD6;

  --neutral:         #5E5E5A;
  --neutral-bg:      #F2F2F0;
  --neutral-border:  #E6E6E3;

  /* ------------------------------------------------------ allocation hues
     Categorical, not accent. See note 2 at the top of this file. */
  --business:        #1F5A48;
  --business-bg:     #E4EEEA;
  --personal:        #6a4a86;
  --personal-bg:     #f0ebf5;
  --transfer:        #5E5E5A;
  --transfer-bg:     #F2F2F0;


  /* ------------------------------------------------ the canvas additions
     D-045. Every value below was measured against the surface it sits on,
     in all three theme states, by tests/test_contrast.py - not chosen by
     eye (D-039). */

  /* Secondary text: rail links, sentences under a heading. Between --text
     and --text-muted. */
  --text-secondary:  #4A4A48;
  /* The hairline between rows inside a card: lighter than --border, which
     stays the card's own edge. */
  --divider:         #F0F0EE;

  /* Text on --accent-soft (a selected choice, the Reconciled badge), and
     the quieter line on a solid --accent card. */
  --accent-soft-text: #153F32;
  --on-accent-muted: #CFE3DC;

  /* NEEDS YOU. The canvas's one amber, for "a person has to answer this" and
     NOTHING ELSE - the Home banner, the rail count, the Needs-you badge, a
     missing receipt. If something else on a screen is this colour, one of
     them is wrong. --warn stays its own token for estimated and partial,
     which are states of a number, not requests for a person. */
  --needs:           #8A4B0F;   /* the count dot, the "?" in a row */
  --needs-bg:        #FBEEDD;   /* the banner, the badge */
  --needs-text:      #6B3A0C;   /* text on --needs-bg */
  --needs-row-bg:    #FFFBF5;   /* a table row that needs you */
  --on-needs:        #FFFFFF;   /* text on the solid --needs fill */

  /* AI-READ. Blue, for a figure a machine read rather than code that tied
     it to a printed total. This is the existing `extracted` state
     (D-035/D-037) given the canvas's visual; it is not a new state. */
  --ai:              #1C3A85;
  --ai-bg:           #E6ECFA;

  /* Chart marks. In = the accent; out = a warm neutral that is visibly a
     different series without shouting. */
  --chart-in:        #1F5A48;
  --chart-out:       #8C8C88;
  --chart-axis:      #E6E6E3;


  /* ------------------------------------------------ direction B (D-061)
     The values the canvas-b README names, plus what it needed and did not
     name. Measured, never chosen (D-039): tests/test_contrast.py solves
     every pair in all three theme states. */

  /* The one black primary button per screen, and the text on it. */
  --primary:         #141414;
  --primary-hover:   #33332F;
  --on-primary:      #FFFFFF;
  /* Segmented controls: a grey track, a white selected pill. */
  --track:           #E6E6E3;
  --track-on:        #FFFFFF;
  /* The inset block inside a card: the drill-down's "the math". */
  --inset:           #F7F7F5;
  /* A card's own edge. Invisible in light, where the soft shadow carries
     the edge; a hairline in dark, where a shadow on a dark ground is
     invisible anyway. */
  --card-edge:       #FFFFFF;
  /* The past months on the chart, lighter than the current one. Solid
     tokens rather than opacity, so nothing composites unmeasured. */
  --chart-in-past:   #C3D6CF;
  --chart-out-past:  #E4E4E1;
  /* Interest cost may use a muted red (canvas-b README). */
  --cost:            #8A2E1F;
  /* The dark "this month's move" panel on Debt & cards (BDebt, D-071): the
     --primary fill, a raised block inside it, quieter text and the green
     for a saving. Solved for 4.5:1 against both fills in every theme; in
     dark mode the panel inverts with --primary, so these invert too. */
  --panel-raised:    #262624;
  --on-panel-muted:  #B4B4AE;
  --on-panel-accent: #7FD1A8;

  /* SHADOWS. Direction B draws a soft card shadow; D-036 said flat. The
     owner approved B (D-061), so three shadows exist - as tokens, so the
     design test can pin that they are these and nothing heavier. */
  --shadow-card:     0 1px 3px rgba(0, 0, 0, 0.05);
  --shadow-pill:     0 1px 2px rgba(0, 0, 0, 0.08);
  --shadow-float:    0 20px 60px rgba(0, 0, 0, 0.18);

  /* ------------------------------------------------------------- overlays
     FLAT. No shadows anywhere. A scrim is not depth, so it stays. */
  --scrim:           rgba(20, 20, 20, 0.22);
  --drop-active-bg:  #E4EEEA;

  /* ------------------------------------------------------------ structure */
  --r-card:          22px;
  --r-input:         12px;
  --r-panel:         24px;   /* the floating drill-down panel */
  --r-inner:         16px;   /* a block inside a card */
  --r-seg:           9px;    /* the selected pill inside a segmented track */
  --r-pill:          999px;
  --hairline:        0.5px;

  --s1:              4px;
  --s2:              8px;
  --s3:              12px;
  --s4:              16px;
  --s5:              24px;
  --s6:              32px;
  --s7:              48px;

  /* Table rows: dense at a desk, thumb-sized on a phone. */
  --row-h:           44px;
  --row-h-touch:     52px;
  --tap:             44px;
  --content-max:     1180px;
  --reading-max:     680px;

  /* ----------------------------------------------------------- typography
     One family. Inter if the reader has it, the system stack otherwise -
     see note 3 at the top of this file. */
  --font-sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  /* Figures. The canvas sets every amount in Geist Mono, which is tabular
     by construction - digits the same width whatever the font does. */
  --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
               Consolas, "Liberation Mono", monospace;

  /* Two weights. There is no --weight-bold, deliberately: emphasis comes
     from size, colour and space, which stay legible at every zoom level. */
  --weight-normal:   400;
  --weight-medium:   500;
  /* A THIRD WEIGHT, and D-036 said there would never be one. The owner
     approved the canvas, which sets headings, the active nav item and
     primary buttons at 600 (docs/design/CANVAS_BRIEF.md). The D-036 argument
     is kept where it applies: numbers are NEVER 600 - a figure set heavy
     reads as an alarm - and the test pins that 600 is used for headings,
     labels and buttons only. D-045. */
  --weight-strong:   600;

  /* Body is 14px. This is a data tool, not a landing page - but 13px was a
     point tighter than the density actually needs, and the measured
     difference in readability was worth the row it costs (D-044). The rest of
     the scale moves with it so the relationships hold. */
  --t-xs:            12px;
  --t-sm:            13px;
  --t-base:          14px;
  --t-lg:            15px;
  --t-xl:            20px;
  --t-2xl:           28px;
  --t-3xl:           32px;   /* the page heading on the canvas */
  --t-input:         16px;   /* the one override - see note 1 */

  --lh-xs:           16px;
  --lh-sm:           18px;
  --lh-base:         20px;
  --lh-lg:           22px;
  --lh-xl:           28px;
  --lh-2xl:          34px;
  --lh-3xl:          38px;

  --line-tight:      1.2;
  --line-body:       1.5;

  /* --------------------------------------------------- compatibility layer
     The names app.css grew up with, mapped onto the ones above. They are
     aliases, not a second palette: every one resolves to a token declared in
     this block, so there is still exactly one place a colour is chosen.

     Kept rather than renamed in one pass because a find-and-replace across
     500 lines of stylesheet and 27 templates is a change nobody can review -
     and a review nobody can do is how a colour quietly goes wrong. New rules
     use the names above; these retire as app.css is converted. */
  --surface-sunken:  var(--surface-alt);
  --surface-hover:   var(--surface-alt);
  --text-subtle:     var(--text-faint);
  --accent-subtle:   var(--accent-soft);
  --success:         var(--positive);
  --success-bg:      var(--positive-bg);
  --success-border:  var(--positive-border);
  --warning:         var(--warn);
  --warning-bg:      var(--warn-bg);
  --warning-border:  var(--warn-border);

  --radius:          var(--r-card);
  --radius-sm:       var(--r-input);
  --radius-pill:     var(--r-pill);

  --space-1:         var(--s1);
  --space-2:         var(--s2);
  --space-3:         var(--s3);
  --space-4:         var(--s4);
  --space-5:         var(--s5);
  --space-6:         var(--s6);
  --space-7:         var(--s7);

  --size-display:    var(--t-2xl);
  --size-title:      var(--t-xl);
  --size-heading:    var(--t-lg);
  --size-body:       var(--t-base);
  --size-input:      var(--t-input);
  --size-small:      var(--t-sm);
  --size-micro:      var(--t-xs);
}

/* ---------------------------------------------------------------- dark, by
   system setting. Guarded with :not([data-theme="light"]) so an explicit
   light choice still wins here. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:              #141413;
    --surface:         #1E1E1C;
    --surface-alt:     #262624;
    --surface-inverse: #F2F2F0;

    --text:            #F2F2F0;
    --text-muted:      #A8A8A2;
    --text-faint:      #A0A09A;
    --text-inverse:    #141413;

    --border:          #33332F;
    --border-strong:   #45453F;
    --border-focus:    #5DB39B;

    --rail:            #1E1E1C;
    --rail-text:       #F2F2F0;
    --rail-text-muted: #C4C4BE;
    --rail-hover:      #2A2A27;
    --rail-active:     #2A2A27;
    --rail-border:     #2A2A27;

    --accent:          #5DB39B;
    --accent-hover:    #7CC4AF;
    --accent-soft:     #1A3B32;
    --accent-text:     #121214;

    /* Dark fills are LIGHT, so their text is ink, not white. See the note
       in :root. */
    --on-status:       #121214;

    --danger:          #E39484;
    --danger-bg:       #35211D;
    --danger-border:   #50302A;

    --positive:        #5fbf95;
    --positive-bg:     #16302a;
    --positive-border: #234a3d;

    --warn:            #d9a441;
    --warn-bg:         #322817;
    --warn-border:     #4d3f22;

    --info:            #5DB39B;
    --info-bg:         #1A3B32;
    --info-border:     #234a3d;

    --neutral:         #a0a09a;
    --neutral-bg:      #282723;
    --neutral-border:  #34322D;

    --business:        #5DB39B;
    --business-bg:     #1A3B32;
    --personal:        #a98cc9;
    --personal-bg:     #2a2333;
    --transfer:        #a0a09a;
    --transfer-bg:     #282723;

    --text-secondary:  #CFCFCA;
    --divider:         #2A2A27;
    --accent-soft-text: #CBE8DE;
    --on-accent-muted: #1B3A31;

    --needs:           #E0A060;
    --needs-bg:        #3A2A18;
    --needs-text:      #F2C58F;
    --needs-row-bg:    #221C14;
    --on-needs:        #1A1208;

    --ai:              #A9BEF5;
    --ai-bg:           #1E2740;

    --chart-in:        #5DB39B;
    --chart-out:       #8C8C88;
    --chart-axis:      #33332F;

    --scrim:           rgba(0, 0, 0, 0.6);
    --drop-active-bg:  #1A3B32;
    --primary:         #F2F2F0;
    --primary-hover:   #FFFFFF;
    --on-primary:      #141413;
    --track:           #2A2A27;
    --track-on:        #3A3A36;
    --inset:           #232321;
    --card-edge:       #2E2E2B;
    --chart-in-past:   #2C4A41;
    --chart-out-past:  #3A3A36;
    --cost:            #E39484;
    --panel-raised:    #E6E6E3;
    --on-panel-muted:  #55554F;
    --on-panel-accent: #1F5A48;
    --shadow-card:     none;
    --shadow-pill:     none;
    --shadow-float:    0 20px 60px rgba(0, 0, 0, 0.5);
  }
}

/* --------------------------------------------------------- dark, by choice.
   The same block again, unguarded, so the toggle wins in both directions.
   Identical to the media-query values by design - tests/test_design_system.py
   asserts the two are the same, because a toggle that produces a slightly
   different dark mode from the system setting is a bug nobody can see. */
:root[data-theme="dark"] {
  --bg:              #141413;
  --surface:         #1E1E1C;
  --surface-alt:     #262624;
  --surface-inverse: #F2F2F0;

  --text:            #F2F2F0;
  --text-muted:      #A8A8A2;
  --text-faint:      #A0A09A;
  --text-inverse:    #141413;

  --border:          #33332F;
  --border-strong:   #45453F;
  --border-focus:    #5DB39B;

  --rail:            #1E1E1C;
  --rail-text:       #F2F2F0;
  --rail-text-muted: #C4C4BE;
  --rail-hover:      #2A2A27;
  --rail-active:     #2A2A27;
  --rail-border:     #2A2A27;

  --accent:          #5DB39B;
  --accent-hover:    #7CC4AF;
  --accent-soft:     #1A3B32;
  --accent-text:     #121214;

  /* Dark fills are LIGHT, so their text is ink, not white. See the note
     in :root. */
  --on-status:       #121214;

  --danger:          #E39484;
  --danger-bg:       #35211D;
  --danger-border:   #50302A;

  --positive:        #5fbf95;
  --positive-bg:     #16302a;
  --positive-border: #234a3d;

  --warn:            #d9a441;
  --warn-bg:         #322817;
  --warn-border:     #4d3f22;

  --info:            #5DB39B;
  --info-bg:         #1A3B32;
  --info-border:     #234a3d;

  --neutral:         #a0a09a;
  --neutral-bg:      #282723;
  --neutral-border:  #34322D;

  --business:        #5DB39B;
  --business-bg:     #1A3B32;
  --personal:        #a98cc9;
  --personal-bg:     #2a2333;
  --transfer:        #a0a09a;
  --transfer-bg:     #282723;

  --text-secondary:  #CFCFCA;
  --divider:         #2A2A27;
  --accent-soft-text: #CBE8DE;
  --on-accent-muted: #1B3A31;

  --needs:           #E0A060;
  --needs-bg:        #3A2A18;
  --needs-text:      #F2C58F;
  --needs-row-bg:    #221C14;
  --on-needs:        #1A1208;

  --ai:              #A9BEF5;
  --ai-bg:           #1E2740;

  --chart-in:        #5DB39B;
  --chart-out:       #8C8C88;
  --chart-axis:      #33332F;

  --scrim:           rgba(0, 0, 0, 0.6);
  --drop-active-bg:  #1A3B32;
  --primary:         #F2F2F0;
  --primary-hover:   #FFFFFF;
  --on-primary:      #141413;
  --track:           #2A2A27;
  --track-on:        #3A3A36;
  --inset:           #232321;
  --card-edge:       #2E2E2B;
  --chart-in-past:   #2C4A41;
  --chart-out-past:  #3A3A36;
  --cost:            #E39484;
  --panel-raised:    #E6E6E3;
  --on-panel-muted:  #55554F;
  --on-panel-accent: #1F5A48;
  --shadow-card:     none;
  --shadow-pill:     none;
  --shadow-float:    0 20px 60px rgba(0, 0, 0, 0.5);
}
