/// Susy3 API Functions
/// ===================
/// These three functions form the core of Susy's
/// layout-building grid API.
///
/// - Use `span()` and `gutter()` to return any grid-width,
///   and apply the results wherever you need them:
///   CSS `width`, `margin`, `padding`, `flex-basis`, `transform`, etc.
/// - For asymmetrical-fluid grids,
///   `slice()` can help manage your nesting context.
///
/// All three functions come with an unprefixed alias by default,
/// using the `susy` import.
/// Import the `susy-prefix` partial instead,
/// if you only only want prefixed versions of the API.
///
/// This is a thin syntax-sugar shell around
/// the "Su" core-math functions: `su-span`, `su-gutter`, and `su-slice`.
/// If you prefer the more constrained syntax of the math engine,
/// you are welcome to use those functions instead.
///
/// @group b-api
/// @see susy-span
/// @see susy-gutter
/// @see susy-slice
/// @see su-span
/// @see su-gutter
/// @see su-slice



/// ## Shorthand
///
/// All functions draw on the same shorthand syntax in two parts,
/// seperated by the word `of`.
///
/// ### Span Syntax: `<width>` [`<location>` `<spread>`]
/// The first part describes the
/// **span** width, location, and spread in any order.
/// Only the width is required:
///
/// - `span(2)` will return the width of 2 columns.
/// - `span(3 wide)` will return 3-columns, with an additional gutter.
/// - location is only needed with asymmetrical grids,
///   where `span(3 at 2)` will return the width of
///   specific columns on the grid.
///   Since these are functions, they will not handle placement for you.
///
/// ### Context Syntax: `[of <columns> <container-spread> <gutters>]`
/// The second half of Susy's shorthand
/// describes the grid-**context** –
/// available columns, container-spread, and optional gutter override –
/// in any order.
/// All of these settings have globally-defined defaults:
///
/// - `span(2 of 6)` will set the context to
///   a slice of 6 columns from the global grid.
///   More details below.
/// - `span(2 of 12 wide)` changes the container-spread
///   as well as the column-context.
/// - `span(2 of 12 set-gutters 0.5em)`
///   will override the global gutters setting
///   for this one calculation.
///
/// A single unitless number for `columns`
/// will be treated as a slice of the parent grid.
/// On a grid with `columns: susy-repeat(12, 120px)`,
/// the shorthand `of 4` will use the parent `120px` column-width.
/// You can also be more explicit,
/// and say `of susy-repeat(4, 100px)`.
/// If you are using asymmetrical grids,
/// like `columns: (1 1 2 3 5 8)`,
/// Susy can't slice it for you without knowing which columns you want.
/// The `slice` function accepts exactly the same syntax as `span`,
/// but returns a list of columns rather than a width.
/// Use it in your context like `of slice(first 3)`.
///
/// @group b-api



// Susy Span
// ---------
/// This is the primary function in Susy —
/// used to return the width of a span across one or more columns,
/// and any relevant gutters along the way.
/// With the default settings,
/// `span(3)` will return the width of 3 columns,
/// and the 2 intermediate gutters.
/// This can be used to set the `width` property of grid elements,
/// or `margin` and `padding`
/// to push, pull, and pad your elements.
///
/// - This is a thin syntax-sugar shell around
///   the core-math `su-span()` function.
/// - The un-prefixed alias `span()` is available by default.
///
/// @group b-api
/// @see su-span
/// @see $susy
///
/// @param {list} $span -
///   Shorthand expression to define the width of the span,
///   optionally containing:
///   - a count, length, or column-list span.
///   - `at $n`, `first`, or `last` location on asymmetrical grids,
///     where `at 1 == first`,
///     and `last` will calculate the proper location
///     based on columns and span.
///   - `narrow`, `wide`, or `wider` for optionally spreading
///     across adjacent gutters.
///   - `of $n <spread>` for available grid columns
///     and spread of the container.
///     Span counts like `of 6` are valid
///     in the context of symmetrical grids,
///     where Susy can safely infer a slice of the parent columns.
///   - and `set-gutters $n` to override global gutter settings.
///
/// @param {map} $config [()] -
///   Optional map of Susy grid configuration settings.
///   See `$susy` documentation for details.
///
/// @return {length} -
///   Calculated length value, using the units given,
///   or converting to `%` for fraction-based grids,
///   or a full `calc` function when units/fractions
///   are not comparable outside the browser.
///
/// @example scss - span half the grid
///   .foo {
///     // the result is a bit under 50% to account for gutters
///     width: susy-span(6 of 12);
///   }
///
/// @example scss - span a specific segment of asymmetrical grid
///   .foo {
///     width: susy-span(3 at 3 of (1 2 3 5 8));
///   }
@function susy-span(
  $span,
  $config: ()
) {
  $output: susy-compile($span, $config);

  @if map-get($output, 'span') {
    @return su-call('su-span', $output);
  }

  $actual: '[#{type-of($span)}] `#{inspect($span)}`';
  @return _susy-error(
    'Unable to determine span value from #{$actual}.',
    'susy-span');
}



// Susy Gutter
// -----------
/// The gutter function returns
/// the width of a single gutter on your grid,
/// to be applied where you see fit –
/// on `margins`, `padding`, `transform`, or element `width`.
///
/// - This is a thin syntax-sugar shell around
///   the core-math `su-gutter()` function.
/// - The un-prefixed alias `gutter()` is available by default.
///
/// @group b-api
/// @see su-gutter
/// @see $susy
///
/// @param {list | number} $context [null] -
///   Optional context for nested gutters,
///   including shorthand for
///   `columns`, `gutters`, and `container-spread`
///   (additional shorthand will be ignored)
///
/// @param {map} $config [()] -
///   Optional map of Susy grid configuration settings.
///   See `$susy` documentation for details.
///
/// @return {length} -
///   Width of a gutter as `%` of current context,
///   or in the units defined by `column-width` when available
///
/// @example scss - add gutters before or after an element
///   .floats {
///     float: left;
///     width: span(3 of 6);
///     margin-left: gutter(of 6);
///   }
///
/// @example scss - add gutters to padding
///   .flexbox {
///     flex: 1 1 span(3 wide of 6 wide);
///     padding: gutter(of 6) / 2;
///   }
///
@function susy-gutter(
  $context: susy-get('columns'),
  $config: ()
) {
  $context: susy-compile($context, $config, 'context-only');

  @return su-call('su-gutter', $context);
}



// Susy Slice
// ----------
/// Working with asymmetrical grids (un-equal column widths)
/// can be challenging – 
/// expecially when they involve fluid/fractional elements.
/// Describing a context `of (15em 6em 6em 6em 15em)` is a lot
/// to put inside the span or gutter function shorthand.
/// This slice function returns a sub-slice of asymmetrical columns to use
/// for a nested context.
/// `slice(3 at 2)` will give you a subset of the global grid,
/// spanning 3 columns, starting with the second.
///
/// - This is a thin syntax-sugar shell around
///   the core-math `su-slice()` function.
/// - The un-prefixed alias `slice()` is available by default.
///
/// @group b-api
/// @see su-slice
/// @see $susy
///
/// @param {list} $span -
///   Shorthand expression to define the subset span, optionally containing:
///   - `at $n`, `first`, or `last` location on asymmetrical grids;
///   - `of $n <spread>` for available grid columns
///     and spread of the container
///     - Span-counts like `of 6` are only valid
///       in the context of symmetrical grids
///     - Valid spreads include `narrow`, `wide`, or `wider`
///
/// @param {map} $config [()] -
///   Optional map of Susy grid configuration settings.
///   See `$susy` documentation for details.
///
/// @return {list} -
///   Subset list of columns for use for a nested context
///
/// @example scss - Return a nested segment of asymmetrical grid
///   $context: susy-slice(3 at 3 of (1 2 3 5 8));
///   /* $context: #{$context}; */
@function susy-slice(
  $span,
  $config: ()
) {
  $span: susy-compile($span, $config);

  @return su-call('su-slice', $span);
}



/// ## Building Grids
/// The web has come a long way
/// since the days of double-margin-hacks
/// and inconsistent subpixel rounding.
/// In addition to floats and tables,
/// we can now use much more powerful tools,
/// like flexbox and CSS grid,
/// to build more interesting and responsive layouts.
///
/// With Susy3, we hope you'll start moving in that direction.
/// You can still build classic 12-column Grid Systems,
/// and we'll help you get there,
/// but Susy3 is primarily designed for a grid-math-on-demand
/// approach to layout:
/// applying our functions only where you really need grid math.
/// Read the [intro article by OddBird][welcome] for more details.
///
/// [welcome]: http://oddbird.net/2017/06/28/susy3/
///
/// @group b-api
/// @link http://oddbird.net/2017/06/28/susy3/ Article: Welcome to Susy3
///
/// @example scss - floats
///   .float {
///     width: span(3);
///     margin-right: gutter();
///   }
///
/// @example scss - flexbox
///   .flexbox {
///     flex: 1 1 span(3);
///     // half a gutter on either side…
///     padding: 0 gutter() / 2;
///   }
///
/// @example scss - pushing and pulling
///   .push-3 {
///     margin-left: span(3 wide);
///   }
///
///   .pull-3 {
///     margin-left: 0 - span(3 wide);
///   }
///
/// @example scss - building an attribute system
///   // markup example: <div data-span="last 3"></div>
///   [data-span] {
///     float: left;
///
///     &:not([data-span*='last']) {
///       margin-right: gutter();
///     }
///   }
///
///   @for $span from 1 through length(susy-get('columns')) {
///     [data-span*='#{$span}'] {
///       width: span($span);
///     }
///   }
