/**
 * patternpaste/stack: the resting state.
 *
 * This is the finished composition a visitor sees if view.js never loads: a
 * column of cards, in order, each one its own height, with a gap between
 * them, nothing hidden and nothing waiting to be undone. No opacity: 0, no
 * transform to reverse, no start state. Motion is added on top by view.js and
 * removed again by the revert.
 *
 * THE BLOCK STATES NO COLOUR AND NO FONT. A drawn card takes the theme's own
 * plate role as its ground and its text, falling through to base and
 * contrast, through the same preset chains every payload in the catalogue uses, because a pile of cards
 * has to be OPAQUE and a ground mixed down from currentColor is not. Every
 * other mark is currentColor mixed down. With the plate off the author's own
 * group is the card and paints its own ground.
 *
 * THE LIVE STATE IS ONE SCREEN. view.js adds `patternpaste-stack--live`, and
 * under it the viewport is the height of the screen and the deck is a grid
 * with every card in the one cell, so all of them sit on top of each other at
 * the height of the tallest, and view.js moves them from there. That is the
 * only layout the class changes; the cards, their plates and their copy are
 * the same rules in both states, which is what keeps the resting column and
 * the first frame of the deck the same card.
 */

.wp-block-patternpaste-stack {
  /* HOW WIDE THE DECK IS, capped, inside a band that is still edge to edge.
   * Written inline by render.php only when the author moved the control off
   * the number this settles at (920), so an untouched deck stays fluid. */
  --patternpaste-width: min(57.5rem, 100%);
  /* A CARD'S MINIMUM HEIGHT. 0 is "its own content", and the default. */
  --patternpaste-card: 0px;
  /* The gap between cards AT REST. The live deck has none: the cards overlap. */
  --patternpaste-gap: clamp(1rem, 2.5vw, 1.5rem);
  /* THE PILE. How much of each buried card shows above the one on top of it
   * (the peek, in pixels) and how many levels keep moving (the depth); cards
   * deeper than the depth freeze there, so the pile cannot grow past the top
   * of a short screen. Both are read back by view.js off the resolved styles
   * and written inline by render.php off their defaults only. */
  --patternpaste-peek: 26px;
  --patternpaste-depth: 4;
  /* THE PILE'S HEIGHT, which is where the live deck's top edge has to leave
   * room. view.js overrides it on a coarse pointer, where the peek is scaled
   * down, and removes the override on revert. */
  --patternpaste-pile: calc(var(--patternpaste-peek) * var(--patternpaste-depth));
  /* The card's corner and its padding, one number each. */
  --patternpaste-radius: 1rem;
  --patternpaste-pad: clamp(1.5rem, 3vw, 2.5rem);
  /* THE GUTTER, and it is the catalogue's own, capped at its measure the way
   * the chapters block caps its spread: past 1600px the inset grows so the
   * content is centred at exactly the measure. A composite's masthead and
   * hand-off row write the same expression and land on the same two edges. */
  --patternpaste-gutter: max(clamp(1.25rem, 4vw, 4rem), calc((100% - 1600px) / 2));

  display: block;
  position: relative;
}

/* The introduction sits above the frame, outside anything that pins, so its
 * links and buttons are ordinary clickable content. */
.patternpaste-stack__intro {
  box-sizing: border-box;
  padding-inline: var(--patternpaste-gutter);
  margin-block-end: var(--patternpaste-gap);
}

.patternpaste-stack__intro > :first-child {
  margin-block-start: 0;
}

.patternpaste-stack__intro > :last-child {
  margin-block-end: 0;
}

/* THE VIEWPORT, at rest: a padded band the deck sits in. It is the pin target
 * and it clips its own overflow, because in the live state the cards ride up
 * from below its bottom edge and the theme must not be trusted to hide them. */
.patternpaste-stack__viewport {
  position: relative;
  box-sizing: border-box;
  padding-inline: var(--patternpaste-gutter);
  overflow: hidden;
}

/* THE DECK, at rest: a column of cards with a gap. */
.patternpaste-stack__deck {
  display: flex;
  flex-direction: column;
  gap: var(--patternpaste-gap);
  box-sizing: border-box;
  width: 100%;
  max-width: var(--patternpaste-width);
  margin-inline: auto;
}

/* A CARD. `overflow: hidden` so the shade's corners follow the card's, and so
 * a photograph the author put in a card is clipped to it. */
.patternpaste-stack__card {
  display: flex;
  flex-direction: column;
  position: relative;
  box-sizing: border-box;
  min-height: var(--patternpaste-card);
  min-width: 0;
  border-radius: var(--patternpaste-radius);
  overflow: hidden;
}

.patternpaste-stack__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  position: relative;
  z-index: 1;
}

/* The author's opaque group must cover the whole grid cell, including when
 * another card determines its height. Its own layout still owns the content. */
.patternpaste-stack__body > .wp-block-group {
  box-sizing: border-box;
  flex: 1;
  width: 100%;
}

.patternpaste-stack__body > :first-child {
  margin-block-start: 0;
}

.patternpaste-stack__body > :last-child {
  margin-block-end: 0;
}

/* THE PLATE: the card drawn. The theme's PLATE role as the ground and its
 * text as the ink, falling through to base and contrast, the same chain every
 * plate in the catalogue writes. The role rung is what keeps a card off the
 * section's own ground: a section variation redefines `base` for everything
 * inside it, so a card on bare `base` disappears into an accent band (seen
 * 2026-09-05 on the pricing deck in an accent section, every card the band's
 * own purple), while `role-plate` is derived per section as a surface that
 * differs from the ground and can carry text. A card is OPAQUE either way,
 * which a card with another card under it has to be; a hairline and a shadow
 * in the ink mixed down. */
.wp-block-patternpaste-stack[data-patternpaste-plate='true'] .patternpaste-stack__card {
  padding: var(--patternpaste-pad);
  color: var(--wp--preset--color--role-plate-text, var(--wp--preset--color--contrast, var(--wp--preset--color--black)));
  background-color: var(--wp--preset--color--role-plate, var(--wp--preset--color--base, var(--wp--preset--color--white)));
  border: 1px solid color-mix(in srgb, currentColor 14%, transparent);
  box-shadow: 0 18px 34px color-mix(in srgb, currentColor 8%, transparent);
}

/* Off, the author's group is the card: no padding, no ground, no line. */
.wp-block-patternpaste-stack[data-patternpaste-plate='false'] .patternpaste-stack__card {
  padding: 0;
  background-color: transparent;
  border: 0;
  box-shadow: none;
}

/* THE SHADE: the veil view.js lays over a buried card, in the card's own ink.
 * Rendered on every render and shown only in the live state, where view.js
 * sets its opacity per level; with no script there is no pile and nothing to
 * veil, so it takes no space and paints nothing. This is not a start state: a
 * resting column has no veil, and `display: none` is that fact rather than an
 * opacity waiting to be undone. */
.patternpaste-stack__shade {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  background: currentColor;
  pointer-events: none;
}

/* THE STEP COUNTER. Hidden at rest for the same reason as the shade: it counts
 * cards as they lock, and nothing locks in a column. */
.patternpaste-stack__count {
  display: none;
}

/* ---------------------------------------------------------------------------
 * THE LIVE STATE. Added by view.js after boot.js's gates, removed on revert.
 * ------------------------------------------------------------------------- */

/* One screen, the deck centred in it, the cards clipped as they arrive.
 * `svh` is the small viewport, so a phone's toolbar can never make the frame
 * taller than what is visible; `vh` is the fallback for a browser without it. */
.patternpaste-stack--live .patternpaste-stack__viewport {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100vh;
  height: 100svh;
  padding-block: clamp(2rem, 6vh, 3.5rem);
}

/* THE DECK AS A GRID: every card in the one cell, so the deck is the height of
 * the tallest card and every card is that height, and the pile view.js builds
 * is a pile of equal cards. The top margin is the room the buried cards will
 * need above the card on top. */
.patternpaste-stack--live .patternpaste-stack__deck {
  display: grid;
  gap: 0;
  margin-block-start: var(--patternpaste-pile);
}

.patternpaste-stack--live .patternpaste-stack__card {
  grid-area: 1 / 1;
  /* A later card lands on top. The index is the server's, off the DOM order. */
  z-index: var(--patternpaste-i, 1);
  will-change: transform;
}

.patternpaste-stack--live .patternpaste-stack__shade {
  display: block;
}

/* The counter, in the frame's TOP corner, on the same gutter as the intro.
 * Only while live and only when asked for. The top and not the bottom, because
 * the arriving card rides up through the bottom of the frame and on a phone
 * the deck is the frame's whole width: measured 2026-09-05 at 390, a counter
 * in the bottom corner sat over the fourth card's copy every time one
 * arrived. Nothing ever travels through the top padding. */
.patternpaste-stack--live[data-patternpaste-count='true'] .patternpaste-stack__count {
  display: flex;
  position: absolute;
  inset-inline-start: max(var(--patternpaste-gutter), calc((100% - var(--patternpaste-width)) / 2));
  inset-block-start: clamp(1rem, 3vh, 2rem);
  z-index: 20;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  line-height: 1;
}

.patternpaste-stack__step {
  position: relative;
  margin: 0;
  padding-block-end: 0.5rem;
  opacity: 0.45;
}

/* The current step carries a rule under it, drawn and not typed. */
.patternpaste-stack__step::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
}

.patternpaste-stack__step.is-current {
  opacity: 1;
}

.patternpaste-stack__step.is-current::after {
  transform: scaleX(1);
}

/* ---------------------------------------------------------------------------
 * THE EDITOR CANVAS. The resting state, with the slot rule made visible.
 * ------------------------------------------------------------------------- */

/* The canvas is the deck: a column of cards. Every layout property the front
 * end's rule sets is restated, because InnerBlocks' wrapper takes the deck's
 * class and inherits nothing else. */
.patternpaste-stack__canvas {
  display: flex;
  flex-direction: column;
  gap: var(--patternpaste-gap);
  width: 100%;
  max-width: var(--patternpaste-width);
  margin-inline: auto;
}

/* A CARD ON THE CANVAS: the same plate the page draws, so what an author sees
 * while writing is the card the reader gets. The editor writes the block name
 * onto every wrapper as `data-type`, which is the one place the canvas can
 * see the slot rule from. */
.patternpaste-stack.is-editing[data-patternpaste-plate='true'] .patternpaste-stack__canvas > .block-editor-block-list__block[data-type='core/group'] {
  box-sizing: border-box;
  padding: var(--patternpaste-pad);
  color: var(--wp--preset--color--role-plate-text, var(--wp--preset--color--contrast, var(--wp--preset--color--black)));
  background-color: var(--wp--preset--color--role-plate, var(--wp--preset--color--base, var(--wp--preset--color--white)));
  border: 1px solid color-mix(in srgb, currentColor 14%, transparent);
  border-radius: var(--patternpaste-radius);
  box-shadow: 0 18px 34px color-mix(in srgb, currentColor 8%, transparent);
}

.patternpaste-stack.is-editing .patternpaste-stack__canvas > .block-editor-block-list__block[data-type='core/group'] {
  min-height: var(--patternpaste-card);
  border-radius: var(--patternpaste-radius);
}

/* Anything that is not a group is introduction, and it has to LOOK like it: a
 * rule down its inside edge, so an author can see it will render above the
 * frame rather than in the deck. */
.patternpaste-stack.is-editing .patternpaste-stack__canvas > .block-editor-block-list__block:not([data-type='core/group']) {
  padding-inline-start: 0.75rem;
  border-inline-start: 2px dashed color-mix(in srgb, currentColor 30%, transparent);
}

.patternpaste-stack__add {
  display: flex;
  justify-content: center;
  padding-block: 0.5rem;
}

/* An empty block shows its placeholder and not an empty column. */
.patternpaste-stack.is-editing.is-empty .patternpaste-stack__canvas {
  display: none;
}

@media print {
  .patternpaste-stack--live .patternpaste-stack__viewport {
    display: block;
    height: auto;
    overflow: visible;
  }

  .patternpaste-stack--live .patternpaste-stack__deck {
    display: flex;
    gap: var(--patternpaste-gap);
    margin-block-start: 0;
  }

  .patternpaste-stack--live .patternpaste-stack__card {
    transform: none !important;
  }

  .patternpaste-stack--live .patternpaste-stack__shade,
  .patternpaste-stack--live .patternpaste-stack__count {
    display: none;
  }
}
