@layer components {
  /* Flash messages. The left border colour encodes the state. */
  .notice {
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-info-border); border-left-width: 0.25rem;
    background: var(--color-info-bg); color: var(--color-text);
  }
  .notice--success { border-color: var(--color-success-border); background: var(--color-success-bg); }
  .notice--error { border-color: var(--color-error-border); background: var(--color-error-bg); }
  .notice--warning { border-color: var(--color-warning-border); background: var(--color-warning-bg); }
  .notice--info { border-color: var(--color-info-border); background: var(--color-info-bg); }
  .notices { display: grid; gap: var(--space-3); margin-bottom: var(--space-6); }

  /* Success and error notices also carry an icon, so the state does not rest on the colour alone. The icon is decorative
     (a mask on the ::before, no text). Notices stay blocks, not flex, because they can contain inline links. */
  .notice--success,
  .notice--error {
    position: relative;
    padding-inline-start: calc(var(--space-4) + 1.25rem + var(--space-3));
  }
  .notice--success::before,
  .notice--error::before {
    content: "";
    position: absolute;
    inset-inline-start: var(--space-4);
    inset-block-start: calc(var(--space-3) + (1lh - 1.25rem) / 2);
    width: 1.25rem;
    height: 1.25rem;
  }
  .notice--success::before {
    background-color: var(--color-success-text);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m7.5 12.5 3 3 6-6.5'/%3E%3C/svg%3E") center / contain no-repeat;
  }
  .notice--error::before {
    background-color: var(--color-error-text);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 7.5v5.5'/%3E%3Cpath d='M12 16.5v.01'/%3E%3C/svg%3E") center / contain no-repeat;
  }
  /* Forced colours repaint backgrounds with the box colour, which would hide the masked icon; paint it in the text colour. */
  @media (forced-colors: active) {
    .notice--success::before,
    .notice--error::before { forced-color-adjust: none; background-color: CanvasText; }
  }

  /* Admin screens use WordPress notices (SHOP-RULES 15.2): a surface box with a 4px left border in the kind's colour. */
  .admin-main .notice {
    border: 0; border-left: 0.25rem solid var(--color-info-border);
    background: var(--color-surface); color: var(--color-text);
  }
  .admin-main .notice--success { border-left-color: var(--color-success-border); }
  .admin-main .notice--error { border-left-color: var(--color-error-border); }
  .admin-main .notice--warning { border-left-color: var(--color-warning-border); }
  .admin-main .notice--info { border-left-color: var(--color-info-border); }
  /* Admin notices have no icon and keep their own padding and positioning. :where() keeps the reset at the weight of the
     icon rule, so a component that styles a notice (the refund list's indent) still wins as it did before the icon. */
  .admin-main .notice::before { content: none; }
  :where(.admin-main) .notice--success,
  :where(.admin-main) .notice--error { position: static; padding-inline-start: var(--space-4); }
}
