@use 'sass:math';
@use '../../compiled/tokens/scss/breakpoint';
@use '../../compiled/tokens/scss/color';
@use '../../compiled/tokens/scss/size';
@use '../../mixins/fluid';
@use '../../mixins/spacing';

/// Setting the breakpoint to `m` (40em) results in an awkward layout
/// when using the Subscribe form in the `extra` slot. However, setting
/// the breakpoint to `l` (60em) results in the transition happening too
/// late. As a result, we're using a custom breakpoint optimized for the
/// Cloud Cover component.

$_cloud-cover-breakpoint: 45em;

/// We can't use `gap` exclusively due to some containers only being present
/// some of the time, so we re-use this value for `gap` and for `margin` later
/// on.
///
/// @type Number
/// @access private

$_row_gap: size.$rhythm-default;

/// At wider sizes we want to add a bit more horizontal/inline space between
/// content sections.
///
/// @type Number
/// @access private

$_column_gap: spacing.$fluid-gap;

/// The ideal cloud size is a factor of both the viewport width and height, and
/// we size other elements based on factors of this value. This function returns
/// that size as a `calc`, optionally with an `$amount` for partial or multiple
/// instances of that value.
///
/// This really wouldn't be necessary if Sass would play nice with a variable
/// declaration for `(14vh + 4vw)` (without `calc`), but it always tries to
/// crunch those numbers together.
///
/// @param {Number} $amount [1] - Optional multiplier for default space.
/// @param {Number} $vh [12vh] - Amount of horizontal space in the result.
/// @param {Number} $vw [3vw] - Amount of vertical space in the result.
/// @return {Calc}
/// @access private

@function _cloud-space($amount: 1, $vh: 12vh, $vw: 3vw) {
  @if $amount == 1 {
    @return calc(#{$vh} + #{$vw});
  }

  @return calc((#{$vh} + #{$vw}) * #{$amount});
}

/**
 * The topmost containing element for this component. We keep most layout logic
 * off of this so it can be used with `o-container`.
 *
 * 1. Allows elements after this to overlap the clouds without having to use
 *    increasingly larger `z-index` values.
 * 2. This is only required to prevent Safari from showing subpixel artifacts
 *    at the bottom of bottom-aligned imagery (specifically the clouds).
 * 3. Allows us to position clouds absolutely relative to this container.
 */

.c-cloud-cover {
  contain: layout; /* 1 */
  overflow: hidden; /* 2 */
  position: relative; /* 3 */
}

/**
 * The pseudo elements for background and foreground clouds.
 *
 * 1. Safari often renders subpixel artifacts on the bottom edge, causing a
 *    visible line below the clouds. As long as the container has `overflow:
 *    hidden` set, this should prevent that from being visible.
 */

.c-cloud-cover::before,
.c-cloud-cover::after {
  background-position: bottom right;
  background-repeat: no-repeat;
  block-size: _cloud-space();
  content: '';
  inline-size: 100%;
  inset-block-end: -1px; /* 1 */
  inset-inline-end: 0;
  pointer-events: none;
  position: absolute;

  @media (width >= $_cloud-cover-breakpoint) {
    inline-size: 50%;
  }
}

// Stylelint wants to change `viewBox` to `viewbox`, which will break
// stylelint-disable value-keyword-case

/**
 * The background clouds. We adjust the colors and viewboxes here rather than
 * in the SVG to give us better control of the style and
 * composition in this context.
 *
 * 1. These sizes correspond to the cloud's proportion to the largest cloud.
 */

.c-cloud-cover::before {
  background-image: svg-load(
      'clouds/medium.svg',
      fill=color.$brand-primary-lighter,
      width= '480',
      height= '220',
      viewBox= '0 0 480 220'
    ),
    svg-load(
      'clouds/small.svg',
      fill=color.$brand-primary-light,
      width= '580',
      height= '140',
      viewBox= '0 0 580 140'
    );
  background-size: auto (math.div(220, 300) * 100%),
    auto (math.div(140, 300) * 100%); /* 1 */
}

/**
 * The foreground cloud.
 */

.c-cloud-cover::after {
  background-image: svg-load(
    'clouds/large.svg',
    fill=color.$text-light-emphasis,
    width= '320',
    height= '300',
    viewBox= '0 0 320 300'
  );
  background-position: bottom right;
  background-size: auto 100%;
  z-index: 2;
}

// stylelint-enable value-keyword-case

/**
 * This element is where the layout is defined. It's most likely the
 * `max-width` container (if present), which may already include horizontal
 * whitespace.
 *
 * 1. We use rows instead of padding/margin for whitespace to allow some scenes
 *    to overlap the clouds.
 * 2. We want this content to cover the background clouds, but not the
 *    foreground clouds.
 */

.c-cloud-cover__inner {
  align-items: center;
  column-gap: $_column_gap;
  display: grid;
  grid-template-areas:
    '.'
    'scene'
    'content'
    'extra'
    '.';
  grid-template-rows:
    _cloud-space(0.5)
    repeat(3, auto)
    _cloud-space(); /* 1 */
  position: relative; /* 2 */
  z-index: 1; /* 2 */

  /**
   * 1. At larger sizes when the scene imagery occupies the rightmost column,
   *    we establish rows that are half the height of the clouds to allow more
   *    overlap.
   */

  @media (width >= $_cloud-cover-breakpoint) {
    grid-template-areas:
      '. .'
      '. scene'
      'content extra'
      '. .'
      '. .';
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows:
      repeat(2, _cloud-space(0.5))
      auto
      repeat(2, _cloud-space(0.5)); /* 1 */
  }

  /**
   * Modified styles for Cloud Cover with Extra content
   *
   * 1. Give the `extra` content a bit more space relative to the content
   *    until the viewport is wide enough for the default evenly split layout.
   */
  .c-cloud-cover--with-extra & {
    @media (width >= $_cloud-cover-breakpoint) and (width < breakpoint.$xl) {
      grid-template-columns: 3fr 4fr; /* 1 */
    }
  }
}

/**
 * For scenes that are meant to intersect with the horizon, we extend the
 * scene area to the bottom row. (We have to do things a bit differently at
 * larger sizes, which you'll see later.)
 */

.c-cloud-cover--horizon-scene .c-cloud-cover__inner {
  @media (width < $_cloud-cover-breakpoint) {
    grid-template-areas:
      '.'
      'content'
      'extra'
      'scene'
      'scene';
  }
}

/**
 * The content container.
 */

.c-cloud-cover__content {
  grid-area: content;
}

.c-cloud-cover__copy {
  font-size: fluid.fluid-clamp(
    1em,
    size.$font-big,
    breakpoint.$xs,
    breakpoint.$l
  );
}

/**
 * The optional _extra_ content container, intended for things like forms or
 * other calls to action.
 */

.c-cloud-cover__extra {
  grid-area: extra;

  /**
   * Because we don't want lingering row gaps when there is no extra, we must
   * use margin to avoid this running up against adjacent content.
   */

  @media (width < $_cloud-cover-breakpoint) {
    margin-block-start: $_row_gap;
  }
}

/**
 * The optional scene, where any visual objects in the sky will be displayed.
 *
 * 1. To avoid content jumps as images load, we'll be absolute-positioning the
 *    visual objects within this element.
 * 2. Without this, a cell with only absolute-positioned elements may take up
 *    zero space.
 */

.c-cloud-cover__scene {
  grid-area: scene;
  inline-size: 100%; /* 2 */
  position: relative; /* 1 */

  /**
   * At smaller breakpoints, we size the scene so that it is always twice as
   * large as the clouds.
   */

  @media (width < $_cloud-cover-breakpoint) {
    block-size: _cloud-space(2);
    margin-block-end: $_row_gap;
  }

  /**
   * At larger breakpoints, we allow more overlap between the clouds and imagery
   * and size based on available space.
   */

  @media (width >= $_cloud-cover-breakpoint) {
    block-size: 100%;
    grid-row-end: span 3;
  }
}

/**
 * Scene adjustments for when the scene is intended to intersect with the
 * horizon.
 */

.c-cloud-cover--horizon-scene .c-cloud-cover__scene {
  /**
   * At smaller sizes we increase the height to account for the additional
   * cloud overlap, and swap the edge of the gap (since the content order is
   * the reverse of the default).
   */

  @media (width < $_cloud-cover-breakpoint) {
    block-size: _cloud-space(3);
    margin-block: $_row_gap 0;
  }

  /**
   * At larger sizes all we have to do is increase the row span. We can't rely
   * on areas alone to do this since the `scene` and `extra` areas overlap.
   */

  @media (width >= $_cloud-cover-breakpoint) {
    grid-row-end: span 4;
  }
}

/**
 * The actual object within the scene, for example an `img` or `svg`.
 *
 * 1. Cover and fill the entire scene.
 * 2. Adjust and reposition the image within that container.
 */

.c-cloud-cover__scene-object {
  block-size: 100%; /* 1 */
  inline-size: 100%; /* 1 */
  inset-block-start: 0; /* 1 */
  inset-inline-start: 0; /* 1 */
  object-fit: contain; /* 2 */
  object-position: center; /* 2 */
  position: absolute; /* 1 */

  /**
   * At larger sizes, it looks a bit more balanced to start adding more space
   * to the right rather than on both sides.
   */

  @media (width >= $_cloud-cover-breakpoint) {
    object-position: left center;
  }
}

/**
 * When the scene is intended to intersect with the horizon, the object must
 * be positioned along the bottom.
 */

.c-cloud-cover--horizon-scene .c-cloud-cover__scene-object {
  object-position: center bottom;

  @media (width >= $_cloud-cover-breakpoint) {
    object-position: left bottom;
  }
}

///
/// Page container
///
/// 1. Attempts to fill the available area (assuming `height: 100%` is applied
///    to all parent elements)
///
.c-cloud-cover--full-height {
  min-block-size: 100%; // 1
}
