/**
 * patternpaste/marquee: the resting state.
 *
 * This is the finished composition a visitor sees if view.js never loads: the
 * introduction, then still rows of items clipped by the band, every authored
 * item where the server put it, 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 revert.
 *
 * THE BLOCK STATES NO COLOUR AND NO FONT. Every mark is `currentColor`, mixed
 * down with `color-mix` where a surface is wanted, and the viewport's ground is
 * TRANSPARENT: the composite's band is the ground, so the rows sit in the
 * buyer's colour rather than ours. Every face is the theme's.
 *
 * THE RULE THE EFFECT ACTUALLY DEPENDS ON is `width: max-content` on the run:
 * it is what lets a row be longer than its frame instead of wrapping, which is
 * the whole of a marquee. Everything else here is composition.
 */

.wp-block-patternpaste-marquee {
  /* The gap between items, and the item's own size. Both sizes default to
   * `auto`, which is the INTRINSIC width and height of whatever the author put
   * in the item: a word is as wide as the word. render.php writes an inline
   * `--patternpaste-item-w` / `--patternpaste-item-h` only when the author
   * stated a number, so an untouched marquee carries no inline copy of what is
   * already here and a row of words is never boxed into a size it did not ask
   * for. */
  --patternpaste-gap: 22px;
  /* WIDTH IS INTRINSIC, HEIGHT IS NOT, and that asymmetry is the composition
   * rather than an oversight. A row's items must share one height or the row
   * is not a row: measured on the first fixture, a mixed run of pictures and
   * words at intrinsic height left the words floating in the middle of a band
   * the pictures alone decided. Width stays intrinsic because that is what
   * makes a ticker read as language: a short word takes a short slot, a long
   * one takes a long slot, and a picture takes whatever its aspect ratio asks
   * for at the row's height. */
  --patternpaste-item-w: auto;
  --patternpaste-item-h: clamp(4.5rem, 11vw, 10rem);
  /* A PICTURE ITEM IS A SLOT, NOT ITS OWN SIZE. `auto` cannot be used for an
   * item holding a photograph: intrinsic sizing resolves a percentage height to
   * `auto`, so the item asks for the image FILE's natural width, and the render
   * measured on the first fixture was a 620px slot with a thumbnail floating in
   * the middle of it. So a media item takes a landscape slot derived from the
   * row's own height, the picture fills it with `object-fit: cover`, and every
   * picture in the marquee is the same shape whatever was uploaded. 1.6 is a
   * touch wider than 3:2, so a landscape photograph is barely cropped and a
   * portrait one is honestly a landscape slot rather than a sliver.
   *
   * It is the SAME attribute as the item width: patternpasteItemWidth writes
   * both properties, so an author who states a width states it for pictures and
   * words alike, and one who states nothing gets words at their own width and
   * pictures at a shape. */
  --patternpaste-media-ratio: 1.6;
  --patternpaste-media-w: calc(var(--patternpaste-item-h) * var(--patternpaste-media-ratio));
  /* The row count and the SHORTEST row's item count, both written inline by
   * render.php. The values here are only what a marquee rendered by something
   * that is not render.php would fall back to. */
  --patternpaste-rows: 2;
  --patternpaste-per-row: 3;
  /* How far the fade eats into each side of the frame. Wide enough that an
   * item dissolves rather than blinking out, narrow enough that a short frame
   * on a phone still has a middle. */
  --patternpaste-fade-width: clamp(2rem, 7vw, 7rem);
  /* 0 to 1 pointer energy, written by view.js in coarse steps. Drives the
   * frame's own tell and nothing else, so a reader with no script sees none. */
  --patternpaste-rate: 0;

  display: block;
  position: relative;
}

/* THE FRAME. It clips its own overflow rather than trusting the theme, and it
 * carries `data-patternpaste-stage`, which is the block saying its content
 * moves THROUGH this box on purpose: check-responsive then judges this box
 * against the document instead of the items inside it. The exemption is the
 * block's to claim and a payload may not forge it (check-portability's
 * payload-data-hook). */
.patternpaste-marquee__viewport {
  position: relative;
  overflow: hidden;
  /* The control surface for the pointer scrub. `touch-action` is set on the
   * live rails below, never here, so a still marquee leaves the finger alone. */
  /* No stated height: the band is exactly its rows, which is the only thing it
   * could be once the row height is the one number that decides a row. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--patternpaste-gap);
  /* No ground of its own: the section behind it is the ground. */
  background: transparent;
}

/* The introduction sits above the frame, outside anything that moves, so its
 * links and buttons are ordinary clickable content. */
.patternpaste-marquee__intro {
  margin-block-end: var(--patternpaste-gap);
}

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

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

/* A ROW. Clips its own overflow so an item leaving one row cannot appear over
 * its neighbour, and lays its run out on one line. */
.patternpaste-marquee__rail {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-width: 0;
  /* A rail is exactly as tall as one item, so the rows are level whatever the
   * items hold and the band is their sum. Not `flex: 1 1`: that let a stated
   * band stretch the rails past the row height and left the items floating in
   * them, which is why the band knob is gone. */
  flex: none;
  height: var(--patternpaste-item-h);
}

/* UNSTATED, THE ROW IS A FLOOR, NOT A CLIP (2026-09-14). The default height is
 * a guess at the words, and a theme's line-height decides whether they fit:
 * measured on `services-marquee-ticker` in twentytwentythree, a 7.5vw heading
 * at 1.4 plus its number ran to 167px in a 143px row, cutting every descender,
 * and at 390px the numbers went too. A words item and its rail grow to what
 * they hold; a picture item keeps the slot. A STATED Item height still clips,
 * because a card that states a height has asked for exactly that. */
.wp-block-patternpaste-marquee:not([style*='--patternpaste-item-h']) .patternpaste-marquee__rail {
  height: auto;
  min-height: var(--patternpaste-item-h);
}

.wp-block-patternpaste-marquee:not([style*='--patternpaste-item-h']) .patternpaste-marquee__item:not(:has(img)) {
  height: auto;
  min-height: var(--patternpaste-item-h);
}

/* AND THE INK, NOT JUST THE BOX. A tight heading line-height draws a
 * descender below its own line box: twentytwentyfive sets 1.125, and the "g"
 * of `services-marquee-ticker` was cut by the rail even once every box fitted.
 * Padding in the text's own em scales with the type, and the floor above grows
 * the row to hold it. */
.wp-block-patternpaste-marquee:not([style*='--patternpaste-item-h']) .patternpaste-marquee__item:not(:has(img)) :is(h1, h2, h3, h4, h5, h6, p),
.wp-block-patternpaste-marquee:not([style*='--patternpaste-item-h']) .patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group']:not(:has(img)) > :is(h1, h2, h3, h4, h5, h6, p) {
  padding-block: 0.15em;
}

/* THE MOVING ELEMENT, and the one rule the effect depends on. `max-content` is
 * what lets the run be longer than the frame instead of wrapping; without it
 * every marquee is a paragraph. `flex: none` keeps the flex parent from
 * shrinking it back to the frame's width, which is the same failure wearing a
 * different hat. */
.patternpaste-marquee__run {
  display: flex;
  align-items: center;
  flex: none;
  width: max-content;
  gap: var(--patternpaste-gap);
  /* Never a start offset: the run rests where the server put it. view.js sets
   * the offset at init and the revert takes it back off. */
}

.patternpaste-marquee__item {
  flex: none;
  width: var(--patternpaste-item-w);
  height: var(--patternpaste-item-h);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-sizing: border-box;
}

/* THE ITEM'S HEIGHT IS SHARED, NOT TAKEN. An item holding a picture AND a
 * caption is the common case, and the picture must give way to the words:
 * measured on the first fixture, a figure at the full row height pushed every
 * caption past the item's clip and the block silently ate content the author
 * had typed. The figure flexes and the words keep their intrinsic height, so
 * whatever else is in the item is always the thing that fits. */
/* An item carrying a picture takes the slot; one carrying only words takes the
 * width of the words. `:has()` is the only way to tell them apart, since what
 * an item holds is the author's business and the server does not inspect it. */
.patternpaste-marquee__item:has(img) {
  width: var(--patternpaste-media-w);
}

/* And its group takes the slot rather than shrink-wrapping, because
 * `max-content` on a group holding a full-width picture is the PICTURE FILE's
 * natural width: measured on the first fixture, the group ran to 1600px inside
 * a 176px item and carried every caption off the end of the clip. A words-only
 * item still shrink-wraps, which is the rule above. */
.patternpaste-marquee__item:has(img) .patternpaste-marquee__item-body > * {
  width: 100%;
}

.patternpaste-marquee__item-body {
  min-width: 0;
  height: 100%;
}

/* THE AUTHOR'S GROUP IS THE COLUMN, not this wrapper. An item's content is one
 * core/group (the slot rule), so the group sits BETWEEN the wrapper and the
 * picture and the words: laying the wrapper out as a column arranged one child
 * and left the figure and the heading to the group's own layout, which sized
 * the figure to the whole item and pushed every caption past the clip. Measured
 * on the first fixture: not one of the six picture items showed its caption. */
.patternpaste-marquee__item-body > * {
  height: 100%;
  /* AND IT SHRINK-WRAPS. An item's group is very often a `constrained` one,
   * which takes the THEME's content size: measured on the first fixture, every
   * picture item became a 620px slot with a thumbnail floating in the middle of
   * it. An item is as wide as what is in it, and the block's frame is what says
   * so, because the group's own layout has no idea it is on a marquee. */
  width: max-content;
  max-width: none;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
}

/* THE AUTHOR'S JUSTIFICATION WINS (2026-09-13). An item's group that states a
 * vertical flex layout with a justification carries core's
 * `is-content-justification-*` class, and centring over it hid the one control
 * that says where a card's words start: `testimonial-marquee-editorial` set its
 * voices left and still got every name centred under a left-set quote. A group
 * that states nothing is centred as before. */
.patternpaste-marquee__item-body > .is-content-justification-left {
  align-items: flex-start;
}

.patternpaste-marquee__item-body > .is-content-justification-right {
  align-items: flex-end;
}

.patternpaste-marquee__item-body > .is-content-justification-stretch {
  align-items: stretch;
}

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

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

/* An image inside an item fills it rather than setting its own size, so a row
 * of pictures is a row and not a staircase. */
/* A picture takes the row's height and whatever width its own aspect ratio
 * asks for, so a row of pictures is a row and not a staircase, and a picture
 * beside a word is the same height as the word's plate. `width: auto` is what
 * keeps the aspect ratio the author set on the image block; forcing the width
 * to the item would crop every picture to one shape. */
.patternpaste-marquee__item figure {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  margin: 0;
}

/* `figure img`, NOT `img`: core's `.wp-block-image img { height: auto }` has
 * the same weight and loads later, so the picture fell back to its own aspect
 * ratio and ran 28px under the caption on `gallery-marquee-mounts`
 * (2026-09-14). */
.patternpaste-marquee__item figure img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

/* Text inside an item never wraps: a marquee item is one slot wide and a
 * second line would make the row ragged again. */
.patternpaste-marquee__item :is(h1, h2, h3, h4, h5, h6, p) {
  white-space: nowrap;
  margin-block: 0;
}

/* A STATED WIDTH IS A CARD, AND A CARD'S WORDS WRAP (2026-09-13). An item at
 * its intrinsic width is a word or a caption and stays on one line; an author
 * who states Item width has asked for a slot of that size, and a quote or a
 * paragraph in it has to break inside the slot rather than run off its clip.
 * Measured on `testimonial-marquee`: every quote longer than the card was cut
 * at its edge. Keyed off the inline property itself, which render.php, edit.jsx
 * and the storefront drawer all write the same way, so the rule follows the
 * knob wherever it is turned. The group takes the slot so its text has a
 * width to wrap to; the item's height still clips, so a card that wants more
 * lines wants a taller Item height. */
.wp-block-patternpaste-marquee[style*='--patternpaste-item-w'] .patternpaste-marquee__item-body,
.wp-block-patternpaste-marquee[style*='--patternpaste-item-w'] .patternpaste-marquee__item-body > * {
  width: 100%;
}

.wp-block-patternpaste-marquee[style*='--patternpaste-item-w'] .patternpaste-marquee__item :is(h1, h2, h3, h4, h5, h6, p) {
  white-space: normal;
}

/* A PICTURE NESTED IN A ROW IS AN AVATAR, NOT THE ITEM'S PICTURE. The figure
 * rule above makes a picture that is a direct child of the item's group fill
 * the slot; a figure one group deeper sits beside words, and growing it split
 * every `testimonial-marquee` card in half with the photograph floating in the
 * left one (2026-09-13). It keeps the size its image block states. */
.patternpaste-marquee__item-body > * > :not(figure) figure {
  flex: none;
  width: auto;
}

/* THE PLATE: an item as a card. A ground mixed down from `currentColor` and a
 * hairline of the same, so the card is visible on the theme's own ground
 * whichever way round that ground is, and states no colour of its own. */
.wp-block-patternpaste-marquee[data-patternpaste-plate='true'] .patternpaste-marquee__item {
  padding: clamp(0.75rem, 1.4vw, 1.25rem);
  background-color: color-mix(in srgb, currentColor 7%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
}

/* Off, whatever the author put in the item IS the item. */
.wp-block-patternpaste-marquee[data-patternpaste-plate='false'] .patternpaste-marquee__item {
  padding: 0;
  background-color: transparent;
  border: 0;
}

/* THE SEPARATOR. Drawn, never a glyph: a character would be a font this block
 * does not state and cannot promise the reader's device has. A dot of
 * currentColor is the same mark everywhere.
 *
 * IT IS ALWAYS IN THE MARKUP AND HIDDEN HERE, so the storefront's Motion drawer
 * can turn it on as well as off: the drawer rewrites the attribute in the
 * browser and cannot add an element the server never rendered. */
.wp-block-patternpaste-marquee[data-patternpaste-mark='false'] .patternpaste-marquee__mark {
  display: none;
}

.patternpaste-marquee__mark {
  flex: none;
  align-self: center;
  width: 0.5em;
  height: 0.5em;
  border-radius: 50%;
  background-color: color-mix(in srgb, currentColor 55%, transparent);
}

/* THE FADED EDGES. A mask, never a painted gradient: a mask makes the edge
 * TRANSPARENT, so whatever the theme painted behind the section is what shows
 * through, in every theme. Left and right only, because a marquee runs
 * horizontally and its edges are where items arrive and leave. */
.wp-block-patternpaste-marquee[data-patternpaste-fade='true'] .patternpaste-marquee__viewport {
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0,
    black var(--patternpaste-fade-width),
    black calc(100% - var(--patternpaste-fade-width)),
    transparent 100%
  );
  mask-image: linear-gradient(
    to right,
    transparent 0,
    black var(--patternpaste-fade-width),
    black calc(100% - var(--patternpaste-fade-width)),
    transparent 100%
  );
}

/* A ROW IS ALWAYS A CONTROL, so it always says so. There is no switch to turn
 * this off: WCAG 2.2.2 is a Level A criterion and a marquee meets every one of
 * its conditions, so the way to stop a row has to be there. */
.patternpaste-marquee__rail {
  cursor: pointer;
}

/* A LIVE ROW TAKES A SIDEWAYS FINGER, and only a sideways one: the browser
 * keeps the vertical pan and the pinch, so a swipe that starts on the band
 * still scrolls the page, and view.js gets the horizontal drag. Keyed off the
 * live class, so a still marquee (no script, reduced motion, the editor)
 * leaves touch exactly as the theme had it. */
.patternpaste-marquee--live .patternpaste-marquee__rail {
  touch-action: pan-y pinch-zoom;
}

/* A focused rail has to be visible against a ground this block does not know,
 * so the ring is currentColor with an offset gap rather than a colour. */
.patternpaste-marquee__rail:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -2px;
}

/* A held row says so. Added by view.js and removed by the revert. */
.patternpaste-marquee__rail.is-held {
  opacity: 1;
}

/* THE EDITOR CANVAS, and the one place it deliberately differs from the page.
 *
 * On the page a row runs off both edges and only a fraction of it is visible at
 * once; an author editing that would spend the session scrolling a strip
 * sideways to reach item nineteen. So the canvas WRAPS: every item is laid out
 * at the row's own height and size, in reading order, all of them reachable.
 * What is missing is only the horizontal run, which is the half that moves and
 * the half the editor never shows anyway.
 *
 * The children here are the author's core/group blocks themselves: InnerBlocks
 * owns them and cannot be asked to deal them into the item wrappers render.php
 * builds, so every rule below reaches the group directly. */
.patternpaste-marquee__canvas {
  display: flex;
  /* ROW, STATED. The canvas carries the viewport's class as well, and that rule
   * lays the frame out as a COLUMN of rails; without restating the direction
   * here the editor stacked every item full-width down the page, which is what
   * the first editor.png showed. */
  flex-direction: row;
  /* CENTRED, so the space a wrapped row cannot fill splits evenly either side
   * rather than reading as a missing item on the right. Never stretched: every
   * item stays the size the page draws it. */
  justify-content: center;
  flex-wrap: wrap;
  align-items: stretch;
  align-content: flex-start;
  height: auto;
  overflow: visible;
  gap: var(--patternpaste-gap);
}

/* THE SLOT RULE, VISIBLE ON THE CANVAS. A top-level group is an item and
 * everything else is the introduction that renders ABOVE the frame, and an
 * author cannot act on that rule if both look the same: the first editor.png
 * dressed the eyebrow and the heading as items in the middle of the run. The
 * editor writes the block name onto every wrapper as `data-type`, which is the
 * one place the canvas can read the slot rule from. */
.patternpaste-marquee__canvas > .block-editor-block-list__block:not([data-type='core/group']) {
  flex: 1 0 100%;
  margin: 0;
}

.patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group'] {
  flex: none;
  width: var(--patternpaste-item-w);
  height: var(--patternpaste-item-h);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-sizing: border-box;
  margin: 0;
}

.patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group']:has(img) {
  width: var(--patternpaste-media-w);
}

/* The page's floor rule, on the canvas. */
.wp-block-patternpaste-marquee:not([style*='--patternpaste-item-h']) .patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group']:not(:has(img)) {
  height: auto;
  min-height: var(--patternpaste-item-h);
}

/* THE GROUP IS THE COLUMN HERE TOO. On the canvas the author's group IS the
 * flex box above, so without a direction its picture and its words were laid
 * side by side: every `gallery-marquee-mounts` frame showed a thumbnail with
 * its title beside it (2026-09-14). These mirror the page's item-body rules,
 * one level up. */
.patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group'] {
  flex-direction: column;
  gap: 0.4em;
}

.patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group'] > figure {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  max-width: none;
  margin: 0;
}

.patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group'] > figure :is(img, .components-resizable-box__container, .components-placeholder) {
  display: block;
  width: 100% !important;
  height: 100% !important;
  max-width: none;
  object-fit: cover;
}

.patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group'] > :is(h1, h2, h3, h4, h5, h6, p) {
  margin-block: 0;
}

.wp-block-patternpaste-marquee[data-patternpaste-plate='true'] .patternpaste-marquee__canvas > .block-editor-block-list__block[data-type='core/group'] {
  padding: clamp(0.75rem, 1.4vw, 1.25rem);
  background-color: color-mix(in srgb, currentColor 7%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
}

/* The appender sits after the items rather than inside one of them. */
.patternpaste-marquee__add {
  display: flex;
  align-items: center;
  padding: clamp(0.75rem, 1.4vw, 1.25rem) 0;
}

/* An empty marquee still shows a frame, so the block has somewhere to drop the
 * first item into. */
.patternpaste-marquee.is-editing.is-empty .patternpaste-marquee__canvas {
  min-height: 8rem;
  border: 1px dashed color-mix(in srgb, currentColor 30%, transparent);
}

/* A canvas is a workspace and never a control: the pause cursor and the focus
 * ring belong to the page, where a rail is something a reader can press. */
.patternpaste-marquee.is-editing .patternpaste-marquee__canvas {
  cursor: auto;
}

/* A marquee in print is a still row: nothing runs on paper. */
@media print {

  .patternpaste-marquee__run {
    flex-wrap: wrap;
  }
}
