@layer cinder.tokens, cinder.foundation, cinder.components, cinder.utilities;
@layer cinder.components {
  /* ========================================
 * BANNER
 * ----------------------------------------
 * Full-width, page-level notification strip. Stretches the inline size of
 * its parent container — to bleed edge-to-edge of the viewport, render
 * outside any max-width content column.
 *
 * No motion is defined in v1; if entry/exit animation is added later, it
 * must be gated on `prefers-reduced-motion: no-preference`.
 * ======================================== */

  .cinder-banner {
    display: grid;
    /* The glyph, the message and the dismiss button share the first row; the actions stack under
     * the message on the next row at every width (COR-2314), so a banner reads the same on a phone
     * as on a desktop and the buttons never overlap the words. An absent glyph or dismiss button
     * leaves its track at zero width, and the gaps are margins on the parts so nothing is left
     * behind. */
    grid-template-columns: auto minmax(0, 1fr) auto;
    column-gap: 0;
    row-gap: var(--cinder-space-3);
    align-items: start;
    inline-size: 100%;
    padding-block: var(--cinder-space-3);
    padding-inline: var(--cinder-space-4);
    border-block: 1px solid var(--cinder-border);
    background: var(--cinder-surface);
    color: var(--cinder-text-default);
    font-size: var(--cinder-text-sm);
    line-height: var(--cinder-leading-normal);
  }

  @media (prefers-reduced-motion: no-preference) {
    .cinder-banner {
      transition:
        background-color var(--cinder-duration-fast) var(--cinder-ease-standard),
        border-color var(--cinder-duration-fast) var(--cinder-ease-standard);
    }
  }

  :root:is([data-cinder-reduced-motion='false'], [data-reduced-motion='off']) .cinder-banner {
    transition:
      background-color var(--cinder-duration-fast) var(--cinder-ease-standard),
      border-color var(--cinder-duration-fast) var(--cinder-ease-standard);
  }

  /* ----------------------------------------
 * Content area
 * ---------------------------------------- */

  .cinder-banner__content {
    grid-column: 2;
    grid-row: 1;
    min-width: 0;
    /* A line of words stays readable: the message never runs wider than 68 characters. */
    max-inline-size: 68ch;
  }

  /* A glyph at the start, as tall as the first line so it sits beside it, not centered on a
   * two-line message. */
  .cinder-banner__icon {
    display: inline-flex;
    grid-column: 1;
    grid-row: 1;
    margin-inline-end: var(--cinder-space-3);
    align-items: center;
    align-self: start;
    block-size: calc(var(--cinder-text-sm) * var(--cinder-leading-normal));
  }

  /* The bold lead keeps the tone's colour; the sentence after it reads in the default text
   * colour, so only the lead is amber or blue. A page's own children keep the status colour. */
  .cinder-banner__title {
    font-weight: var(--cinder-font-semibold);
  }

  .cinder-banner__title[data-cinder-title-layout='stacked'] {
    display: block;
  }

  .cinder-banner__text {
    color: var(--cinder-text-default);
  }

  /* The stale-data notice sits on its own line beneath the message, a step smaller. It keeps
   * the status foreground colour so contrast on the tinted surface is unchanged. */
  .cinder-banner__stale {
    display: block;
    font-size: var(--cinder-text-xs);
  }

  /* ----------------------------------------
 * Actions region
 * ---------------------------------------- */

  /* Under the message, in a row that wraps: several actions break onto lines of their own rather
   * than squeezing, and a button label never wraps inside its button. */
  .cinder-banner__actions {
    display: flex;
    flex-wrap: wrap;
    grid-column: 2;
    grid-row: 2;
    align-items: center;
    justify-self: start;
    gap: var(--cinder-space-2);
  }

  .cinder-banner__actions button,
  .cinder-banner__actions a {
    white-space: nowrap;
  }

  /* Touch: the action is a full 44px target, not the compact desktop height. */
  @media (pointer: coarse) {
    .cinder-banner__actions > :is(button, a) {
      min-block-size: 2.75rem;
    }
  }

  /* A phone: every action is a 44px target, as a coarse pointer makes it (the button reads its
   * height from the token, so the token is what changes), and a banner that stacks them gives each
   * its own full line, so the buttons are as wide as the words. */
  @media (max-width: 39.99rem) {
    .cinder-banner__actions {
      /* @runtime-state */
      --cinder-button-height-xs: var(--cinder-touch-target-min);
      /* @runtime-state */
      --cinder-button-height-sm: var(--cinder-touch-target-min);
      /* @runtime-state */
      --cinder-button-height-md: var(--cinder-touch-target-min);
    }

    .cinder-banner__actions[data-cinder-stacked='true'] {
      flex-direction: column;
      align-items: stretch;
      inline-size: 100%;
    }

    .cinder-banner__actions[data-cinder-stacked='true'] > :is(button, a) {
      justify-content: center;
    }
  }

  /* ----------------------------------------
 * Sticky
 * ---------------------------------------- */

  .cinder-banner[data-cinder-sticky='true'] {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
  }

  /* A stuck banner sits below its scroll container's top padding, and rows scrolled under it
     showed through that gap (s4#17). The banner covers the band above it with the page canvas, a
     page's top padding deep (space-4), so nothing reads between the banner and the edge. Before
     it sticks the band falls on that same padding, so it draws nothing a reader sees. */
  .cinder-banner[data-cinder-sticky='true']::before {
    content: '';
    position: absolute;
    inset-inline: 0;
    /* Above the 1px top border, which the inset alone would cover (it measures from the padding
       box). */
    inset-block-end: calc(100% + 1px);
    block-size: var(--cinder-space-4);
    background: var(--cinder-surface-canvas);
    pointer-events: none;
  }

  /* ----------------------------------------
 * Dismiss button
 * Mirrors .cinder-alert__dismiss rule-for-rule.
 * ---------------------------------------- */

  /* Box-model reset, hit-area, and idle :hover live on .cinder-_dismiss-button
 * (see src/styles/components.css). Only Banner-specific layout positioning,
 * the motion-gated transition, and status-driven focus chrome live here. */
  .cinder-banner__dismiss {
    grid-column: 3;
    grid-row: 1;
    margin-inline-start: var(--cinder-space-3);
    align-self: center;
  }

  @media (prefers-reduced-motion: no-preference) {
    .cinder-banner__dismiss {
      transition:
        background-color var(--cinder-duration-fast) var(--cinder-ease-standard),
        box-shadow var(--cinder-duration-fast) var(--cinder-ease-standard);
    }
  }

  :root:is([data-cinder-reduced-motion='false'], [data-reduced-motion='off'])
    .cinder-banner__dismiss {
    transition:
      background-color var(--cinder-duration-fast) var(--cinder-ease-standard),
      box-shadow var(--cinder-duration-fast) var(--cinder-ease-standard);
  }

  .cinder-banner__dismiss:focus-visible {
    outline: var(--cinder-ring-width) solid transparent;
    box-shadow:
      0 0 0 var(--cinder-ring-offset) var(--cinder-ring-offset-color),
      0 0 0 calc(var(--cinder-ring-offset) + var(--cinder-ring-width))
        var(--_cinder-banner-ring, var(--cinder-ring-color));
  }

  .cinder-banner__dismiss-icon {
    width: 1rem;
    height: 1rem;
  }

  /* ----------------------------------------
 * Status variants
 *
 * The soft-surface color algebra (background, border, foreground) lives in the
 * shared `_status-surface.css` partial, consumed via `.cinder-_status-surface`
 * + `.cinder-_status-surface-border` on the root (see banner.svelte). Banner
 * draws no inline-start stripe, so it does not compose the stripe class. Each
 * variant sets the partial's inputs (base color + per-variant foreground chroma)
 * plus the banner-local focus-ring color.
 *
 * NOTE (CSS audit, Batch D): the soft surface is synthesized rather than read
 * from the `--cinder-color-{status}-{bg,fg,border}` triples because the
 * dark-theme triple background sits ~8 oklch-L points lighter (28% vs 20% L),
 * exceeding the 0.02 ΔL threshold. See documentation/css-audit/status-triple-equivalence.md.
 * ---------------------------------------- */

  /* Neutral is a notice, not a status, so it takes the neutral tokens instead of the status-surface
   * recipe, which tints from a status hue. */
  .cinder-banner[data-cinder-variant='neutral'] {
    --_cinder-banner-ring: var(--cinder-ring-color);
    border-color: var(--cinder-status-neutral-border);
    background: var(--cinder-status-neutral-background);
    color: var(--cinder-status-neutral-text);
  }

  .cinder-banner[data-cinder-variant='info'] {
    --_cinder-banner-ring: var(--cinder-status-info-text);
    --_cinder-status-base: var(--cinder-status-info-solid);
    --_cinder-status-fg-chroma-light: 0.12;
    --_cinder-status-fg-chroma-dark: 0.12;
  }

  .cinder-banner[data-cinder-variant='success'] {
    --_cinder-banner-ring: var(--cinder-status-success-text);
    --_cinder-status-base: var(--cinder-status-success-solid);
    --_cinder-status-fg-chroma-light: 0.14;
    --_cinder-status-fg-chroma-dark: 0.12;
  }

  .cinder-banner[data-cinder-variant='warning'] {
    --_cinder-banner-ring: var(--cinder-status-warning-text);
    --_cinder-status-base: var(--cinder-status-warning-solid);
    --_cinder-status-fg-chroma-light: 0.16;
    --_cinder-status-fg-chroma-dark: 0.14;
  }

  .cinder-banner[data-cinder-variant='danger'] {
    --_cinder-banner-ring: var(--cinder-status-danger-text);
    --_cinder-status-base: var(--cinder-status-danger-solid);
    --_cinder-status-fg-chroma-light: 0.18;
    --_cinder-status-fg-chroma-dark: 0.16;
  }

  /* ----------------------------------------
 * Feature
 *
 * An announcement, not a status (COR-2363): a rounded block with an indigo wash (the accent mixed
 * 9% over the surface) and a soft radial glow at the inline end, with no border and no status
 * colour. The glyph art sits in a 48px accent disc with an 8px translucent halo, the title is
 * 16px bold over one muted line, and the actions trail at the inline end. The banner is its own
 * inline-size container, so below 560px of its own width the actions drop under the words in
 * the body column, whatever the viewport.
 * ---------------------------------------- */

  .cinder-banner[data-cinder-variant='feature'] {
    --_cinder-banner-ring: var(--cinder-ring-color);
    --_cinder-banner-glow-at: 100% 50%;
    container-type: inline-size;
    container-name: cinder-banner;
    /* The art, the words, the trailing actions and the dismiss button. Below 560px the actions
     * move to the second row of the words' column and their own track collapses to nothing. */
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    padding-block: var(--cinder-space-4);
    padding-inline: var(--cinder-space-5);
    border: 0;
    border-radius: var(--cinder-radius-surface);
    background:
      radial-gradient(
        ellipse 45% 140% at var(--_cinder-banner-glow-at),
        color-mix(in oklch, var(--cinder-accent-solid) 18%, transparent),
        transparent 70%
      ),
      color-mix(in oklch, var(--cinder-surface), var(--cinder-accent-solid) 9%);
    color: var(--cinder-text-default);
  }

  .cinder-banner[data-cinder-variant='feature']:dir(rtl) {
    --_cinder-banner-glow-at: 0% 50%;
  }

  /* One icon in a 48px accent disc, with an 8px translucent halo the margin leaves room for. */
  .cinder-banner__art {
    display: inline-flex;
    grid-column: 1;
    grid-row: 1;
    align-items: center;
    justify-content: center;
    inline-size: 3rem;
    block-size: 3rem;
    margin: var(--cinder-space-2);
    margin-inline-end: calc(var(--cinder-space-2) + var(--cinder-space-4));
    border-radius: var(--cinder-radius-full);
    background: var(--cinder-accent-solid);
    color: var(--cinder-accent-contrast);
    box-shadow: 0 0 0 var(--cinder-space-2)
      color-mix(in oklch, var(--cinder-accent-solid) 16%, transparent);
  }

  .cinder-banner__art > :where(svg) {
    inline-size: 1.5rem;
    block-size: 1.5rem;
  }

  /* The words read muted under a 16px bold title in the default text colour. */
  .cinder-banner[data-cinder-variant='feature'] > .cinder-banner__content {
    color: var(--cinder-text-muted);
  }

  .cinder-banner[data-cinder-variant='feature'] .cinder-banner__title {
    color: var(--cinder-text-default);
    font-size: var(--cinder-text-lg);
    font-weight: var(--cinder-font-bold);
    line-height: var(--cinder-leading-snug);
  }

  .cinder-banner[data-cinder-variant='feature'] .cinder-banner__text {
    color: var(--cinder-text-muted);
  }

  /* The actions trail on the inline end of the first row, on one line. */
  .cinder-banner[data-cinder-variant='feature'] > .cinder-banner__actions {
    grid-column: 3;
    grid-row: 1;
    flex-wrap: nowrap;
    justify-self: end;
    margin-inline-start: var(--cinder-space-4);
  }

  .cinder-banner[data-cinder-variant='feature'] > .cinder-banner__dismiss {
    grid-column: 4;
  }

  /* Below 560px of the banner's own width, the actions drop under the words in the body column,
   * and wrap between buttons (never inside one). */
  @container cinder-banner (max-width: 34.99rem) {
    .cinder-banner[data-cinder-variant='feature'] > .cinder-banner__actions {
      grid-column: 2;
      grid-row: 2;
      flex-wrap: wrap;
      justify-self: start;
      margin-inline-start: 0;
    }
  }

  /* ----------------------------------------
 * Forced-colors / high-contrast
 * ---------------------------------------- */

  @media (forced-colors: active) {
    .cinder-banner {
      border-block: 1px solid CanvasText;
    }

    /* The feature banner draws no border and paints its wash with color-mix, which forced colours
     * drop; give it the system edge and canvas instead. */
    .cinder-banner[data-cinder-variant='feature'] {
      border: 1px solid CanvasText;
      background: Canvas;
    }

    .cinder-banner__art {
      border: 1px solid CanvasText;
      box-shadow: none;
    }

    /* `color-mix` against transparent is unreliable in forced-colors mode; pin to ButtonFace.
   * Nested under @media (hover: hover) to suppress sticky-hover on touch. */
    @media (hover: hover) {
      .cinder-banner__dismiss:hover {
        background: ButtonFace;
      }
    }

    .cinder-banner__dismiss:focus-visible {
      outline: var(--cinder-ring-width) solid ButtonText;
      outline-offset: 3px;
      box-shadow: none;
    }
  }
}
