/* ============================================================
   BLOCK STYLES — the design vocabulary an admin picks from in
   the editor. One named look per rule, registered in
   functions.php (rev_block_styles) and checked by
   tools/check-block-styles.mjs.

   Selectors are class-only and this file is loaded BOTH on the
   frontend (header.php) and into the editor canvas
   (add_editor_style), from the single copy — that is what makes
   the canvas and the published page identical. Never scope a
   rule here under .rev-landing: that wrapper is frontend markup
   and does not exist in the editor.

   Values are tokens only. See docs/adr/0001-*.md for why the
   list is closed and the editor's per-block CSS box is not the
   answer to a missing look.
   ============================================================ */

/* The two counters the vocabulary keeps — the Numbered card's badge and
   the Eyebrow numbered's chapter index — are created here, once, on the
   page itself. Without this they are created implicitly by whichever
   element first increments one, and a counter's scope is that element,
   its descendants and its FOLLOWING SIBLINGS only: three cards in three
   columns are not siblings, so each would start its own counter and
   every badge would read 1. Reset on the page and there is one counter
   per page, running in document order however deeply the blocks nest.
   WordPress rewrites `body` to the canvas wrapper for the editor
   (add_editor_style), so the canvas counts the same way. */
body{counter-reset:rev-card 0 rev-section 0}

/* Eyebrow — the uppercase monospace section label, on a paragraph.
   ponytail: the hairline is a fixed 52px here, not the frontend's
   draw-in as its section arrives (style.css) — that is set off by
   main.js, which never runs in the editor canvas, so animating here
   would mean the two previews disagree. */
.is-style-eyebrow,
.is-style-eyebrow-plain{
  display:flex;align-items:center;gap:16px;
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
}
.is-style-eyebrow::before{content:'';flex:0 0 52px;height:1px;background:var(--line)}
/* Eyebrow plain — the same label with nothing drawn before it, for a
   section whose heading is already the page's landmark and does not
   want the rule leading into it. It shares Eyebrow's type so the two
   can never drift, and takes the accent instead of the hairline: with
   no rule beside it the label is the only colour above the heading. */
.is-style-eyebrow-plain{color:var(--violet-lt)}

/* Eyebrow numbered — the chapter label, "01 · PLATFORM". The number is
   counted, not typed, the same way .is-style-numbered-card counts its
   index: an admin reordering or deleting a section renumbers the rest
   by moving it, and cannot leave an 03 above an 02. The counter is
   never reset, so it runs down the page in document order, and only a
   label that prints a number increments it — a Divider band used for a
   closing band cannot swallow one. No hairline: the number takes the
   slot the rule had in the design. */
.is-style-eyebrow-number{
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.16em;text-transform:uppercase;color:var(--violet-lt);
  counter-increment:rev-section;
}
.is-style-eyebrow-number::before{content:counter(rev-section,decimal-leading-zero) " · "}

/* Buttons — the call-to-action pair. Geometry is shared; only the
   fill differs, so "which one" is an emphasis decision and not a
   layout one. */
.wp-block-button:is(.is-style-primary,.is-style-secondary,.is-style-primary-arrow,.is-style-secondary-arrow) .wp-block-button__link{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-weight:700;font-size:var(--wp--preset--font-size--small);
  padding:14px 28px;border-radius:10px;text-decoration:none;
  border:1px solid transparent;
  transition:background .2s,border-color .2s,box-shadow .3s,transform .22s cubic-bezier(.22,1,.36,1);
}
.wp-block-button:is(.is-style-primary,.is-style-primary-arrow) .wp-block-button__link{
  background:var(--violet);color:var(--wp--preset--color--white);
}
.wp-block-button:is(.is-style-primary,.is-style-primary-arrow) .wp-block-button__link:hover{
  box-shadow:0 10px 34px -10px rgba(91,60,240,.85);transform:translateY(-1px);
}
.wp-block-button:is(.is-style-secondary,.is-style-secondary-arrow) .wp-block-button__link{
  background:transparent;color:var(--wp--preset--color--white);border-color:var(--line-2);
}
.wp-block-button:is(.is-style-secondary,.is-style-secondary-arrow) .wp-block-button__link:hover{
  background:rgba(255,255,255,.06);transform:translateY(-1px);
}

/* The arrow pair — the same two fills, pointing forward. A separate style
   rather than something laid on top of Primary, because the editor's style
   picker is single-select: a block gets exactly one style (CONTEXT.md).
   The glyph is a mask, not an <img> or an icon font: the shape is drawn here
   and the colour comes from the label via currentColor, so the arrow cannot
   drift from the button it sits in and an admin sources no image. */
.wp-block-button:is(.is-style-primary-arrow,.is-style-secondary-arrow) .wp-block-button__link::after{
  content:'';flex:none;width:17px;height:17px;background:currentColor;
  -webkit-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.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center/contain no-repeat;
  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.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center/contain no-repeat;
  transition:transform .25s cubic-bezier(.22,1,.36,1);
}
.wp-block-button:is(.is-style-primary-arrow,.is-style-secondary-arrow) .wp-block-button__link:hover::after{
  transform:translateX(4px);
}

/* Chips — a paragraph as a pill. Three colourways, one geometry: the
   choice is emphasis, not shape. inline-flex so the pill hugs its
   text instead of stretching to the column, which is also what lets
   consecutive chip paragraphs sit on one line. */
.is-style-chip-violet,
.is-style-chip-green,
.is-style-chip-outline{
  display:inline-flex;align-items:center;gap:9px;
  width:fit-content; /* hugs the label in a grid or flex parent too, as the Badge does */
  padding:9px 18px;border-radius:999px;
  font-size:var(--wp--preset--font-size--small);font-weight:600;
  border:1px solid transparent;
}
/* The fills are the tokens themselves, thinned with color-mix rather than
   re-typed as rgba() — a hand-written rgb() is the violet until someone
   nudges the token, and then it is a shade beside it. */
.is-style-chip-violet{
  background:color-mix(in srgb,var(--violet) 18%,transparent);
  border-color:color-mix(in srgb,var(--violet) 55%,transparent);
  color:var(--wp--preset--color--white);
}
.is-style-chip-green{
  background:color-mix(in srgb,var(--green) 12%,transparent);
  border-color:color-mix(in srgb,var(--green) 42%,transparent);
  color:var(--green);
}
.is-style-chip-outline{
  border-color:var(--line-2);color:var(--muted);
}

/* Badge — the glass pill that labels a headline, on a paragraph. The live dot
   is drawn by the rule, so the pill is a paragraph an admin types into and
   nothing else. Fill and border are white thinned with color-mix rather than a
   hand-written rgba(), for the same reason the chips are. */
.is-style-badge{
  display:inline-flex;align-items:center;gap:10px;
  /* inline-flex hugs the label in flow, but a pill is still a block-level
     paragraph: dropped into a grid or flex container — the Hero is a grid —
     it is an item, and an item stretches to its track. fit-content is what
     makes the pill hug everywhere. */
  width:fit-content;
  padding:9px 20px;border-radius:999px;
  font-size:var(--wp--preset--font-size--small);font-weight:500;
  color:var(--wp--preset--color--white);
  background:color-mix(in srgb,var(--wp--preset--color--white) 8%,transparent);
  border:1px solid color-mix(in srgb,var(--wp--preset--color--white) 24%,transparent);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
}
.is-style-badge::before{
  content:'';flex:none;width:8px;height:8px;border-radius:50%;
  background:var(--green);
  animation:rev-badge-pulse 2.2s ease-in-out infinite;
}
@keyframes rev-badge-pulse{
  0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--green) 60%,transparent)}
  70%    {box-shadow:0 0 0 7px transparent}
}
/* The frontend's blanket reduced-motion rule is scoped under .rev-landing,
   which the editor canvas has no wrapper for — the pulse carries its own. */
@media (prefers-reduced-motion:reduce){
  .is-style-badge::before{animation:none}
}

/* Check list — the row of reassurances, on a list. The circled tick is masked
   from the token green, so an admin sources no images and the ticks cannot
   arrive in the wrong colour.
   ponytail: the type is the small preset (15px) — a size that is not on the
   scale does not exist here (docs/adr/0001-*.md). */
.is-style-check-list{list-style:none;padding-left:0;display:flex;flex-wrap:wrap;gap:14px 28px}
.is-style-check-list li{
  display:flex;align-items:center;gap:8px;
  font-size:var(--wp--preset--font-size--small);
  color:color-mix(in srgb,var(--wp--preset--color--white) 80%,transparent);
}
.is-style-check-list li::before{
  content:'';flex:none;width:16px;height:16px;background:var(--green);
  -webkit-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'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M8.5 12.5l2.5 2.5 4.5-5'/%3E%3C/svg%3E") center/contain no-repeat;
  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'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M8.5 12.5l2.5 2.5 4.5-5'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* Card — the panel an admin drops blocks into. Geometry is shared by
   the panel looks below, so any of them standing side by side line up.
   The padding is named so the Image card's image can bleed through
   exactly that much. */
.is-style-card,
.is-style-numbered-card,
.is-style-image-card,
.is-style-team-card,
.is-style-stat-tile{
  --card-pad:clamp(26px,3vw,36px);
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:16px;
  padding:var(--card-pad);
}

/* Numbered card — a card carrying an accent index, drawn as the violet
   badge the design opens each card with. The number is counted, not
   typed: an admin reordering the cards renumbers them by moving them,
   and cannot leave a 3 above a 5. The counter is never reset, so it
   runs across the page in document order.
   ponytail: the badge is a ::before, not a block an admin fills — a
   typed number is a number that goes stale, and the square is geometry
   the vocabulary owns. */
.is-style-numbered-card{counter-increment:rev-card}
.is-style-numbered-card::before{
  content:counter(rev-card);
  display:grid;place-items:center;
  width:44px;height:44px;margin-bottom:24px;
  border-radius:12px;
  background:color-mix(in srgb,var(--violet) 22%,transparent);
  color:var(--violet-lt);
  font-size:var(--wp--preset--font-size--x-large);font-weight:800;
  line-height:1;
}

/* A list inside a numbered card is the card's footnote row: mono,
   uppercase, dim, one bullet each — the reassurances under the body
   copy in the design. Dressed from the card rather than registered as
   its own style, the way the Strip dresses its labels: the list's one
   style slot stays free for Check list if a card wants ticks instead. */
.is-style-numbered-card :is(ul,ol):not(.is-style-check-list){list-style:none;padding:0}
.is-style-numbered-card :is(ul,ol):not(.is-style-check-list) li{
  display:flex;align-items:baseline;gap:8px;
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.1em;text-transform:uppercase;color:var(--dim);
  margin-top:10px;
}
.is-style-numbered-card :is(ul,ol):not(.is-style-check-list) li::before{content:'\2022';color:var(--violet-lt)}

/* Image card — a card that opens on an image running to its edges, then a
   stack of tag pills, a title, the copy and a mono footer label. The one
   thing an admin brings is the image; everything else is dressed from the
   card, the way the Numbered card dresses its list, so each block's own
   style slot stays free. The image bleeds through the card's padding with
   a negative margin rather than the card dropping its padding, so the text
   below needs no padding of its own. Only the image that opens the card
   bleeds: a later one (a LinkedIn icon under a Team card's label) sits in
   the text column like any other block. */
:is(.is-style-image-card,.is-style-team-card){overflow:hidden} /* clips the image to the card's corners */
:is(.is-style-image-card,.is-style-team-card) .wp-block-image:first-child{
  margin:calc(-1*var(--card-pad)) calc(-1*var(--card-pad)) 0;
}
.is-style-image-card .wp-block-image:first-child img{
  display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;
}
:is(.is-style-image-card,.is-style-team-card) .wp-block-image:first-child+*{margin-top:var(--card-pad)}
/* No image yet: WordPress renders an Image block with no file as nothing at
   all, so the card holds the frame itself until one is uploaded — the three
   cards keep one height and the page never shows a hole. The editor keeps
   the block's own upload placeholder, which is why this keys off the block
   being absent rather than empty. */
:is(.is-style-image-card,.is-style-team-card):not(:has(.wp-block-image:first-child))::before{
  content:'';display:block;aspect-ratio:16/9;
  margin:calc(-1*var(--card-pad)) calc(-1*var(--card-pad)) var(--card-pad);
  background:
    radial-gradient(120% 120% at 20% 0%,color-mix(in srgb,var(--violet) 40%,transparent),transparent 60%),
    var(--panel-2);
}
/* The tags: the card's list, one outlined mono pill per item, stacked. */
.is-style-image-card :is(ul,ol):not(.is-style-check-list){
  list-style:none;padding:0;
  display:flex;flex-direction:column;align-items:flex-start;gap:12px;
}
.is-style-image-card :is(ul,ol):not(.is-style-check-list) li{
  padding:8px 20px;border-radius:999px;
  border:1px solid color-mix(in srgb,var(--violet) 55%,transparent);
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  color:var(--violet-lt);
}
/* The footer label, pushed to the card's foot so the three line up however
   long the copy above runs. Uppercased here, so it reads right however it is
   typed.
   ponytail: the last paragraph is the label — delete it and the copy above
   takes its place; a style of its own if that ever bites. */
.is-style-image-card>p:last-of-type,
.is-style-image-card>.wp-block-group__inner-container>p:last-of-type{
  margin-top:auto;padding-top:var(--card-pad);
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.16em;text-transform:uppercase;color:var(--dim);
}

/* Team card — the Image card's frame (shared above) around a person: a
   square photo, the name (the heading), the role (first paragraph), the
   bio (the paragraphs between) and a mono label (the last paragraph).
   Unlike the Image card's footer, the label follows the copy rather than
   sitting on the card's foot. ponytail: a card with one paragraph gets the
   label's look, as the Stat tile does. */
.is-style-team-card .wp-block-image:first-child img{
  display:block;width:100%;height:auto;aspect-ratio:1;object-fit:cover;
}
.is-style-team-card:not(:has(.wp-block-image:first-child))::before{aspect-ratio:1}
.is-style-team-card :is(h2,h3,h4){font-size:var(--wp--preset--font-size--large)}
:is(.is-style-team-card,.is-style-team-card>.wp-block-group__inner-container)>p{font-size:var(--wp--preset--font-size--small);color:var(--muted)}
:is(.is-style-team-card,.is-style-team-card>.wp-block-group__inner-container)>p:first-of-type{color:var(--text)}
:is(.is-style-team-card,.is-style-team-card>.wp-block-group__inner-container)>p:last-of-type{
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.16em;text-transform:uppercase;color:var(--dim);
}
/* A link on the name (the person's LinkedIn) is stretched over the whole
   card and lifts it on hover, as the Open roles cards do; a card with no
   link on its name stays a plain panel, so a link in the bio stays just
   a link. Focus lifts it too, for the keyboard. Frontend only: in the canvas the stretched
   link would sit over the card's blocks and swallow every click meant
   for them — body is rewritten to the canvas wrapper there, so this
   never matches. The new tab is forced in functions.php. */
body:not(.editor-styles-wrapper) .is-style-team-card:has(:is(h2,h3,h4) a){
  position:relative;
  transition:transform .3s ease,border-color .3s ease,box-shadow .3s ease;
}
body:not(.editor-styles-wrapper) .is-style-team-card:has(:is(h2,h3,h4) a):is(:hover,:focus-within){
  transform:translateY(-6px);border-color:var(--violet-lt);
  box-shadow:0 24px 48px -24px rgba(91,60,240,.55);
}
/* A trailing image (the LinkedIn icon) sits on the card's foot, so the
   icons line up across a row however long each bio runs. The padding
   keeps the usual gap above it on the tallest card. */
:is(.is-style-team-card,.is-style-team-card>.wp-block-group__inner-container)>.wp-block-image:last-child:not(:first-child){
  margin-top:auto;padding-top:1.1em;
}
.is-style-team-card :is(h2,h3,h4) a{color:inherit;text-decoration:none;transition:color .25s ease}
.is-style-team-card:hover :is(h2,h3,h4) a{color:var(--violet-lt)}
body:not(.editor-styles-wrapper) .is-style-team-card :is(h2,h3,h4) a::after{content:'';position:absolute;inset:0}
/* Four across is too narrow for a face and a name between core's stacking
   point (781px) and a full desktop row, so a row of Team cards goes 2×2
   there — 1100px is roughly where a quarter of the row drops under the
   width a face and a two-word name need. Each column is a fixed half, not
   a growing one, so a lone card left over on a second row (a fifth
   advisor, its column set to a quarter's width in the editor) stays a
   half too rather than spanning the row. The !importants answer core's
   own nowrap!important and that inline width.
   ponytail: the 1em is half of core's 2em column gap; a gap setting in
   theme.json would have to change it too. */
@media (min-width:782px) and (max-width:1100px){
  .wp-block-columns:has(>.wp-block-column>.is-style-team-card){flex-wrap:wrap!important}
  .wp-block-columns:has(>.wp-block-column>.is-style-team-card)>.wp-block-column{flex:0 0 calc(50% - 1em)!important}
}

/* Stat tile — headline figure, label, source line. The three parts are
   read off the blocks an admin puts in the group: the heading is the
   figure, the first paragraph the label above it, the last the source
   underneath. ponytail: a tile with exactly one paragraph gets the
   source line's look, since first and last are then the same block. */
.is-style-stat-tile :is(h1,h2,h3,h4,h5,h6){
  font-size:var(--wp--preset--font-size--xx-large);font-weight:800;
  line-height:1.05;letter-spacing:-.03em;color:var(--violet-lt);
  font-variant-numeric:tabular-nums;
}
.is-style-stat-tile p:first-of-type,
.is-style-stat-tile p:last-of-type{
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
}
.is-style-stat-tile p:first-of-type{
  letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
}
.is-style-stat-tile p:last-of-type{color:var(--dim)}

/* Stats grid — the four-column horizontal strip of figures, labels,
   descriptions and sources on a group.
   Outer container has rounded corners, hairline border, and a 1px gap
   filled by the hairline color to create the vertical dividers.
   Each stat cell sits on --bg and transitions to #0f0d22 on hover.
   The alternating violet-light / green accents on label and figure
   are assigned via nth-child, so adding, reordering or editing cards
   maintains the designed cadence automatically without manual classes. */
.is-style-stats-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:16px;overflow:hidden;
  padding:0;
}
.is-style-stats-grid>.wp-block-group__inner-container{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;width:100%;
}
.is-style-stats-grid.is-style-stats-grid.is-style-stats-grid>*,
.is-style-stats-grid.is-style-stats-grid.is-style-stats-grid>.wp-block-group__inner-container>*{
  max-width:none;margin-inline:0;margin-top:0;
}
.is-style-stats-grid>.wp-block-group,
.is-style-stats-grid>.wp-block-group__inner-container>.wp-block-group{
  background:var(--bg);padding:clamp(30px,3.4vw,46px) clamp(22px,2.4vw,34px);
  transition:background .35s;display:flex;flex-direction:column;margin:0;
}
.is-style-stats-grid>.wp-block-group:hover,
.is-style-stats-grid>.wp-block-group__inner-container>.wp-block-group:hover{
  background:#0f0d22;
}
.is-style-stats-grid p{margin:0}
.is-style-stats-grid p:first-of-type{
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.15em;text-transform:uppercase;margin-bottom:16px;
}
.is-style-stats-grid :is(h1,h2,h3,h4,h5,h6){
  font-size:clamp(40px,4.4vw,58px);font-weight:800;line-height:1.05;
  letter-spacing:-.03em;margin:0 0 14px;font-variant-numeric:tabular-nums;
}
.is-style-stats-grid p:not(:first-of-type):not(:last-of-type){
  font-weight:600;font-size:var(--wp--preset--font-size--small);line-height:1.5;
  margin-bottom:8px;color:var(--wp--preset--color--white);
}
.is-style-stats-grid p:last-of-type:not(:first-of-type){
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  color:var(--dim);margin-top:auto;
}
.is-style-stats-grid>.wp-block-group:nth-child(odd) p:first-of-type,
.is-style-stats-grid>.wp-block-group:nth-child(odd) :is(h1,h2,h3,h4,h5,h6),
.is-style-stats-grid>.wp-block-group__inner-container>.wp-block-group:nth-child(odd) p:first-of-type,
.is-style-stats-grid>.wp-block-group__inner-container>.wp-block-group:nth-child(odd) :is(h1,h2,h3,h4,h5,h6){
  color:var(--violet-lt);
}
.is-style-stats-grid>.wp-block-group:nth-child(even) p:first-of-type,
.is-style-stats-grid>.wp-block-group:nth-child(even) :is(h1,h2,h3,h4,h5,h6),
.is-style-stats-grid>.wp-block-group__inner-container>.wp-block-group:nth-child(even) p:first-of-type,
.is-style-stats-grid>.wp-block-group__inner-container>.wp-block-group:nth-child(even) :is(h1,h2,h3,h4,h5,h6){
  color:var(--green);
}
@media (max-width:960px){
  .is-style-stats-grid,
  .is-style-stats-grid>.wp-block-group__inner-container{
    grid-template-columns:1fr 1fr;
  }
}
@media (max-width:620px){
  .is-style-stats-grid,
  .is-style-stats-grid>.wp-block-group__inner-container{
    grid-template-columns:1fr;
  }
  .is-style-stats-grid :is(h1,h2,h3,h4,h5,h6){
    font-size:clamp(38px,11vw,52px);
  }
}


/* Divider band — the section background that breaks a long page into
   chapters, hairlined top and bottom. Set the group to Full width to
   let it span the page: the escape from the content column is
   WordPress's own .alignfull (add_theme_support('align-wide') in
   functions.php, the frontend half in style.css), which the editor
   canvas widens by itself — so the bleed is one behaviour, not two
   that can disagree.
   --panel is the design's section fill: it reads as a separate band
   against --bg, the way .strip and .cases already do. */
/* The landing reset zeroes every margin and restores flow only for the
   page's top-level blocks (style.css), so blocks nested inside a panel
   would stack edge to edge on the published page while the canvas kept
   its gaps. Restore it here — and one level down too, for the inner
   container WordPress wraps a group's children in. */
:is(.is-style-card,.is-style-numbered-card,.is-style-image-card,.is-style-team-card,.is-style-stat-tile,.is-style-section,.is-style-divider-band,.is-style-hero,.wp-block-column)>*+*,
:is(.is-style-card,.is-style-numbered-card,.is-style-image-card,.is-style-team-card,.is-style-stat-tile,.is-style-section,.is-style-divider-band,.is-style-hero,.wp-block-column)>.wp-block-group__inner-container>*+*{
  margin-top:1.1em;
}

/* A column is on that list for the same reason a panel is: blocks stacked
   in one column of a Columns row are nested too, so without this two
   paragraphs beside a card run together on the published page.

   Headings keep the designed leading rather than the body's 1.7, which is
   the reading line-height for prose and leaves gaps between the lines of a
   headline. :where() so every style below (and prose.css) still wins. */
:where(.wp-block-heading){line-height:1.15}

/* Feature card — the compact panel of a side column: a title with its one
   line right under it, read as a single label rather than two blocks. The
   Card's geometry, tightened; a stack of them is the column beside a
   section's opening copy (Split section). */
.is-style-feature-card{
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:14px;
  padding:18px 22px;
}
.is-style-feature-card>*+*,
.is-style-feature-card>.wp-block-group__inner-container>*+*{margin-top:4px}
.is-style-feature-card :is(h1,h2,h3,h4,h5,h6){
  font-size:var(--wp--preset--font-size--medium);font-weight:700;line-height:1.35;
}
.is-style-feature-card+.is-style-feature-card{margin-top:14px}

/* Closing CTA — the page's last word: the heading on the left, one button
   on the right, in a panel far wider than it is tall. The heading's 16ch
   cap is what breaks it over two lines while the button stays on the
   baseline between them.
   ponytail: the gradient stops stay literals — the wash is two one-off
   tints, not a token. */
.is-style-closing-cta,
.is-style-closing-cta>.wp-block-group__inner-container{
  display:flex;align-items:center;justify-content:space-between;
  gap:30px;flex-wrap:wrap;
}
.is-style-closing-cta{
  padding:clamp(32px,4.5vw,56px);
  border:1px solid var(--line);
  border-radius:20px;
  background:linear-gradient(165deg,rgba(30,26,66,.78),rgba(16,14,36,.62));
}
.is-style-closing-cta>.wp-block-group__inner-container{flex:1}
.is-style-closing-cta :is(h1,h2,h3,h4,h5,h6){
  font-size:clamp(28px,3.4vw,42px);max-width:16ch;
}

/* Section — the unshaded chapter: the Divider band's spacing with no
   fill and no hairlines. Alternating the two down a page is what makes
   a chapter break visible, and it stays an admin's choice per section
   rather than an nth-child rule any block between two sections would
   silently flip. */
.is-style-section{
  padding:var(--wp--preset--spacing--section) var(--wp--preset--spacing--pad);
}

.is-style-divider-band{
  background:var(--panel);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  padding:var(--wp--preset--spacing--section) var(--wp--preset--spacing--pad);
}

/* Hero — the page's opener, on a group: the radial gradient, the masked
   grid, the designed minimum height and the narrow text column. Set the
   group to Full width to let it span the page, the same way the Divider
   band and the Strip do.
   The moving background is a core Video block inside the group — the
   Hero Pattern ships it empty, set to autoplay, loop, muted and no
   controls, and the admin uploads or swaps the clip from the media
   library. Any Video block placed directly in a hero is laid behind the
   text as a cover. Until one is uploaded (or while it loads) the gradient
   below is the background.
   Unscoped like everything else in this file, so the editor canvas and
   the published page cannot disagree. The consequence is intended: the
   hero renders at its full designed height, video included, while being
   edited, which is the only way to judge an opener without previewing.
   The video sits under the text there too, so select it from List View
   to replace it.

   ponytail: the gradient stops stay literals — they
   are not palette tokens, and promoting them would put four more
   near-identical violets in the admin's colour picker
   (docs/adr/0001-*.md). */
.is-style-hero{
  position:relative;overflow:hidden;
  display:grid;align-content:center;
  min-height:min(92vh,880px);
  padding:var(--wp--preset--spacing--section) var(--wp--preset--spacing--pad);
  background:radial-gradient(90% 120% at 82% 50%,#3B2AAC 0%,#241A6E 34%,var(--bg) 68%);
}
/* The grid, as a pseudo-element rather than a block an admin could
   delete. Masked so it fades out under the text and leaves the headline
   on flat colour. */
.is-style-hero::before{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background-image:
    linear-gradient(color-mix(in srgb,var(--wp--preset--color--white) 3%,transparent) 1px,transparent 1px),
    linear-gradient(90deg,color-mix(in srgb,var(--wp--preset--color--white) 3%,transparent) 1px,transparent 1px);
  background-size:70px 70px;
  -webkit-mask-image:linear-gradient(90deg,#000 0%,transparent 55%);
  mask-image:linear-gradient(90deg,#000 0%,transparent 55%);
}
/* The background video, under the grid and the veil. Two classes, to
   beat the generic >*+* spacing above, which would push it down. */
.is-style-hero>.wp-block-video{
  position:absolute;inset:0;z-index:0;margin:0;pointer-events:none;
}
.is-style-hero>.wp-block-video video{width:100%;height:100%;object-fit:cover}
/* Editor only: before a clip is picked the block is the upload
   placeholder, which has to stay clickable and above the veil. */
.is-style-hero>.wp-block-video:is(.components-placeholder,:has(.components-placeholder)){
  position:relative;inset:auto;z-index:3;pointer-events:auto;
}
/* The veil between the video and the text: dark behind the text column,
   clear on the right where the footage shows. */
.is-style-hero::after{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--bg) 88%,transparent) 0%,
    color-mix(in srgb,var(--bg) 55%,transparent) 45%,
    color-mix(in srgb,var(--bg) 0%,transparent) 80%);
}
/* The text column — a long headline breaks where the designed one breaks.
   A grid, not flex: the blocks stack as rows and align-content centres
   the stack as a whole against the designed minimum height. Flex would
   centre each line separately and spread the badge, headline and buttons
   evenly down 880px.
   Whichever of the two holds the blocks gets the cap — a constrained
   group wraps its children in an inner container, one without puts them
   straight in (as in the Strip below).
   The class is tripled to outrank the .wp-container-* layout CSS
   WordPress generates for a constrained group, which is two classes and
   prints inline in <head>, after this sheet: without it theme.json's
   contentSize centres each child and the opener reads as a centred
   document instead (the same fix the Strip needs, for the same reason). */
.is-style-hero.is-style-hero.is-style-hero>:not(.wp-block-video),
.is-style-hero.is-style-hero.is-style-hero>.wp-block-group__inner-container>*{
  max-width:600px;margin-inline:0;
}
/* Above the grid and the veil, both of which are z-index 1. */
.is-style-hero>:not(.wp-block-video){position:relative;z-index:2}

/* The opener's own typography, read off the blocks an admin puts in the
   group the way the Stat tile reads its own: the headline is the heading,
   the intro is a paragraph. Weight, leading and tracking are set here
   because they are on no picker and a Pattern may carry nothing but
   registered styles (docs/adr/0001-*.md); sizes stay the admin's pick
   from the scale, except the headline's — see below.
   Direct children only, and one level down for the inner container a
   constrained group wraps them in: a heading inside a Card dropped into a
   hero is that card's heading, not the opener's.
   A paragraph already wearing a style — the Badge, a Chip, an Icon label —
   is excluded by carrying one, so the list never has to be maintained: the
   pills hug their own label and the intro's measure and colour would only
   dull them.
   The intro's 40ch sits inside the 600px column above, so the narrower
   of the two wins per block. */
.is-style-hero>:is(h1,h2,h3),
.is-style-hero>.wp-block-group__inner-container>:is(h1,h2,h3){
  font-weight:800;line-height:1.08;letter-spacing:-.025em;padding-bottom:.04em;
}
/* The headline's size is the style's, not the Pattern's: WordPress prints a
   preset class as font-size:… !important, so a size chosen in the Pattern
   could not be dropped a step on a phone below. An admin picking a size in
   the editor still wins, for the same reason. */
.is-style-hero>h1,
.is-style-hero>.wp-block-group__inner-container>h1{font-size:var(--wp--preset--font-size--display)}
.is-style-hero>p:not([class*="is-style-"]),
.is-style-hero>.wp-block-group__inner-container>p:not([class*="is-style-"]){
  max-width:40ch;
  color:color-mix(in srgb,var(--wp--preset--color--white) 80%,transparent);
}
/* The opener's vertical rhythm. The generic 1.1em above is 1.1em of each
   block's own font size, which lands ~19px before the buttons and ~16px
   before the trust row against the designed 30-42 and 38-56 — the opener
   reads visibly tight without these. */
.is-style-hero>*+*,
.is-style-hero>.wp-block-group__inner-container>*+*{margin-top:clamp(22px,3vw,30px)}
.is-style-hero>.wp-block-buttons,
.is-style-hero>.wp-block-group__inner-container>.wp-block-buttons{margin-top:clamp(30px,4vw,42px)}
.is-style-hero>.is-style-check-list,
.is-style-hero>.wp-block-group__inner-container>.is-style-check-list{margin-top:clamp(38px,5vw,56px)}

/* Mobile: the text spans the width, so the grid drops its mask and the
   veil turns radial to keep the headline readable over the video — the
   designed opener's own mobile treatment, at the same breakpoint. */
@media (max-width:960px){
  .is-style-hero{
    min-height:min(88vh,760px);
    background:radial-gradient(120% 80% at 50% 46%,#33257F 0%,#201862 40%,var(--bg) 76%);
  }
  .is-style-hero::before{-webkit-mask-image:none;mask-image:none;opacity:.25}
  .is-style-hero::after{
    content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
    background:radial-gradient(78% 52% at 50% 50%,
      color-mix(in srgb,var(--bg) 86%,transparent) 0%,
      color-mix(in srgb,var(--bg) 62%,transparent) 42%,
      color-mix(in srgb,var(--bg) 0%,transparent) 76%);
  }
  .is-style-hero.is-style-hero.is-style-hero>:not(.wp-block-video),
  .is-style-hero.is-style-hero.is-style-hero>.wp-block-group__inner-container>*{max-width:100%}
}

/* Phone: the designed opener drops the headline a size and stacks the CTA
   pair full width (style.css, the 620px block), so the block-built one
   does too — at the same breakpoint. The heading's font size comes from
   the admin's preset, so this is the one place the style overrules it:
   the display step is 44px at its floor, where the design gives 34. */
@media (max-width:620px){
  .is-style-hero>h1,
  .is-style-hero>.wp-block-group__inner-container>h1{
    font-size:clamp(34px,9vw,46px);line-height:1.12;
  }
  .is-style-hero .wp-block-buttons{flex-direction:column;align-items:stretch}
  .is-style-hero .wp-block-buttons .wp-block-button{width:100%}
  .is-style-hero .wp-block-button__link{width:100%}
  .is-style-hero .is-style-check-list{gap:10px 18px}
}

/* Gradient accent — the accented word inside a headline. An inline
   format, not a Block style: it dresses a range of text inside a block
   (assets/editor.js), which a per-block style cannot do.
   <mark> is the tag the format wraps the selection in, so its default
   highlight — yellow fill, black text — is what these two declarations
   overwrite: the accent shows the gradient and nothing else.
   ponytail: the outer two stops stay literals. They are not palette
   tokens, and promoting them would put two more near-identical violets
   in the admin's colour picker. */
.rev-accent{
  background:linear-gradient(100deg,#DCD4FF,var(--violet-lt) 45%,#6E52FF);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
}

/* Strip — the bordered band of labels beneath a hero, on a group. The
   band is the group; each label is a paragraph inside it, and the mono
   uppercase treatment comes from here rather than from a style on each
   paragraph. That is the point: the editor's style picker is
   single-select, so a label styled by its container still has its one
   slot free to spend on an icon (CONTEXT.md, Block style).
   Nothing here counts the labels — adding, removing or reordering them
   is flex doing its job, and the icons travel with their paragraphs
   because each one is that paragraph's own style.
   Set the group to Full width to let the band span the page, the same
   way the Divider band does — and the labels still line up with the
   column above, because .alignfull pushes the gutters back in at
   max(--pad,50vw - --max/2) (style.css) and outranks the padding here.
   ponytail: no mobile type step, where the designed strip drops to
   11.5px — that size is not on the scale, so it does not exist here
   (docs/adr/0001-*.md). The packing below is the part that mattered. */
.is-style-strip{
  background:var(--panel);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  padding:26px var(--wp--preset--spacing--pad);
}
/* Whichever of the two holds the paragraphs does the spreading: a group
   with a constrained layout wraps its children in an inner container,
   one without puts them straight in. Both get the same rule, so the
   band lays out either way.
   The class is doubled to outrank the .wp-container-* layout CSS
   WordPress generates for a Row (a group with a flex layout), which is
   a single class emitted after this sheet. Without it, whatever an
   admin left in the Layout panel decides how the labels sit and the
   band is a different shape per page — the style owns the look
   (docs/adr/0001-*.md). */
.is-style-strip.is-style-strip,
.is-style-strip>.wp-block-group__inner-container{
  display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:20px 40px;
}
.is-style-strip>.wp-block-group__inner-container{flex:1 1 100%}
/* The band butts against the block above it: a hairline with a gap over it
   reads as a floating bar rather than the edge of the section it closes.
   Doubled to outrank the landing column's flow spacing (.landing>*+*,
   style.css), which is two classes and loads before this sheet. */
.is-style-strip.is-style-strip{margin-top:0}
/* theme.json's layout.contentSize makes WordPress cap and centre every child
   of a constrained group (margin-inline:auto). In a flex row those auto
   margins swallow the free space, so the labels bunch in the middle instead
   of spreading. The class is tripled to outrank that generated rule, which
   is two classes and prints inline in <head>, after this sheet. */
.is-style-strip.is-style-strip.is-style-strip>*{max-width:none;margin-inline:0}
.is-style-strip p{
  display:flex;align-items:center;margin:0;
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}
/* Spread-out labels on a narrow screen read as a gappy column, so the
   band packs them from the left once it has to wrap in earnest. */
@media (max-width:620px){
  .is-style-strip.is-style-strip,
  .is-style-strip>.wp-block-group__inner-container{justify-content:flex-start;gap:14px 24px}
}

/* The four icon styles — a closed, enumerated set: shield, check,
   database, globe. A glyph outside the four does not exist, and adding
   one is a theme change rather than an upload field
   (docs/adr/0003-icon-set-is-closed-and-enumerated.md).
   Each draws its glyph and nothing else: the label's type, colour and
   alignment come from the Strip around it, so the same style also works
   on a paragraph standing on its own.
   Masked from the accent token like every other mark in this file, so an
   admin sources no image and no glyph can arrive off-brand. */
.is-style-icon-shield::before,
.is-style-icon-check::before,
.is-style-icon-database::before,
.is-style-icon-globe::before{
  content:'';flex:none;display:inline-block;vertical-align:-2px;
  width:15px;height:15px;margin-right:10px;background:var(--violet-lt);
  -webkit-mask:var(--rev-glyph) center/contain no-repeat;
  mask:var(--rev-glyph) center/contain no-repeat;
}
.is-style-icon-shield::before{
  --rev-glyph: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'%3E%3Cpath d='M12 2l8 4v6c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z'/%3E%3C/svg%3E");
}
.is-style-icon-check::before{
  --rev-glyph: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'%3E%3Cpath d='M9 11l3 3 8-8'/%3E%3Cpath d='M20 12v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h9'/%3E%3C/svg%3E");
}
.is-style-icon-database::before{
  --rev-glyph: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'%3E%3Cellipse cx='12' cy='6' rx='8' ry='3'/%3E%3Cpath d='M4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6'/%3E%3C/svg%3E");
}
.is-style-icon-globe::before{
  --rev-glyph: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'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E");
}

/* Stats band — the quieter variant of the Stats grid: one eyebrow above
   the whole band instead of a label per cell, every figure violet, and
   the description and source set in the same mono uppercase so a cell
   reads as figure then caption. Geometry is deliberately a copy of the
   Stats grid's rather than a shared base: the editor's Styles list is a
   single choice, so the two looks can never combine on one group, and a
   shared base would only be read by two callers that never overlap.
   ponytail: no alternating accent and no hover shift — the variant's
   whole point is the flatter read. */
.is-style-stats-band{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:16px;
  overflow:hidden;padding:0;
}
.is-style-stats-band>.wp-block-group__inner-container{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;width:100%;
}
.is-style-stats-band.is-style-stats-band.is-style-stats-band>*,
.is-style-stats-band.is-style-stats-band.is-style-stats-band>.wp-block-group__inner-container>*{
  max-width:none;margin-inline:0;margin-top:0;
}
.is-style-stats-band>.wp-block-group,
.is-style-stats-band>.wp-block-group__inner-container>.wp-block-group{
  background:var(--panel);padding:clamp(26px,3vw,40px) clamp(20px,2.2vw,32px);
  display:flex;flex-direction:column;margin:0;
}
.is-style-stats-band :is(h1,h2,h3,h4,h5,h6){
  font-size:clamp(34px,3.6vw,48px);font-weight:800;line-height:1.05;
  letter-spacing:-.02em;margin:0 0 18px;color:var(--violet-lt);
  font-variant-numeric:tabular-nums;
}
.is-style-stats-band p{
  margin:0;font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.12em;text-transform:uppercase;line-height:1.7;color:var(--muted);
}
.is-style-stats-band p:last-of-type:not(:first-of-type){color:var(--dim)}
@media (max-width:960px){
  .is-style-stats-band,
  .is-style-stats-band>.wp-block-group__inner-container{grid-template-columns:1fr 1fr}
}
@media (max-width:620px){
  .is-style-stats-band,
  .is-style-stats-band>.wp-block-group__inner-container{grid-template-columns:1fr}
}

/* Figure pair — the two headline figures a case study opens with
   (style.css, .case__figs): the heading is the figure, the paragraph
   under it the mono uppercase caption. No fill and no border, because
   the pair sits inside a Card that already has both — this is the one
   figure look that is not a panel of its own.
   The accents alternate green then violet by nth-child, the way the
   Stats grid's do, so an admin who swaps the two columns keeps the
   designed cadence without touching a colour control.
   ponytail: two columns by declaration, not a count — a pair is what
   the design has, and a third figure wraps onto the next row rather
   than squeezing the first two. */
.is-style-figure-pair,
.is-style-figure-pair>.wp-block-group__inner-container{
  display:grid;grid-template-columns:1fr 1fr;gap:clamp(20px,3vw,36px);
}
.is-style-figure-pair.is-style-figure-pair.is-style-figure-pair>*,
.is-style-figure-pair.is-style-figure-pair.is-style-figure-pair>.wp-block-group__inner-container>*{
  max-width:none;margin-inline:0;margin-top:0;
}
.is-style-figure-pair :is(h1,h2,h3,h4,h5,h6){
  font-size:clamp(34px,3.6vw,48px);font-weight:800;line-height:1.05;
  letter-spacing:-.03em;margin:0 0 10px;font-variant-numeric:tabular-nums;
  color:var(--green);
}
.is-style-figure-pair>:nth-child(even) :is(h1,h2,h3,h4,h5,h6),
.is-style-figure-pair>.wp-block-group__inner-container>:nth-child(even) :is(h1,h2,h3,h4,h5,h6){
  color:var(--violet-lt);
}
.is-style-figure-pair p{
  margin:0;font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
}
@media (max-width:480px){
  .is-style-figure-pair,
  .is-style-figure-pair>.wp-block-group__inner-container{grid-template-columns:1fr}
}

/* Trend chart — the panel the growth curve is drawn in (style.css,
   .chart). The curve is not in this file and not in the content
   either: assets/main.js reads the list inside the group as
   `label value` pairs, builds the SVG and prepends it, then strips
   the numbers so the same list stays as the axis row
   (docs/adr/0005-*.md). So the data an admin types is the only copy
   of it, and there is no graphic to keep in step with the figures.
   In the editor canvas the script never runs: the panel and the
   list render, numbers and all, and the curve appears on the
   published page. */
.is-style-trend-chart{
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:16px;
  padding:clamp(18px,2.4vw,26px);
}
.is-style-trend-chart svg{width:100%;height:auto;display:block;overflow:visible}
.is-style-trend-chart :is(ul,ol){
  list-style:none;padding:0;margin:14px 0 0;
  display:flex;justify-content:space-between;gap:10px;
}
.is-style-trend-chart li{
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  color:var(--dim);
}
/* The generated marks. Their colours live here, not in the script, so
   the curve is a token like every other accent on the page. */
.rev-chart__line{fill:none;stroke:var(--green);stroke-width:2.5;stroke-linecap:round}
.rev-chart__end{fill:var(--green);filter:drop-shadow(0 0 7px var(--green))}
.rev-chart__from{stop-color:var(--green);stop-opacity:.34}
.rev-chart__to{stop-color:var(--green);stop-opacity:0}

/* Meter list — the before/after bars of the second case study
   (style.css, .bars), on a list an admin types. Each item is
   `Label <strong>After</strong> 80`: the bolded word is the marker
   pushed to the right, and the trailing number is the bar's length,
   read off the text by assets/main.js and set as --rev-meter
   (docs/adr/0005-*.md). Until it is read the number is visible text,
   which is exactly what an admin editing the list needs to see.
   The last row is green — the design's one "this is the upside" row,
   the same rule .bar:last-child carries in style.css. */
.is-style-meter-list{list-style:none;padding:0;margin:0}
.is-style-meter-list li{
  display:flex;flex-wrap:wrap;align-items:baseline;
  font-family:var(--mono);font-size:var(--wp--preset--font-size--x-small);
  letter-spacing:.06em;color:var(--muted);
  padding-bottom:14px;margin-top:24px;position:relative;
}
.is-style-meter-list li strong{margin-left:auto;font-weight:400;color:var(--violet-lt)}
.is-style-meter-list li:last-child strong{color:var(--green)}
/* Track and fill: the track is the row's own bottom edge, the fill the
   length typed into it. 0% until the script reads it, so a bar can
   never show a length nobody asked for. */
.is-style-meter-list li::before,
.is-style-meter-list li::after{
  content:'';position:absolute;left:0;bottom:0;height:4px;border-radius:999px;
}
.is-style-meter-list li::before{right:0;background:var(--line-2)}
.is-style-meter-list li::after{
  width:var(--rev-meter,0%);background:var(--violet);
  transition:width 1.3s cubic-bezier(.22,1,.36,1);
}
.is-style-meter-list li:last-child::after{background:var(--green)}
@media (prefers-reduced-motion:reduce){
  .is-style-meter-list li::after{transition:none}
}

/* Cards in a columns row are all as tall as the tallest one, and the
   graphic each one ends with sits on the bottom edge — the designed
   case studies read as a pair, and two panels ending at different
   heights is the one thing that breaks that read.
   The column is already a flex item that stretches to the row, so the
   panel only has to fill the column it is in. box-sizing is stated
   here rather than assumed: the frontend reset lives under
   .rev-landing (style.css), which the editor canvas has no wrapper
   for, and without it the padding would push each card past 100%. */
.wp-block-column>:is(.is-style-card,.is-style-numbered-card,.is-style-image-card,.is-style-team-card,.is-style-stat-tile){
  box-sizing:border-box;
}
/* Only a panel that is the column's whole content fills it: cards stacked
   in one column (Split section) would each take the full row height. */
.wp-block-column>:is(.is-style-card,.is-style-numbered-card,.is-style-image-card,.is-style-team-card,.is-style-stat-tile):only-child{
  height:100%;
}
/* A Card is a column of blocks, so its last graphic can be pushed to the
   bottom: the trend chart and the meter bars line up across the pair
   however much copy sits above them. Only the two graphics take the
   push — a card ending in a paragraph keeps its copy tight under the
   line before it. */
.is-style-card,
.is-style-card>.wp-block-group__inner-container,
.is-style-image-card,
.is-style-image-card>.wp-block-group__inner-container,
.is-style-team-card,
.is-style-team-card>.wp-block-group__inner-container{display:flex;flex-direction:column}
/* the inner container is the card's only child when the group carries a
   layout, so it has to grow before anything inside it can be pushed down */
:is(.is-style-card,.is-style-image-card,.is-style-team-card)>.wp-block-group__inner-container{flex:1}
.is-style-card>:is(.is-style-trend-chart,.is-style-meter-list),
.is-style-card>.wp-block-group__inner-container>:is(.is-style-trend-chart,.is-style-meter-list){
  margin-top:auto;
}

/* ============================================================
   LATEST POSTS — the blog's cards, on any page
   The Query Loop an admin inserts (patterns/latest-posts.php),
   dressed as the post cards /blog/ already shows. Nothing here is markup the theme renders: the rules
   address core's own post blocks, so the loop stays an ordinary
   block whose fields can be reordered, retyped or deleted.

   ponytail: this look is a second copy of .rvb-card
   (assets/blog.css). That sheet is loaded on singular pages
   only and never into the editor canvas, so a card built from
   it would be invisible in the editor and unstyled on a Landing
   page.
   ============================================================ */
.is-style-latest-posts .wp-block-post-template{
  margin-top:26px;padding:0;list-style:none;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(min(320px,100%),1fr));gap:22px;
}
.is-style-latest-posts .wp-block-post{
  position:relative; /* the title's stretched link is measured from the card */
  box-sizing:border-box; /* the frontend reset lives under .rev-landing, which the canvas has no wrapper for */
  display:flex;flex-direction:column;gap:12px;
  background:var(--panel);border:1px solid var(--line);border-radius:18px;overflow:hidden;
  transition:transform .3s ease,border-color .3s ease,box-shadow .3s ease;
}
.is-style-latest-posts .wp-block-post:hover{
  transform:translateY(-6px);border-color:var(--violet-lt);
  box-shadow:0 24px 48px -24px rgba(91,60,240,.55);
}
/* The body is inset, the thumbnail is not. Gutters are margins on the
   fields themselves rather than a wrapper block, so the card is the
   fields and nothing else — an admin deleting one leaves no empty box. */
.is-style-latest-posts .wp-block-post>:not(.wp-block-post-featured-image){margin-left:22px;margin-right:22px}
.is-style-latest-posts .wp-block-post>:last-child{margin-bottom:22px}

/* Thumbnail — the gradient behind it is what a post with no featured
   image falls back to, the same one the blog cards use. */
.is-style-latest-posts .wp-block-post-featured-image{
  margin:0 0 8px;position:relative;aspect-ratio:16/10;overflow:hidden;
  background:
    radial-gradient(120% 120% at 20% 0%,rgba(91,60,240,.35),transparent 55%),
    radial-gradient(120% 120% at 100% 100%,rgba(47,191,100,.22),transparent 55%),var(--panel-2);
}
.is-style-latest-posts .wp-block-post-featured-image img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .5s ease;
}
.is-style-latest-posts .wp-block-post:hover .wp-block-post-featured-image img{transform:scale(1.05)}

/* Category tag. ponytail: the two accent categories are matched on the
   term link's href — the Query Loop renders nothing carrying the term's
   name, which is what .rvb-tag[data-c] keys off in assets/blog.css.
   Renaming a category's slug drops its tag back to violet; rename it
   here too, or drop these two rules and let every tag be violet. */
.is-style-latest-posts .wp-block-post-terms{line-height:1}
.is-style-latest-posts .wp-block-post-terms a{
  display:inline-block;text-decoration:none;
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--violet-lt);background:rgba(91,60,240,.14);border:1px solid rgba(91,60,240,.3);
  padding:5px 10px;border-radius:6px;
}
.is-style-latest-posts .wp-block-post-terms a[href*="/compliance"]{
  color:var(--green);background:rgba(47,191,100,.12);border-color:rgba(47,191,100,.3);
}
.is-style-latest-posts .wp-block-post-terms a[href*="/ai-testing"]{
  color:var(--blue);background:rgba(90,170,255,.12);border-color:rgba(90,170,255,.3);
}

/* Title, and the one link over the whole tile: clicking the thumbnail,
   the excerpt or the byline opens the post, with no second link for a
   screen reader to announce and no script to load. */
.is-style-latest-posts .wp-block-post-title{
  margin:0;font-size:19px;line-height:1.28;letter-spacing:-.01em;font-weight:600;
}
.is-style-latest-posts .wp-block-post-title a{color:inherit;text-decoration:none;transition:color .25s ease}
.is-style-latest-posts .wp-block-post:hover .wp-block-post-title a{color:var(--violet-lt)}
.is-style-latest-posts .wp-block-post-title a::after{content:'';position:absolute;inset:0}

.is-style-latest-posts .wp-block-post-excerpt,
.is-style-latest-posts .wp-block-post-excerpt p{margin:0}
.is-style-latest-posts .wp-block-post-excerpt__excerpt{
  color:var(--muted);font-size:14.5px;line-height:1.55;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}

/* The byline row — the only group inside a card, so it is addressed by
   what it is rather than by a class an admin could delete. The dot is
   the stylesheet's, so removing the author block removes it too. */
.is-style-latest-posts .wp-block-post .wp-block-group{
  margin-top:auto;padding-top:12px;border-top:1px solid var(--line);
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.02em;color:var(--dim);
}
.is-style-latest-posts .wp-block-post-date:not(:first-child)::before{content:'·';margin-right:10px;opacity:.5}
.is-style-latest-posts .wp-block-read-more{
  margin-left:auto;color:var(--violet-lt);text-decoration:none;
  display:inline-flex;align-items:center;gap:6px;transition:gap .25s ease;
}
.is-style-latest-posts .wp-block-post:hover .wp-block-read-more{gap:11px}

/* ============================================================
   OPEN ROLES — the Careers listing's cards
   The Query Loop in patterns/open-roles.php, reading Careers.
   Same approach as Latest posts: the rules address core's own
   post blocks, so the fields stay ordinary blocks. The card is
   Panel raised because it sits on a Divider band (Panel), where
   a Panel card would vanish into the band.

   ponytail: the tag and the line under the excerpt are both Post
   Terms blocks, told apart by their taxonomy's class. The slugs
   (department, working_term) are set in CPT UI, not here —
   rename one there and rename it here too.
   tools/check-block-patterns.mjs fails if the pattern names a
   taxonomy these rules do not style.
   ============================================================ */
.is-style-open-roles .wp-block-post-template{
  margin-top:26px;padding:0;list-style:none;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(min(440px,100%),1fr));gap:22px;
}
.is-style-open-roles .wp-block-post{
  position:relative; /* the title's stretched link is measured from the card */
  box-sizing:border-box;
  display:flex;flex-direction:column;align-items:flex-start;gap:14px;
  padding:26px;
  background:var(--panel-2);border:1px solid var(--line);border-radius:18px;
  transition:transform .3s ease,border-color .3s ease,box-shadow .3s ease;
}
.is-style-open-roles .wp-block-post:hover{
  transform:translateY(-6px);border-color:var(--violet-lt);
  box-shadow:0 24px 48px -24px rgba(91,60,240,.55);
}

/* Department — the tag */
.is-style-open-roles .taxonomy-department{line-height:1}
.is-style-open-roles .taxonomy-department a{
  display:inline-block;text-decoration:none;
  font-family:var(--mono);font-size:11px;letter-spacing:.04em;
  color:var(--violet-lt);background:rgba(91,60,240,.14);border:1px solid rgba(91,60,240,.3);
  padding:5px 12px;border-radius:999px;
}

/* Title, and the one link over the whole card */
.is-style-open-roles .wp-block-post-title{
  margin:0;font-size:19px;line-height:1.28;letter-spacing:-.01em;font-weight:600;
}
.is-style-open-roles .wp-block-post-title a{color:inherit;text-decoration:none;transition:color .25s ease}
.is-style-open-roles .wp-block-post:hover .wp-block-post-title a{color:var(--violet-lt)}
.is-style-open-roles .wp-block-post-title a::after{content:'';position:absolute;inset:0}

/* The excerpt is the role's one-line subtitle. Clamped, because a Career
   saved without one gets WordPress's 55-word cut of the body instead. */
.is-style-open-roles .wp-block-post-excerpt,
.is-style-open-roles .wp-block-post-excerpt p{margin:0}
.is-style-open-roles .wp-block-post-excerpt__excerpt{
  color:var(--muted);font-size:14.5px;line-height:1.55;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}

/* Working terms — one quiet line, the separator is the block's own */
.is-style-open-roles .taxonomy-working_term{
  margin-top:auto;padding-top:6px;
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);
}
.is-style-open-roles .taxonomy-working_term a{color:inherit;text-decoration:none}

.is-style-open-roles .wp-block-query-no-results{margin-top:26px;color:var(--muted)}
