/*
 * The platform's own defaults, so a site can ship no CSS at all.
 *
 * ⚠️ THE OTHER SIX STYLESHEETS IN THIS DIRECTORY SPEND 64 CUSTOM PROPERTIES AND
 * DEFINE NONE OF THEM. Every card, control, facet, field, button and vote
 * display reads them from whichever site is active. That made a working site a
 * precondition for the platform rendering at all: a new site that had not yet
 * written a token file got 64 invalid declarations - no colour, no radius, no
 * border, no padding on anything shipped here - and a design imported into it
 * would look broken while importing perfectly.
 *
 * The requirement was real and backwards. A component that needs a value should
 * carry a default for it; a site should override what it wants to differ, and
 * nothing else.
 *
 * ⚠️ EVERY COLOUR HERE IS AN ACSS ROLE, NEVER A COLOUR. Nothing in this file
 * picks a hue. Each token says what it IS - a surface, a line, body text, the
 * accent - and takes it from the ramp ACSS generates from that site's
 * `design/acss-roles.json`. So a new site's whole appearance is one JSON file of
 * hues and lightnesses, and this stylesheet never needs editing.
 *
 * ⚠️ `:root`, DELIBERATELY THE WEAKEST THING THAT WORKS. A site declares on
 * `html:root` (0-1-1) and beats every line here without a fight. This file is a
 * floor, not an opinion.
 *
 * The fallback after each `var()` is what renders with ACSS switched off: a
 * legible neutral scale, not a design.
 */

/*
 * ⚠️ 1rem IS 10px, AND EVERY LENGTH BELOW ASSUMES IT.
 *
 * A default layer written in rem has to say what a rem is, or its own numbers
 * mean different things on different installs - which is the exact failure that
 * made site-one render 1.6x too big the day ACSS arrived.
 *
 * ⚠️ REM AND NOT px, THOUGH, AND THAT IS A DELIBERATE REVERSAL. px would make
 * these immune to the root entirely, which is tempting and wrong: a tap target
 * and a control height in px do not grow when somebody raises their browser's
 * base font size, and a 24px minimum exists for exactly that person.
 *
 * ⚠️ ACSS ALSO SETS font-size ON `html`, at the same specificity, and loads
 * later - so it wins. A site's `design/acss-roles.json` must carry
 * `root-font-size: 62.5` to agree with this. `verify-acss.php` checks the file;
 * nothing checks the agreement, so it is written here as well as there.
 */
html {
  font-size: 62.5%;
}

:root {

  /* ------------------------------------------------------------- type stacks
   * The system stack, because a platform has no business shipping a typeface.
   * A site that wants one declares --font-sans and loads it.
   */
  --font-sans: system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", monospace;

  /* The faceted listing's filter column (filters.css). A site sets its own. */
  --width-sidebar: 26rem;

  /* --------------------------------------------------- surfaces and the lines
   * The BASE ramp. Whether it is warm or cool is the palette's business.
   */
  --color-surface: var(--white, #ffffff);
  --color-surface-sunk: var(--base-ultra-light, #fafafa);
  --color-surface-sunk-2: var(--base-semi-light, #f4f4f3);
  --color-surface-hover: var(--base-light, #f7f7f7);
  /*
   * ⚠️ SELECTED IS NOT HOVERED (D224). A pressed segmented key, a chosen tab,
   * an open menu: these were painted with --color-surface-sunk, the same shade
   * a list's every-other row already uses, so on a banded list the active view
   * had exactly the weight of a stripe and could not be found. A selected thing
   * is one step further than anything a pointer does.
   */
  --color-surface-on: var(--base-semi-light, #ededed);
  --color-border: var(--base-semi-dark, #e6e6e6);
  --color-border-strong: var(--base-dark, #d6d6d6);
  --color-hairline: var(--base-semi-light, #f0f0f0);

  /* -------------------------------------------------------------------- text
   * The NEUTRAL ramp, kept separate from the surfaces on purpose: one grey
   * doing both jobs is what makes a site look machine-made.
   */
  --color-text: var(--neutral-dark, #1a1a1f);
  --color-text-body: var(--neutral-semi-dark, #3d3d45);
  --color-text-muted: var(--neutral, #6a6a74);
  --color-text-quiet: var(--neutral, #6f6f79);

  /* ------------------------------------------------------------------ accent
   * ⚠️ `-ink` IS THE ONE THAT CARRIES WHITE TYPE. The lighter accent fails
   * contrast under a white label - measured at 3.1:1 on this platform's own
   * filled button before it moved - so the button spends `-ink` and this is
   * where that distinction is kept.
   */
  --color-accent: var(--primary, #2f6fed);
  --color-accent-hover: var(--primary-hover, #2a63d4);
  --color-accent-ink: var(--primary-hover, #2a63d4);
  --color-accent-ink-hover: var(--primary-semi-dark, #1f4ba3);
  --color-accent-soft: var(--primary-light, #e8f0fe);
  --color-on-accent: var(--white, #ffffff);
  --color-on-accent-soft: var(--primary-semi-dark, #1f4ba3);

  /* ------------------------------------------------------------------ status
   * ⚠️ success, warning and danger SHIP DISABLED IN ACSS, and a role that is
   * off emits no token at all. Until a site's acss-roles.json turns them on,
   * every one of these renders the fallback beside it.
   */
  --color-success: var(--success, #2e9c5a);
  --color-success-ink: var(--success-semi-dark, #1c6b3c);
  --color-check: var(--success, #2e9c5a);
  --color-warning-ink: var(--warning-semi-dark, #8a5a00);
  --color-error: var(--danger, #d94b4b);
  --color-purple: var(--tertiary, #8b5cf6);

  /* The rating stars (D222): an unchosen star is a grey tile, a chosen or
     hovered one takes the rating colour. Site one's look, made the default;
     a site restyles them by setting these four, never by rewriting the rules. */
  /* ⚠️ A TINT OF THE TEXT, not a shade. A fixed grey vanished on site
     three's dark panel, which was that grey; the text laid thinly over
     whatever is underneath stands off any ground, in either mode. */
  --color-star-off: color-mix(in oklab, var(--color-text) 8%, transparent);
  --color-star-glyph-off: color-mix(in oklab, var(--color-text) 35%, transparent);
  --color-rating: var(--accent, #f5b93b);
  --color-on-rating: var(--color-surface);
  --vote-star-size: 4rem;

  /* HOVER IS A COLOUR, SET PER SITE LIKE ONE (D223). A linked card takes
     --hover-ground, a text link --hover-ink; no lift, no motion. Both are
     ACSS shades, so the palette moves them, and a site re-points them in its
     tokens.css. Drawings spend these rather than inventing a hover each. */
  --hover-ground: var(--primary-ultra-light);
  /*
   * ⚠️ ACSS'S OWN HOVER SHADE, so "where do I change the hover colour" has an
   * answer in the panel: Colours, the brand colour, its hover. It is also what
   * ACSS gives its own links (--link-color-hover is the same value), so a
   * card's name and a text link light to the same colour (D224).
   */
  --hover-ink: var(--primary-hover);

  /* THE NOTE (D224): the quiet line under or beside a title, and the state a
     block says back ("No conversation yet", "The youngest names in the index").
     One size and one colour, set here and per site in its tokens.css; a tone
     (a refusal, a confirmation) keeps its own colour. */
  --note-size: var(--text-s);
  --note-color: var(--color-text-muted);

  /* THE LABEL (D224): the small text that names a question or a group. A
     vote card's question ("Your take", "Seen it?"), the sort's "Sort by", an
     account tile. One look, whatever a design calls the question, set here
     and changed per site in its tokens.css. */
  --label-font: var(--font-mono);
  --label-size: var(--text-xs);
  --label-weight: 400;
  --label-color: var(--color-text-muted);
  --label-case: uppercase;
  --label-tracking: 0.13rem;

  /* The detail page's sidebar, set per site like a corner (D224). */
  --sidebar-width: 34rem;

  /* A choice pill's icon chip sits the same distance from the pill's top,
     bottom and start, and its corners follow the pill's: its radius is the
     pill's minus that inset. A site sets the pill's radius here. */
  /* ⚠️ The control corner, as controls.css learned: the platform's own guess of
     6px sat beside 12px buttons on the fourth site (D223). */
  --vote-choice-radius: var(--radius-m-2);
  --vote-chip-size: 2.4rem;
  --vote-chip-inset: 0.6rem;

  /* A choice card's options, in the order the dataset declares them (D222):
     fragrance's have, want, had, as green, red and the accent. A fourth and
     later option takes the accent. The chip's tint is mixed from these, so a
     site sets three colours and dark mode follows on its own. */
  --color-choice-a: var(--color-success);
  --color-choice-b: var(--color-error);
  --color-choice-c: var(--color-accent);
  --color-on-choice: var(--white, #ffffff);

  /* ---------------------------------------------------------------- borders */
  --border-hair: 0.1rem;
  --border-thick: 0.2rem;

  /* ----------------------------------------------------------------- radius
   * ⚠️ ACSS CAN EMIT A RADIUS LADDER - `option-radius-sizes`, off by default,
   * generated from base-radius and radius-scale - but it is GEOMETRIC, one
   * ratio throughout. A hand-drawn ladder rarely is: site-one's runs 3, 6, 10,
   * 16, 20, whose ratios are 2.0, 1.67, 1.6 and 1.25, and the closest ACSS fit
   * makes its smallest radius 67% bigger.
   *
   * So radius stays declared rather than generated, here and on every site.
   */
  /* ONE KNOB (D224): every corner is a multiple of --radius-base, so a site
     rounds or squares everything by setting it once; 0 is a square site.
     --radius-full stays a pill whatever the base. */
  --radius-base: 1rem;
  --radius-s: calc(var(--radius-base) * 0.6);
  --radius-m-2: calc(var(--radius-base) * 1.2);
  --radius-l-2: calc(var(--radius-base) * 1.8);
  --radius-full: 99rem;

  /* --------------------------------------------------------------- controls
   * ACSS'S OWN RECIPE, IN OUR NAMES (D224).
   *
   * ACSS sizes a button intrinsically: `0.5em` of block padding, `1.25em` of
   * inline padding and a line height of 1. So a band's height is its type step
   * twice over plus its border, and its inline padding is that step times 1.25,
   * and the whole ladder follows the type scale with no numbers of its own.
   * Measured against ACSS's classes: btn--s 29.5px, btn--m 31.5, btn--xxl 50.1.
   *
   * ⚠️ WE STILL SIZE BY min-height, and that is the one real difference. ACSS
   * lets a button be as tall as its padding makes it; a row of mixed controls
   * (a field, its submit, a select) only lines up if they share an explicit
   * height. The recipe is ACSS's, the floor is ours.
   *
   * These stopped being 3rem, 2.6rem and 5rem, three numbers chosen by hand
   * that drifted from every ACSS button a drawing put beside them.
   *
   * ⚠️ THE LARGE BAND IS TALLER, NOT LOUDER. Its height follows the xxl step
   * and its TYPE does not: an archive's search box is a big target, not big
   * text, and at --text-xxl it shouted its placeholder at the page (D224).
   * controls.css sets that type; only the box is from the ladder here.
   *
   * `--tap-min` is the floor a tap target may not go under. In rem so it grows
   * with the reader's own font size, which is the entire reason it exists.
   */
  --control-h-s: calc(var(--text-s) * 2 + 2px);
  --control-h: calc(var(--text-m) * 2 + 2px);
  --control-h-l: calc(var(--text-xxl) * 2 + 2px);
  --control-px-s: calc(var(--text-s) * 1.25);
  --control-px: calc(var(--text-m) * 1.25);
  --control-px-l: calc(var(--text-xxl) * 1.25);
  --tap-min: 2.4rem;

  /* -------------------------------------------------------------------- odds
   * The lightness of the hatch behind an empty state.
   */
  --hatch-l: 96%;

  /* ------------------------------------------------- the space ACSS does not
   * ACSS's scale runs xs to xxl, and the ones ACSS defines are left to it
   * entirely - declaring them here would tie with ACSS at `:root` and win or
   * lose on load order, which is not a thing to leave to chance.
   *
   * ⚠️ ONLY THE TWO BELOW xs ARE OURS NOW. Three half-steps used to be declared
   * here as well - `--space-m-3`, `--space-m-4` and `--space-l-3` - and the
   * components spent them. They were the old mockup importer's collision
   * suffixes: two drawings with different scales, one value renamed `-3` to
   * survive. ACSS could never reach them, so a palette-and-scale change in
   * `acss-roles.json` restyled everything except the cards, facets and fields
   * that spent them. They fold onto ACSS's own steps.
   */
  --space-3xs: 0.2rem;
  --space-2xs: 0.4rem;
}

/*
 * ⚠️ THIS LADDER ONCE HELD A NAME ACSS ALSO USES, AND LOST.
 *
 * `--radius-m` was declared here and ACSS defines it as a straight alias of
 * `--radius`, so the two tied at 0-1-0 and ACSS won on load order: the
 * platform's 10px silently became ACSS's 5px, and every card, panel and control
 * on a site that ships no CSS of its own was drawn at half the radius the
 * components were written for. Caught by measuring, not by reading. It survived
 * for a while as `html:root { --radius-m }`, a deliberate specificity win over
 * a name we should not have owned.
 *
 * It is gone. The platform draws four corners (D224) and none of them is a name
 * ACSS has heard of, so there is nothing left to collide. Check before adding
 * one: every other name above is this platform's own vocabulary.
 */

/*
 * A dark section on a site that does NOT switch scheme: `scheme--dark`, ACSS's
 * own class, on the section.
 *
 * ACSS gives that class `color-scheme: dark` and nothing else, and every role
 * above is a LIGHT ramp step, so a vote card, a review box or the listing's
 * filters dropped into a dark section drew white panels with dark ink on it.
 * The same roles, re-pointed at the dark end of the same ramps. A drawing asks
 * for it by class; nothing here picks a hue.
 *
 * ⚠️ ONLY WHERE NOTHING FLIPS. On a site that switches (below) ACSS already turns
 * every shade inside `scheme--dark` into its twin, and re-pointing on top of
 * that flips the panel back to light.
 */
:root:not([data-ov-scheme]) .scheme--dark {
  --color-surface: var(--neutral-dark, #26262b);
  --color-surface-sunk: var(--neutral-ultra-dark, #16161a);
  --color-surface-sunk-2: var(--neutral-dark, #26262b);
  --color-surface-hover: var(--neutral-semi-dark, #3f3f46);
  --color-surface-on: var(--neutral-semi-dark, #3f3f46);
  --color-border: var(--neutral-semi-dark, #3f3f46);
  --color-border-strong: var(--neutral, #6a6a74);
  --color-hairline: var(--neutral-dark, #26262b);
  --color-text: var(--neutral-ultra-light, #f2f2f3);
  --color-text-body: var(--neutral-ultra-light, #f2f2f3);
  --color-text-muted: var(--neutral-semi-light, #a1a1a1);
  --color-text-quiet: var(--neutral-semi-light, #a1a1a1);
  --color-accent-ink: var(--primary, #c8322a);
  --color-accent-ink-hover: var(--primary-hover, #a82620);
  --color-accent-soft: var(--primary-ultra-dark, #2a0906);
  --color-on-accent-soft: var(--primary-light, #fbe3df);
  /* Mixed again here, or the tint is of the page's text, not the section's. */
  --color-star-off: color-mix(in oklab, var(--color-text) 8%, transparent);
  --color-star-glyph-off: color-mix(in oklab, var(--color-text) 35%, transparent);
}

/*
 * A site that SWITCHES between light and dark (D222): `data-ov-scheme` on
 * <html>, written when ACSS's colour-scheme support is on.
 *
 * ACSS then makes every shade a `light-dark()` pair and swaps the pairs:
 * ultra-light with ultra-dark, light with dark, semi-light with semi-dark. So
 * each role here sits on the LIGHT half of a pair, and its dark-mode value is
 * whatever that pair's other half is. The roles above cannot do that: they put
 * a border on `--base-semi-dark`, which on a light-only palette is a pale grey
 * and in a mirrored one is the dark end.
 *
 * ⚠️ IT ONLY WORKS ON A MIRRORED PALETTE. Every pair has to be a real light
 * value and a real dark one. A ramp whose "light" step sits at 56% lightness
 * turns every panel mid-grey in dark mode. verify-acss.php checks the pairs.
 */
:root[data-ov-scheme] {
  --color-surface: var(--base-ultra-light, #fafafa);
  --color-surface-sunk: var(--base-light, #f4f4f3);
  /*
   * ⚠️ THREE ROLES, THREE SHADES. These read --base-light all three, so a sunk
   * surface, a hover and a selected thing were one colour on any site that
   * switches scheme, and nothing could be a step darker than anything else
   * (D224).
   */
  --color-surface-sunk-2: var(--base-semi-light, #e6e6e6);
  --color-surface-hover: var(--base-light, #f4f4f3);
  --color-surface-on: var(--base-semi-light, #e6e6e6);
  --color-border: var(--base-semi-light, #e6e6e6);
  --color-border-strong: var(--neutral-semi-light, #a1a1a1);
  --color-hairline: var(--base-semi-light, #e6e6e6);
  --color-text: var(--neutral-ultra-dark, #16161a);
  --color-text-body: var(--neutral-dark, #26262b);
  --color-text-muted: var(--neutral-semi-dark, #3f3f46);
  --color-text-quiet: var(--neutral-semi-dark, #3f3f46);
  /* The primary itself, which a site gives an `alt` for dark mode, so the
     platform's buttons are the same colour as ACSS's btn--primary beside them.
     On semi-dark they flipped to a washed-out semi-light in dark mode (D222). */
  --color-accent-ink: var(--primary, #2f6fed);
  --color-accent-ink-hover: var(--primary-hover, #2a63d4);
  --color-accent-soft: var(--primary-light, #e8f0fe);
  --color-on-accent: var(--primary-ultra-light, #ffffff);
  --color-on-accent-soft: var(--primary-dark, #1f3b7a);
  --color-success-ink: var(--success-dark, #1c6b3c);
  --color-warning-ink: var(--warning-dark, #8a5a00);
}

/*
 * A floor under ACSS's button utilities: every `btn--*` is at least a tap
 * target tall. `btn--xs` and `btn--none` drew 19 to 22px, under the 24px
 * minimum, the first time the design kit put all of them on one page (D222).
 * Zero specificity, so a drawing that sizes a button itself still wins.
 */
:where([class*="btn--"]:not([class*="oview-btn"], [class*="ov-btn"])) {
  min-block-size: var(--tap-min, 2.4rem);
}

/*
 * ⚠️ A THING YOU CLICK SHOWS A HAND. A drawn <button> reaches Bricks as a text
 * element, so the slider's Back and More showed a text cursor over their words
 * on the fourth site (D223). Zero specificity: a site's own cursor still wins.
 */
:where([class*="btn--"], [data-oview-slider-prev], [data-oview-slider-next], button, [role="button"], a[href]),
:where([class*="btn--"], [data-oview-slider-prev], [data-oview-slider-next]) * {
  cursor: pointer;
}

/*
 * ⚠️ A PAGE BRICKS HAS NO TEMPLATE FOR SITS IN THE FRAME TOO. The forum, a
 * privacy policy, anything WordPress renders itself, arrives in Bricks'
 * fallback `#brx-content.wordpress` at Bricks' own 1100px: at 1600px the forum
 * started at 250 under a header at 117 (D223). It carries the gutter a header
 * does, because ACSS pads sections and this is not one. `body` first, because
 * Bricks' content-default.css says `width: 1100px` at the same specificity
 * and loads after this file.
 */
body #brx-content.wordpress {
  box-sizing: border-box;
  width: 100%;
  max-width: calc(var(--content-width) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/*
 * THE DETAIL PAGE, ONE LAYOUT FOR EVERY SITE (D224). A drawing puts the page's
 * subject in `oview-detail__main` and, when it has one, a sidebar in
 * `oview-detail__aside`, both inside `oview-detail`; it never lays them out
 * itself. So whether a page has a sidebar is the drawing's choice, and where
 * the sidebar goes is the platform's: beside the main column while there is
 * room for one, and AFTER it below 992px, because it comes after it in the
 * markup. That order is also what keeps the outline whole: the sidebar's h3s
 * follow the main column's h2s instead of jumping ahead of them.
 */
.oview-detail {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--sidebar-width);
  gap: var(--space-xl);
  align-items: start;
}

.oview-detail__main {
  display: flex;
  flex-direction: column;
  gap: var(--space-xxl);
  min-width: 0;
}

.oview-detail__aside {
  position: sticky;
  top: calc(var(--oview-header-bottom, 6rem) + var(--space-m));
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
  min-width: 0;
}

/*
 * ⚠️ A MODULE THAT SHOWS FIVE OF SOMETHING SAYS WHERE THE REST ARE (D224).
 * Site one's sidebar ended every list with "See all releases" and the fourth
 * site's ended with the fifth row and nothing, because the row was a drawing's
 * habit rather than a part. It is a part now: the last child of a panel, the
 * full width of it, a line above, quiet until pointed at.
 *
 * It is a link to a page that already exists, usually a listing filtered the
 * way the module is sorted. A module with no such page has no row.
 */
.oview-see-all {
  display: block;
  margin-top: var(--space-xs);
  /*
   * ⚠️ THE PANEL'S OWN BOTTOM PADDING IS THE SPACE UNDER THIS ROW, so the row
   * pads the SAME amount above its text and none below. Padding the row evenly
   * puts --space-m under the text and --space-xs over it, and the line sits
   * closer to the words than the panel's edge does (D224).
   */
  padding: var(--space-m) var(--space-m) 0;
  border-top: 1px solid var(--neutral-semi-light);
  color: var(--note-color);
  font-size: var(--note-size);
  /* An action, not a caption: quiet in colour, sure of itself in weight. */
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}

.oview-see-all:hover,
.oview-see-all:focus-visible {
  color: var(--hover-ink);
}

@media (max-width: 991px) {
  .oview-detail {
    grid-template-columns: minmax(0, 1fr);
  }

  .oview-detail__aside {
    position: static;
  }
}

/* ==========================================================================
 * THE RAIL: ITS SCROLLBAR AND ITS TWO ARROWS, FOR EVERY SITE
 *
 * ⚠️ BOTH WERE LEFT TO THE DRAWING AND NEITHER WAS EVER DRAWN (D224). A rail
 * track is a real overflow container, so it came with the operating system's
 * scrollbar: a thick grey slab under a row of cards, in a design that owns
 * every other pixel. And its two buttons said "Back" and "More" in words, so a
 * row of cards ended with two lozenges of text competing with the card names.
 *
 * Both are keyed off the marks the platform already defines, `data-oview-slider`
 * and its prev/next, so a drawing gets them by using the slider at all.
 * ========================================================================== */

[data-oview-slider] {
  scrollbar-width: thin;
  scrollbar-color: var(--neutral-semi-light) transparent;
}

[data-oview-slider]::-webkit-scrollbar {
  height: 0.6rem;
}

[data-oview-slider]::-webkit-scrollbar-track {
  background: transparent;
}

[data-oview-slider]::-webkit-scrollbar-thumb {
  border-radius: var(--radius-full);
  background: var(--neutral-semi-light);
}

/*
 * No darker thumb on hover: a step within one ramp is not a hover in this
 * system (D223), and the check that holds that line says so.
 */

/*
 * ⚠️ THE LABEL IS THE aria-label, NOT THE TEXT. The text collapses to nothing
 * so the button is a square, and the chevron is drawn as a mask over
 * currentColor, which means it takes the button's own colour in both schemes
 * and on hover without a second rule.
 *
 * ⚠️ THE ATTRIBUTE IS WRITTEN TWICE, and `button` is not in the selector at
 * all. ACSS's btn--s sets a font size at one class and this file loads before
 * ACSS, so a :where() rule at zero specificity left the words showing through
 * the icon; and Bricks exports a button element as a `<span class="brxe-button">`,
 * so naming the tag matched nothing. Doubling the attribute buys the specificity
 * without !important and without caring what tag the builder chose.
 */
/*
 * ⚠️ AND WHATEVER HOLDS THEM CENTRES ITSELF. A section head aligns its parts on
 * their baselines, and a button whose label is font-size 0 has its baseline at
 * the bottom of the circle, so the pair hung below the title it belongs to.
 * `:has()` lets the platform reach a container it did not draw and has no name
 * for (D224).
 */
:has(> [data-oview-slider-prev]),
:has(> [data-oview-slider-next]) {
  align-self: center;
}

[data-oview-slider-prev][data-oview-slider-prev],
[data-oview-slider-next][data-oview-slider-next] {
  --oview-chevron: 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.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E");
  /*
   * ⚠️ THE ICON IS PINNED, NOT LAID OUT. The label's text node is still a child
   * even at font-size 0, so centring by grid or flex gives the button TWO items
   * and the chevron lands in the upper half of the circle. `inset: 0` with
   * `margin: auto` centres a fixed-size box in its padding box whatever else is
   * in there.
   */
  position: relative;
  display: inline-block;
  inline-size: var(--control-h);
  block-size: var(--control-h);
  padding: 0;
  border-radius: var(--radius-full);
  /*
   * ⚠️ THE LABEL IS PUSHED OUT, NOT SHRUNK TO NOTHING. font-size: 0 hid it and
   * failed the mobile gate's 12px text floor, which reads every text node on
   * the page and cannot tell a hidden label from a tiny one (D224).
   */
  overflow: hidden;
  text-indent: 150%;
  white-space: nowrap;
}

[data-oview-slider-prev][data-oview-slider-prev]::before,
[data-oview-slider-next][data-oview-slider-next]::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: 1.4rem;
  block-size: 1.4rem;
  background: currentColor;
  -webkit-mask: var(--oview-chevron) center / contain no-repeat;
  mask: var(--oview-chevron) center / contain no-repeat;
}

[data-oview-slider-prev][data-oview-slider-prev]::before {
  transform: scaleX(-1);
}

/* ==========================================================================
 * A LEDE, WHICH THE PLATFORM'S OWN FIXTURE EMITS AND NOTHING STYLED (D225).
 *
 * `seed-test-article.php` writes `<p class="ov-prose-lede">` as the article's
 * opening paragraph, because an opening paragraph is a real typographic role:
 * it says "start here" and it sets the article's voice. On site five it
 * measured 14.09px in the body colour - identical to the paragraph under it -
 * so the class was a promise the platform never kept, on every site but the
 * first.
 *
 * ⚠️ A BASE MEANING, NOT A TREATMENT. One step up the ladder and a little
 * quieter, which is what a lede is anywhere. Site one sets a serif drop cap on
 * top of this and that is editorial: it belongs to that site's voice, not to
 * every site that ever renders a post.
 *
 * Not scoped to a prose wrapper, deliberately. The class is on the element
 * itself, so this works whether or not a site's article template wraps its
 * content in `.ov-prose` - and a new site's does not, because it has no
 * article template yet.
 * ========================================================================== */

.ov-prose-lede {
	font-size: var(--text-l);
	line-height: 1.5;
	color: var(--color-text-muted, var(--neutral-semi-dark));
}
