@use 'sass:math';
@use '../../../compiled/tokens/scss/breakpoint';
@use '../../../compiled/tokens/scss/color';
@use '../../../compiled/tokens/scss/line-height';
@use '../../../compiled/tokens/scss/size';
@use '../../../mixins/border-radius';
@use '../../../mixins/button';
@use '../../../mixins/emdash';
@use '../../../mixins/headings';
@use '../../../mixins/ms';
@use '../../../mixins/ratio-box';
@use '../../../mixins/spacing';
@use '../../../mixins/table';
@use '../../../mixins/theme';

/**
 * Gutenberg block: Button
 * Applies our pattern library styles to buttons generated via Gutenberg blocks.
 */

$wp-button-gap: size.$spacing-gap-button-group-default;

.wp-block-buttons {
  display: flex;
  flex-wrap: wrap;
  margin-block-end: $wp-button-gap * -1;
}

/**
 * 1. Prevent inherited display flex styling from crushing layout
 */
.wp-block-button {
  flex: none; /* 1 */

  .wp-block-buttons & {
    margin-block-end: $wp-button-gap;
    margin-inline-end: $wp-button-gap;
  }

  .wp-block-button__link {
    @include button.default;
  }

  &.is-style-outline .wp-block-button__link {
    @include button.secondary;
  }
}

/**
 * Gutenberg block: File download button
 * Applies our pattern library styles to gutenberg file download blocks.
 */
.wp-block-file {
  /**
   * 1. Prevents stacked file buttons from collapsing on each other.
   */
  + .wp-block-file {
    margin-block-start: $wp-button-gap; /* 1 */
  }

  /**
   * The following three selectors target a class name _and_ a universal
   * selector (*). This is intentional because the Gutenberg file block can
   * generate two different elements, a file-link and a file-button and we
   * want to style both of them with the same visual appearance and
   * characteristics. We could easily have chosen `:not(.wp-block-file__button)`
   * but opted for less characters.
   *
   * 1. Prevents default WP styling from modifying buttons opacity on hover.
   */
  .wp-block-file__button,
  * {
    @include button.default;
    opacity: inherit !important; /* 1 */
  }

  /**
   * 1. Prevents default WP styling from modifying button text color on hover
   */
  &.c-button--secondary {
    .wp-block-file__button,
    * {
      @include button.secondary;
      color: inherit !important; /* 1 */
    }
  }

  /**
   * 1. Prevents default WP styling from modifying button text color on hover
   */
  &.c-button--tertiary {
    .wp-block-file__button,
    * {
      @include button.tertiary;
      color: inherit !important; /* 1 */
    }
  }
}

/**
 * Gutenberg Block: Columns
 *
 * 1. Apply our standard rhythm styles to the contents of Columns.
 */
.wp-block-column {
  @include spacing.vertical-rhythm; // 1
}

/**
 * Gutenberg Block: Code
 * Styles for Gutenberg code blocks (and code inside Markdown blocks)
 *
 * 1. Set inline margins and padding to outdent the block out a bit,
 *    but keep the code aligned with the page content.
 * 2. WordPress tries to wrap lines of code by default, but we prefer
 *    to use overflow to scroll.
 */
.wp-block-code,
.wp-block-jetpack-markdown pre,
.legacy-post pre {
  @include spacing.fluid-margin-inline-negative; // 1
  @include spacing.fluid-padding-inline; // 1

  code {
    white-space: pre; // 2
  }
}

// Don't outdent code blocks in comments, where spacing is at a premium.
.c-comment pre {
  margin-inline: 0;
  padding-inline: ms.step(1); // restoring default padding
}

/// Gutenberg block: Embed

.wp-block-embed {
  // If the embed type has an aspect ratio, apply the same ratio-box styles as
  // our embed component.
  &.wp-has-aspect-ratio .wp-block-embed__wrapper {
    @include ratio-box.enhanced-styles;
  }

  /// Supporting all aspect ratios that WordPress supports at the time of
  /// writing.
  /// @see {https://github.com/WordPress/gutenberg/blob/208e3e2/packages/block-library/src/embed/constants.js}

  &.wp-embed-aspect-21-9 .wp-block-embed__wrapper {
    --aspect-ratio: 21/9;
  }

  &.wp-embed-aspect-18-9 .wp-block-embed__wrapper {
    --aspect-ratio: 2;
  }

  &.wp-embed-aspect-16-9 .wp-block-embed__wrapper {
    --aspect-ratio: 16/9;
  }

  &.wp-embed-aspect-4-3 .wp-block-embed__wrapper {
    --aspect-ratio: 4/3;
  }

  &.wp-embed-aspect-1-1 .wp-block-embed__wrapper {
    --aspect-ratio: 1;
  }

  &.wp-embed-aspect-9-16 .wp-block-embed__wrapper {
    --aspect-ratio: 9/16;
  }

  &.wp-embed-aspect-1-2 .wp-block-embed__wrapper {
    --aspect-ratio: 1/2;
  }

  // Apply consistent margin styles to video embeds.
  &.is-type-video {
    &:not(.alignwide):not(.alignfull):not(.aligncenter) {
      @include spacing.fluid-margin-inline-negative;
    }

    // Prevent figcaption contents from hitting the viewport edge
    &:not(.aligncenter) {
      figcaption {
        @include spacing.fluid-padding-inline;
      }
    }
  }
}

/// Gutenberg block: Image
/// Styles for images inserted via Gutenberg blocks.

.wp-block-image {
  position: relative;

  /// Since we are applying `margin-top` to CMS content via our o-rhythm
  /// pattern, the default `margin-bottom` value on Gutenberg figcaption
  /// elements is unnecessary, so we remove it here.
  &,
  figcaption {
    margin-block-end: 0;
  }

  /// When some alignment options are selected, WordPress nests the figure with
  /// the alignment class within the `wp-block-image` element.
  ///
  /// 1. The default top margin makes these alignment options appear misaligned
  ///    unless they are floating midway through text, which is extremely
  ///    uncommon.
  /// 2. We constrain the width to 50% minus half of WordPress's default gutter
  ///    size. This makes the adjacent content feel visually balanced.
  .alignleft,
  .alignright {
    margin-block-start: 0; // 1
    max-inline-size: calc(50% - 0.5em); // 2
  }

  /// By default, WordPress uses table styles to constrain captions to the size
  /// of the image. This makes sense for left- and right-aligned image blocks,
  /// but for consistency with our non-block `figure` elements, we allow
  /// captions to go as wide as they need for centered elements.
  .aligncenter {
    &,
    > figcaption {
      display: block;
    }
  }

  /// Apply border only to image
  ///
  /// 1. We're using 1px borders here rather than size.$edge-small because it
  ///    was causing subpixel rendering errors leaving a slight gap between the
  ///    image and the border.
  &.is-style-outlined img {
    border-color: var(--theme-color-border-text-group);
    border-style: solid;
    border-width: 1px; // 1
  }
}

/// Because WordPress changes the structure of the Image block markup depending
/// on the alignment option but does not append the alignment class to the
/// parent element in all cases, this was the only solution I could find for
/// targeting its _default_ state. We may be able to simplify once the `:has`
/// selector is better supported!
figure.wp-block-image {
  /// When this element has no alignment option set, attempt to fill the
  /// container padding.
  &:not(.alignwide):not(.alignfull) {
    @include spacing.fluid-margin-inline-negative;
  }

  /// The `figure.wp-block-image` selector will only be valid if there is no
  /// alignment, wide alignment or full alignment. In all three cases, any
  /// caption is in danger of meeting the viewport edge unless we add in some
  /// padding.
  figcaption {
    @include spacing.fluid-padding-inline;
  }
}

/// Gutenberg block: Media-Text
.wp-block-media-text {
  // I'm honestly not sure why the core WordPress block doesn't use `gap` at the
  // time of this writing, but it solves a lot of spacing issues.
  gap: size.$spacing-gap-inline-medium;

  // When an image is set to fill the container, setting a `border-radius` makes
  // the cropping feel more visually intentional (similar to card covers).
  &.is-image-fill .wp-block-media-text__media {
    border-radius: size.$border-radius-medium;
  }

  .wp-block-media-text__content {
    // Maintain vertical rhythm between child elements.
    @include spacing.vertical-rhythm;

    // We remove the padding since `gap` is already applied to the parent.
    padding: 0;
  }
}

/// Gutenberg block: Video
/// Styles for videos inserted via Gutenberg blocks.
.wp-block-video {
  &:not(.alignwide):not(.alignfull):not(.aligncenter) {
    @include spacing.fluid-margin-inline-negative;
  }

  &:not(.aligncenter) {
    figcaption {
      @include spacing.fluid-padding-inline;
    }
  }
}

/// Gutenberg block: Group
///
/// Allow child elements to inherit the parent element rhythm.
.wp-block-group__inner-container {
  @include spacing.vertical-rhythm;

  /// If the first child of the group is a block image that is not a `figure`
  /// element, assume it is a left- or right-aligned image. To prevent extra
  /// whitespace at the top of the group, we negate the start margin of the
  /// next element in the group.
  > .wp-block-image:not(figure):first-child + * {
    margin-block-start: 0;
  }
}

/**
 * Gutenberg block: Table
 * Applies our pattern library styles to tables generated via Gutenberg blocks.
 */

/**
 * Default table
 *
 * Note that this only targets tables in the Table block, the Markdown block,
 * and in legacy post content. If you add a table manually in an HTML block,
 * you should add the `c-table` class, which will apply the same styles.
 */
.wp-block-table,
.wp-block-jetpack-markdown,
.legacy-post,
.c-comment {
  table td,
  table th {
    @include table.t-container;

    // At some point, WordPress started setting a default border on table cells
    border-width: 0;
  }

  table th {
    @include table.t-heading;
  }

  table thead {
    @include table.t-head;
  }

  table tfoot {
    @include table.t-foot;
  }

  table caption {
    @include table.t-caption;
  }
}

/// Gutenberg block: Table
.wp-block-table {
  &.is-style-stripes {
    border-block-end: 0;

    tbody tr:nth-of-type(2n - 1) {
      @include table.t-striped;
    }
  }

  &.is-style-ruled tbody tr {
    @include table.t-ruled;
  }

  &.is-style-numeric table {
    @include table.t-numeric;

    th {
      text-align: end;
    }
  }
}

/// Quote and Pullquote shared block styles

.wp-block-quote,
.wp-block-pullquote {
  /// When the quote has text alignment other than left, we right-align the
  /// citation styles so they don't disrupt the reading line.
  &.has-text-align-center,
  &.has-text-align-right {
    cite {
      text-align: end;

      &::before {
        margin-inline-end: 1ch;
        position: static;
      }
    }
  }
}

/// Quote Block Styles

.wp-block-quote {
  /// We reset the left border and padding when the style is plain or when text
  /// alignment or background color will differentiate the content on its own.
  &.is-style-plain,
  &.has-background,
  &.has-text-align-center,
  &.has-text-align-right {
    border-inline-start-width: 0;
    padding-inline-start: 0;
  }

  /// We reset the text color when the blockquote is plain

  /// The plain style tries to make the blockquote appear more or less unstyled,
  /// so we reset all of the defaults.
  &.is-style-plain {
    color: inherit;
  }
}

/// Pullquote Block Styles

.wp-block-pullquote {
  /// We have to reset the default text color and font size because Gutenberg
  /// makes it really difficult to adjust the defaults without a complete switch
  /// to using `theme.json`. These defaults are only exposed via inline styles
  /// rather than the core block CSS, which makes them extra difficult to
  /// troublehoot as well.
  color: var(--theme-color-text-muted);
  font-size: inherit;
  line-height: inherit;

  /// We use generous margins to differentiate the pull quote from adjacent
  /// content. The core pattern uses padding for this, but we use margin so the
  /// margin of adjacent elements won't needlessly stack.
  margin: size.$rhythm-generous 0;
  padding: 0;

  /// Inherit parent element text by default instead of centering
  &:not([class*='has-text-align']) {
    text-align: inherit;
  }

  /// For alignments that exceed the content container, apply fluid padding
  /// to maintain a consistent reading line.
  &.alignwide,
  &.alignfull {
    @include spacing.fluid-padding-inline;
  }

  /// For alignment styles that cause the element to float, don't adjust the
  /// element's appearance until a specific breakpoint.
  &.alignleft,
  &.alignright {
    max-inline-size: 100%;

    /// At that breakpoint, omit the border, apply default margins to encourage
    /// alignment with adjacent elements, and set a maximum width to prevent
    /// this element from overwhelming its siblings.
    @media (width >= breakpoint.$m) {
      border-inline-start-width: 0;
      margin: var(--rhythm, size.$rhythm-default) 0;
      max-inline-size: 50%;
    }
  }

  &.alignleft {
    @media (width >= breakpoint.$m) {
      float: left;
      margin-inline-end: size.$rhythm-generous;
    }
  }

  &.alignright {
    @media (width >= breakpoint.$m) {
      float: right;
      margin-inline-start: size.$rhythm-generous;
    }
  }

  /// We omit the typical blockquote border and padding because the text size,
  /// margin and various alignment options will differentiate the element from
  /// its siblings without. This also simplifies having to turn the border on
  /// and off for the aforementioned alignment options.
  blockquote {
    border-inline-start-width: 0;
    padding: 0;
  }

  /// Increase the typical font size for pull quotes
  p {
    @include headings.level(1, false);
  }

  /// Use a smaller font size when the pull quote is floating.
  /// We're ignoring this selector because Stylelint thinks it's duplicating
  /// the parent styles because it isn't seeing the nested selector.

  /* stylelint-disable-next-line no-duplicate-selectors */
  &.alignleft,
  &.alignright {
    p {
      @media (width >= breakpoint.$m) {
        @include headings.level(3, false);
      }
    }
  }
}

/**
 * Gutenberg block: Separator
 *
 * The default separator is intended to be partial-width, so we apply those
 * styles selectively here rather than un-applying them to the other modifiers.
 */

.wp-block-separator.is-style-default {
  inline-size: calc(100% / 3);
  margin-inline: auto;
}
