@layer components {
  /* The site-wide announcement, every theme's default. Two properties carry its colour —
     --banner-bg and --banner-fg — set by its tone (shared/banner-tones.css); a theme restyles by
     redefining a tone's pair, or by restyling a placement (see sites/zohar). */
  .promo-banner {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--inline-space);
    padding-block: var(--block-space-half);
    padding-inline: var(--block-space);
    text-align: center;
    font-size: var(--text-small);
    background: var(--banner-bg);
    color: var(--banner-fg);
  }

  .promo-banner__inner {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--inline-space) var(--block-space);
  }

  .promo-banner__message { margin: 0; font-weight: 500; color: inherit; }
  .promo-banner__countdown { font-weight: 700; white-space: nowrap; }
  .promo-banner__countdown::before { content: "·"; margin-inline: 0.5em; opacity: 0.6; }

  /* A solid pill in the banner's colours reversed, with a nudging arrow. */
  .promo-banner__cta {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    padding-block: 0.2em;
    padding-inline: 0.85em;
    border-radius: 999px;
    background: var(--banner-fg);
    color: var(--banner-bg);
    max-inline-size: 100%;
    font-weight: 600;
    text-decoration: none;
    text-wrap: balance;
    transition: box-shadow var(--transition);
  }
  .promo-banner__cta::after { content: "→"; transition: transform var(--transition); }
  .promo-banner__cta:hover { color: var(--banner-bg); text-decoration: none; box-shadow: 0 4px 14px -6px oklch(0% 0 0 / 0.5); }
  .promo-banner__cta:hover::after { transform: translateX(0.2em); }
  [dir="rtl"] .promo-banner__cta::after { content: "←"; }
  [dir="rtl"] .promo-banner__cta:hover::after { transform: translateX(-0.2em); }

  .promo-banner__dismiss {
    flex: none;
    display: inline-flex;
    padding: 0.25em;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity var(--transition), background var(--transition);
  }
  .promo-banner__dismiss:hover {
    opacity: 1;
    background: color-mix(in oklab, currentColor 15%, transparent);
  }
  .promo-banner__dismiss svg { inline-size: 1.05rem; block-size: 1.05rem; }

  /* ── Placements ── */

  /* Above or below the header: a full-bleed bar (the base). The light tone needs an edge. */
  .promo-banner.banner-tone--light:is(.promo-banner--top, .promo-banner--below-header, .promo-banner--bottom) {
    box-shadow: inset 0 -1px 0 oklch(0% 0 0 / 0.08), inset 0 1px 0 oklch(0% 0 0 / 0.08);
  }

  /* In the page: a rounded callout above the content, in the reading column. */
  .promo-banner--inline {
    margin-block-end: var(--block-space-double);
    padding: var(--block-space);
    border-radius: var(--radius);
    font-size: var(--text-normal);
  }
  .promo-banner--inline.banner-tone--light { box-shadow: 0 0 0 1px oklch(0% 0 0 / 0.1); }

  /* Pinned to the bottom of the screen, stacked in the dock with the cookie and language bars. */
  .promo-banner--bottom { box-shadow: 0 -8px 24px -18px oklch(0% 0 0 / 0.6); }

  /* A floating card in the bottom corner, sitting on the dock's other bars. */
  .promo-banner--card {
    align-self: flex-end;
    align-items: flex-start;
    inline-size: min(22rem, calc(100% - 2 * var(--block-space)));
    margin: var(--block-space);
    padding: var(--block-space);
    border-radius: var(--radius);
    text-align: start;
    box-shadow: 0 12px 32px -10px oklch(0% 0 0 / 0.45);
  }
  .promo-banner--card .promo-banner__inner { flex-direction: column; align-items: flex-start; justify-content: flex-start; }
  .promo-banner--card .promo-banner__message { font-size: var(--text-normal); }

  /* A corner ribbon on the page's trailing corner, just under the header, so it never covers the
     navigation. The banner is a zero-height marker; its inner box is a square that cuts the band
     clean at both edges, and only the band takes the pointer. The band's centre sits on the
     corner's diagonal, --ribbon-reach from the corner, so its text lands mid-band. */
  .promo-banner--corner {
    --ribbon-reach: 2.6rem;
    --ribbon-thickness: 1.8rem;
    --ribbon-text: var(--text-x-small);
    --ribbon-length: calc(var(--ribbon-reach) * 4);
    position: relative;
    z-index: calc(var(--z-header) - 1);
    display: block;
    block-size: 0;
    padding: 0;
    background: none;
    cursor: pointer;
  }
  @media (min-width: 40rem) { .promo-banner--corner { --ribbon-reach: 3.4rem; --ribbon-thickness: 2.1rem; --ribbon-text: var(--text-small); } }
  .promo-banner--corner .promo-banner__inner {
    position: absolute;
    inset-block-start: 0;
    inset-inline-end: 0;
    display: block;
    inline-size: calc(var(--ribbon-reach) * 2 + var(--ribbon-thickness));
    block-size: calc(var(--ribbon-reach) * 2 + var(--ribbon-thickness));
    overflow: hidden;
    pointer-events: none;
  }
  .promo-banner--corner .promo-banner__message {
    position: absolute;
    inset-block-start: calc(var(--ribbon-reach) - var(--ribbon-thickness) / 2);
    inset-inline-end: calc(var(--ribbon-reach) - var(--ribbon-length) / 2);
    display: block;
    inline-size: var(--ribbon-length);
    block-size: var(--ribbon-thickness);
    /* Only the stretch the square shows carries text: the reach's chord, less a little air. */
    padding-inline: calc((var(--ribbon-length) - var(--ribbon-reach) * 2.83) / 2 + 0.5rem);
    line-height: var(--ribbon-thickness);
    text-align: center;
    font-size: var(--ribbon-text);
    font-weight: 700;
    letter-spacing: 0.02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--banner-fg);
    background: linear-gradient(180deg, color-mix(in oklab, var(--banner-bg) 85%, oklch(100% 0 0)), var(--banner-bg));
    /* Stitching just inside each edge, and a soft drop. */
    box-shadow:
      inset 0 2px 0 -1px color-mix(in oklab, var(--banner-fg) 35%, transparent),
      inset 0 -2px 0 -1px color-mix(in oklab, var(--banner-fg) 35%, transparent),
      0 2px 6px oklch(0% 0 0 / 0.3);
    transform: rotate(45deg);
    pointer-events: auto;
  }
  [dir="rtl"] .promo-banner--corner .promo-banner__message { transform: rotate(-45deg); }
  .promo-banner--corner a.promo-banner__message { text-decoration: none; }
  .promo-banner--corner a.promo-banner__message:hover { color: var(--banner-fg); filter: brightness(1.06); }
  .promo-banner--corner .promo-banner__cta,
  .promo-banner--corner .promo-banner__dismiss { display: none; }

  /* Bars and cards slide in from the edge they sit on; the callout fades; the ribbon stays put. */
  @media (prefers-reduced-motion: no-preference) {
    .promo-banner:is(.promo-banner--top, .promo-banner--below-header) { animation: promo-banner-down 0.5s ease both; }
    .promo-banner:is(.promo-banner--bottom, .promo-banner--card) { animation: promo-banner-up 0.5s ease both; }
    .promo-banner--inline { animation: promo-banner-fade 0.5s ease both; }
    @keyframes promo-banner-down { from { opacity: 0; transform: translateY(-100%); } }
    @keyframes promo-banner-up   { from { opacity: 0; transform: translateY(100%); } }
    @keyframes promo-banner-fade { from { opacity: 0; } }
  }
}
