@use 'sass:math';
@use '../compiled/tokens/scss/color';
@use '../compiled/tokens/scss/ease';
@use '../compiled/tokens/scss/font-weight';
@use '../compiled/tokens/scss/line-height';
@use '../compiled/tokens/scss/size';
@use '../compiled/tokens/scss/transition';
@use '../mixins/border-radius';
@use '../mixins/emdash';
@use '../mixins/ms';
@use '../mixins/spacing';
@use '../mixins/theme';

/**
 * Sensible box model
 */

*,
::before,
::after {
  box-sizing: border-box;
}

/**
 * Remove default spacing from elements. We'll be managing these directly at a
 * layout or component level.
 *
 * Element list derived from browser default stylesheets.
 *
 * @see https://stackoverflow.com/a/3980775/5175805
 */

blockquote,
body,
button,
dd,
dl,
figure,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
input,
ol,
p,
pre,
select,
textarea,
ul {
  margin: 0;
}

/**
 * 1. Forces the viewport to be filled. Necessary for the footer to
 *    "stick" to the bottom of short pages.
 *    @see https://css-tricks.com/couple-takes-sticky-footer/#there-is-grid
 */
html {
  block-size: 100%; // 1
}

/**
 * 1. Keep full-bleed items from triggering a horizontal scrollbar.
 *    @see https://cloudfour.com/thinks/breaking-out-with-viewport-units-and-calc/
 */

html,
body {
  overflow-x: hidden; // 1
}

/**
 * We apply theme rules here rather than `:root` because custom background
 * colors, iframe embeds, etc. will defer to or attempt to change the `body`
 * background so it's important to establish defaults.
 */

body {
  @include theme.rules;
}

/**
 * Default link color
 */

a {
  color: var(--theme-color-text-action);
}

/**
 * 1. Block display is usually what we want
 * 2. Remove strange space-below when inline
 * 3. Responsive by default
 *
 * @see https://github.com/mozdevs/cssremedy
 */

audio,
canvas,
embed,
iframe,
img,
object,
svg,
video {
  display: block; /* 1 */
  max-inline-size: 100%; /* 3 */
  vertical-align: middle; /* 2 */
}

/**
 * Embedded elements with consistent aspect ratios require this to maintain
 * that ratio when resized.
 */

canvas,
img,
svg,
video {
  block-size: auto;
}

/**
 * It's pretty arbitrary that audio elements are 300px wide by default.
 */

audio {
  inline-size: 100%;
}

/**
 * Code blocks
 *
 * 1. Don't allow code blocks to overflow willy-nilly.
 * 2. Prevent absolute-positioned children (such as visually-hidden language
 *    labels) from breaking horizontal scroll in Chrome.
 * 3. Set a shallower tab size to encourage accessible code samples without
 *    compromising horizontal real estate.
 */

pre {
  @include border-radius.conditional;
  background: color.$brand-primary-darker;
  color: color.$text-light;
  overflow: auto; /* 1 */
  padding: ms.step(1);
  position: relative; /* 2 */
  tab-size: 2; /* 3 */
}

/**
 * When certain monospace inline elements are not within a preformatted block or
 * a link, we offset their color from surrounding content.
 *
 * We're disabling a selector rule here because the alternative is pretty
 * ridiculously verbose. We should consider revising our selector rules.
 */

/* stylelint-disable-next-line selector-not-notation */
:not(pre, pre *, a) > :is(code, kbd) {
  color: var(--theme-color-text-code);
}

/**
 * Some additional styles are added to `kbd` elements because it's fun to
 * embrace just a little skeuomorphism and make them look like keys. ⌨️
 *
 * 1. We use a shadow instead of `border-bottom-width` to apply a bit of depth
 *    because it won't visually impact the element's rounded corners.
 * 2. Without a `min-width`, single character keys (which is most of them)
 *    appear rather skinny and strange.
 */

*:not(pre):not(a) > kbd {
  background: var(--theme-color-background-kbd);
  border: size.$edge-small solid var(--theme-color-border-kbd);
  border-radius: size.$border-radius-small;
  box-shadow: 0 size.$edge-small 0 0 var(--theme-color-border-kbd); /* 1 */
  display: inline-block;
  min-inline-size: ms.step(2); /* 2 */
  padding: 0 ms.step(-6);
  text-align: center;
}

/**
 * Diff elements
 */

del {
  opacity: var(--theme-opacity-del);
}

/**
 * IE10 and earlier still show borders around linked images, and all browsers
 * still show borders around iframe elements by default.
 *
 * We set the `border-style` and `border-width` so that utility classes can
 * easily set themed default colors.
 */

iframe,
img {
  border-style: solid;
  border-width: 0;
}

/**
 * IE10 and earlier do not respect the `hidden` attribute.
 *
 * @see https://cloudfour.com/thinks/see-no-evil-hidden-content-and-accessibility/
 */

[hidden] {
  display: none !important;
}

/**
 * IE11 and earlier display some HTML5 elements as `inline` by default.
 */

article,
aside,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section {
  display: block;
}

/**
 * Shared indentation for typographic blocks
 */

ul,
ol,
blockquote {
  padding-inline-start: size.$spacing-type-block-indent;
}

blockquote {
  @include spacing.vertical-rhythm;
  border-inline-start: size.$border-width-blockquote solid
    var(--theme-color-border-text-group);
  color: var(--theme-color-text-muted);
}

blockquote > cite,
blockquote > footer > cite {
  display: block;
  font-style: inherit;
  padding-inline-start: size.$spacing-type-block-indent;
  position: relative;

  &::before {
    @include emdash.content;
    inset-inline-start: 0;
    position: absolute;
  }
}

/// Details/Summary
///
/// 1. Apply vertical rhythm between child elements, similar to `blockquote`

details {
  @include spacing.vertical-rhythm; // 1

  /// 1. Offset the summary text a bit from its contents
  /// 2. Use the same interaction affordance as buttons
  /// 3. Set up our custom marker. Because Safari for `::marker` is poor, we
  ///    have to use some hackery instead.
  /// 4. Apply padding that is consistent with lists.
  ///
  > summary {
    color: var(--theme-color-text-emphasis); // 1
    cursor: pointer; // 2
    font-weight: font-weight.$medium;
    list-style: none; // 3
    padding-inline-start: size.$spacing-type-block-indent; // 4
    position: relative; // 3

    /// Safari 16.6 demands more than `list-style: none`
    &::-webkit-details-marker {
      display: none;
    }
  }

  /// Icon affordance for summary. We use a pseudo element so we can rotate it
  /// without an additional asset.
  ///
  /// 1. Align nicely with adjacent text, using the default `line-height` as a
  ///    fallback when line-height units aren't supported.
  /// 2. Offset just a bit visually so the pointer aligns nicely with the
  ///    content below. We use `translate` instead of `transform` so we can
  ///    modify the rotation without repeating this style.
  > summary::before {
    background-position: center;
    background-repeat: no-repeat;
    background-size: contain;
    block-size: line-height.$loose * 1em; // 1
    block-size: 1lh; // 1
    content: '';
    inline-size: 1em;
    inset-inline-start: 0;
    position: absolute;
    translate: -33% 0; // 2

    // Vary the icon color based on the theme.
    @include theme.styles {
      background-image: svg-load(
        'icons/caret-right.svg',
        fill=color.$text-dark
      );
    }

    @include theme.styles(dark) {
      background-image: svg-load(
        'icons/caret-right.svg',
        fill=color.$text-light-emphasis
      );
    }

    // Animate the icon rotation if the user has no reduced motion preference.
    @media (prefers-reduced-motion: no-preference) {
      transition: rotate transition.$immediate ease.$out;
    }
  }

  // Rotate the icon when the details element is open.
  &[open] > summary::before {
    rotate: 90deg;
  }
}

/**
 * Apply some sensible defaults to tables
 */

/**
 * `text-align: start` does not work reliably on tables, but `inherit` does when
 * applied to both the `table` element and cells
 */

table,
th,
td {
  text-align: inherit;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  inline-size: 100%;
  overflow-x: auto;
}

/*
 * 1. Removes default margin
 * 2. Center content
 * 3. Space between elements inside <figure>
 */

figure {
  margin: 0; /* 1 */

  > * {
    margin-inline: auto; /* 2 */
  }

  > * + * {
    margin-block-start: ms.step(-1); /* 3 */
  }
}

figcaption {
  font-size: size.$font-small;
  font-style: italic;
  text-align: center;
}

address {
  font-style: normal;
}

/**
 * Labels
 */

label {
  color: var(--theme-color-text-label);
}

/**
 * Horizontal rules
 *
 * We use border styles and `currentColor` for greater compatibility with
 * the WordPress Gutenberg "Separator" block.
 *
 * 1. Our goal is for the borders to add together to form the total desired
 *    width. We do this because that's what WordPress's Gutenberg block does
 *    in order to support weird border+background style combinations.
 */

hr {
  border-color: currentColor;
  border-style: solid;
  border-width: math.div(size.$edge-medium, 2) 0; /* 1 */
  color: var(--theme-color-border-text-group);
}
