/*
Theme Name: Pages by the Shore
Theme URI: https://pagesbytheshore.com
Description: Child theme of Twenty Twenty-Five implementing the Pages by the Shore v1 brand system. Ships both modes — Daybreak on the Shore (light, default) and Dusk on the Shore (dark), switchable from a footer dropdown. Palette, typography, and design laws per the canonical brand token sheet (frozen 2026-07-16). Fonts are self-hosted; no third-party font CDN on the live site.
Author: Katie Ellsworth
Template: twentytwentyfive
Version: 1.9.7
Requires at least: 6.7
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: pbts
*/

/* =========================================================
   Pages by the Shore — custom styles
   ---------------------------------------------------------
   theme.json carries the DAYBREAK palette, the self-hosted
   font registration, and element defaults. This file carries
   what theme.json can't express cleanly: the wordmark, the
   design laws, the accessibility floor, the DUSK overlay,
   and the footer theme switch.
   ========================================================= */

/* --- Design Law 2: inline links are always underlined ---
   Scoped to in-content links, NOT nav items or buttons.
   Reasoning is in the build guide — change the scope here
   if you decide nav links should underline too. */
.wp-block-post-content a:where(:not(.wp-element-button)),
.entry-content a:where(:not(.wp-element-button)),
.wp-block-post-excerpt a {
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

/* --- Wordmark (Site Title): Fraunces italic 500, Deep ---
   Matches the wordmark demo on the brand sheet. Uses the
   Deep token, so it re-themes correctly in Dusk. */
.wp-block-site-title,
.wp-block-site-title a {
  font-family: var(--wp--preset--font-family--fraunces);
  font-style: italic;
  font-weight: 500;
  color: var(--wp--preset--color--deep);
  text-decoration: none;
  letter-spacing: 0.01em;
}

/* --- Eyebrow / utility label: IBM Plex Mono ---
   Add the class "pbts-eyebrow" to any paragraph or heading
   (Block settings > Advanced > Additional CSS class(es)). */
.pbts-eyebrow {
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--wp--preset--color--muted);
}

/* --- Accessibility floor: visible keyboard focus (Sun Gold) --- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.wp-block-button__link:focus-visible {
  outline: 2px solid var(--wp--preset--color--sun-gold);
  outline-offset: 2px;
}

/* --- Respect the reduced-motion preference --- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* =========================================================
   DUSK ON THE SHORE — dark mode overlay
   ---------------------------------------------------------
   The .pbts-dusk class is added to <html> by the footer
   switch, and re-applied before paint by the head script
   (so there's no flash). Scoping the overrides to
   `html.pbts-dusk body` is deliberate: it reliably beats
   WordPress's own :root/body preset output, which a plain
   :root override does not. Everything re-themes automatically
   BECAUSE every color references a token — which is why you
   must always pick the named palette swatches, never a raw
   hex, on your blocks. Values are the brand sheet's Dusk set.
   ========================================================= */
html.pbts-dusk { background-color: #132734; } /* overscroll area */
html.pbts-dusk body {
  --wp--preset--color--background: #132734;
  --wp--preset--color--surface:    #1c3542;
  --wp--preset--color--ink:        #e9ebe6;
  --wp--preset--color--muted:      #a1b2b3;
  --wp--preset--color--lake:       #7fb0bf;
  --wp--preset--color--deep:       #d5e3e4;
  --wp--preset--color--sun-gold:   #e0b46e;
  --wp--preset--color--wild-rose:  #eda9c6;
  --wp--preset--color--lupine:     #c8b7e4;
  --wp--preset--color--line:       #2c4653;
  --wp--preset--color--sage:       #98b291;
  --wp--preset--color--ember:      #d08366;
  --wp--preset--color--on-primary: #132734;
}

/* =========================================================
   Footer theme switch (the dropdown)
   Markup for this lives in the footer template part — see
   the build guide. The control itself uses brand tokens, so
   it also re-themes in Dusk.
   ========================================================= */
.pbts-theme-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.pbts-theme-switch label {
  margin: 0;
}
.pbts-theme-select {
  font-family: var(--wp--preset--font-family--atkinson-hyperlegible);
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--wp--preset--color--ink);
  background: var(--wp--preset--color--surface);
  border: 1px solid var(--wp--preset--color--line);
  border-radius: 6px;
  padding: 4px 8px;
  cursor: pointer;
}

/* =========================================================
   Minimal footer — sits on a hairline rule and breathes.
   The block markup for the footer lives in the build guide;
   this just gives it its spacing and top border. Uses the
   Line + Surface tokens, so it re-themes in Dusk too.
   ========================================================= */
.pbts-footer {
  border-top: 1px solid var(--wp--preset--color--line);
  margin-top: 3rem;
  padding-top: 1.25rem;
  padding-bottom: 1.25rem;
  font-size: 0.9rem;
}

/* =========================================================
   Fluent Forms — map the plugin's colors onto the brand tokens.
   Fluent lets font-family cascade from the theme (labels already
   use Atkinson) but leaves its own colors. We repaint them with
   tokens, so the form re-themes in Dusk for free.

   IMPORTANT: these target Fluent's own element classes DIRECTLY
   (.ff-el-form-control, .ff-btn-submit, …) with no form ancestor.
   An earlier version scoped to `form.fluentform`, which assumes
   the `fluentform` class is on the <form> tag — it isn't, so the
   rules matched nothing. Those ff-* classes are unique to Fluent,
   so targeting them directly is both safe and reliable.
   ========================================================= */

/* Inputs, textareas, selects */
.ff-el-form-control {
  background-color: var(--wp--preset--color--surface);
  color: var(--wp--preset--color--ink);
  border: 1px solid var(--wp--preset--color--line);
  border-radius: 6px;
}
.ff-el-form-control::placeholder {
  color: var(--wp--preset--color--muted);
  opacity: 1;
}
.ff-el-form-control:focus {
  border-color: var(--wp--preset--color--lake);
  outline: 2px solid var(--wp--preset--color--sun-gold);
  outline-offset: 1px;
  box-shadow: none;
}

/* Labels (color only — Fluent's bold weight is fine) */
.ff-el-input--label label {
  color: var(--wp--preset--color--ink);
}

/* Submit button.
   Your form's button carries `ff_btn_no_style`, so the browser
   was drawing it as a NATIVE control (that "buttonface" from the
   User Agent stylesheet). You can't paint over a native button
   without first removing its native appearance — hence the two
   appearance:none lines. Then we fill it with Lake. !important
   guards against Fluent's own button rules; the appearance reset
   is what actually makes the fill show. */
.ff-btn.ff-btn-submit {
  -webkit-appearance: none;
  appearance: none;
  background-color: var(--wp--preset--color--lake) !important;
  color: var(--wp--preset--color--on-primary) !important;
  border: none;
  border-radius: 6px;
  padding: 0.6em 1.4em;
  cursor: pointer;
}
.ff-btn.ff-btn-submit:hover,
.ff-btn.ff-btn-submit:focus {
  background-color: var(--wp--preset--color--deep) !important;
  color: var(--wp--preset--color--on-primary) !important;
}

/* Required asterisks + error text → Ember (brand's warm alarm).
   .text-danger is scoped under .ff-el-group so it can't collide
   with other plugins that use that common class name. */
.ff-el-group .text-danger,
.ff-el-is-required > label::after {
  color: var(--wp--preset--color--ember);
}
/* Error-state field border → Ember */
.ff-el-is-error .ff-el-form-control {
  border-color: var(--wp--preset--color--ember);
}
/* Success message → Sage */
.ff-message-success {
  color: var(--wp--preset--color--sage);
  border-color: var(--wp--preset--color--sage);
}

/* --- Block styles (registered in functions.php) ---------------------
   These appear in the block sidebar under Styles, so you don't have to
   remember a class name. Same treatments as the utility classes above. */

/* Eyebrow: the brand's utility voice — mono, tracked, uppercase.
   Works on paragraphs and headings. Note that a heading using this
   style keeps its heading level (and its place in the document
   outline) while looking like a label. */
.is-style-pbts-eyebrow {
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--wp--preset--color--muted);
}

/* Lede: the opening paragraph of a page. Slightly larger and quieter
   than body copy, which sets it apart without changing typeface. */
.is-style-pbts-lede {
  font-size: var(--wp--preset--font-size--large);
  line-height: 1.5;
  color: var(--wp--preset--color--muted);
  /* 62ch is the reading-measure target, but at this font size it
     computes wider than the 720px content column. WordPress caps
     children of a constrained container using a :where() selector,
     which carries zero specificity — so a plain max-width here
     would beat it and the lede would render wider than the title
     and rule above and below it. Cap explicitly at whichever is
     smaller. */
  max-width: min(62ch, var(--wp--style--global--content-size));
}

/* =========================================================
   Masthead
   ---------------------------------------------------------
   The problem this solves: the header sat on the same Mist
   canvas as the page content, with no rule and a small
   wordmark, so "site" and "page" read as one undifferentiated
   surface. Filling it with Surface and closing it with a
   hairline gives the header a job; the larger wordmark gives
   it presence. All values are tokens, so Dusk flips for free.
   ========================================================= */
.wp-site-blocks > header {
  background-color: var(--wp--preset--color--surface);
  border-bottom: 1px solid var(--wp--preset--color--line);
  padding-block: clamp(0.75rem, 1.8vw, 1.25rem);
}

/* Wordmark size lives here rather than on the block so every
   place the site title appears stays in agreement. */
.wp-block-site-title a {
  font-size: clamp(1.75rem, 3.2vw, 2.5rem);
  line-height: 1.15;
}

/* Nav in the brand's utility voice: IBM Plex Mono, tracked and
   uppercase. This does two jobs — it widens the hierarchy gap so
   the Fraunces wordmark clearly leads, and it puts the mono face
   to work where the brand sheet intends it (labels and wayfinding,
   not prose). Kept at 13px rather than the 11px used for eyebrows:
   these are tap targets and links, so legibility outranks delicacy.
   Nav stays un-underlined by design — Law 2 is scoped to in-content
   links, and underlining every nav item would fight the tracking. */
.wp-site-blocks > header .wp-block-navigation {
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.wp-site-blocks > header .wp-block-navigation a {
  color: var(--wp--preset--color--ink);
}
.wp-site-blocks > header .wp-block-navigation a:hover {
  color: var(--wp--preset--color--lake);
}
/* Current page gets Lake — wayfinding needs a "you are here." */
.wp-site-blocks > header .wp-block-navigation .current-menu-item a,
.wp-site-blocks > header .wp-block-navigation .wp-block-navigation-item.current-menu-item > a {
  color: var(--wp--preset--color--lake);
}

/* Mobile overlay: same voice, but sized up. Tracked uppercase at
   13px is fine in a horizontal bar and cramped in a full-screen
   menu, where each item is a thumb target. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
  font-size: 1rem;
  letter-spacing: 0.14em;
}

/* Trim the gap between the masthead and the page title.
   NOTE: this only wins if the gap is padding on <main>. If a
   large space remains, the template contains a Spacer block —
   delete it in the Site Editor instead. */
.wp-site-blocks > main {
  padding-top: clamp(1.5rem, 4vw, 2.5rem);
}

/* =========================================================
   BLOG (added v1.8.0)
   ---------------------------------------------------------
   Three templates ship in /templates: home.html (the Blog
   posts page), archive.html (category archives), single.html
   (posts). All typographic — no image slots anywhere, per the
   blog reference. Cards separate with hairline rules, the
   same device the masthead uses, so "list of posts" speaks
   the site's existing structural language.
   ========================================================= */

/* --- Page header: Eyebrow + Title + Lede, the pattern from
   the site's open-items list, debuting here. --- */
.pbts-page-header {
  margin-bottom: 2.5rem;
}
.pbts-page-header .is-style-pbts-eyebrow {
  margin-bottom: 0.5rem;
}
.pbts-page-header h1 {
  margin-top: 0;
  margin-bottom: 0.5rem;
}
/* Term description rendered as the lede on category archives.
   (The Lede block style targets paragraphs; term-description
   wraps its text in a div, so we restate the treatment.) */
.pbts-page-header .wp-block-term-description {
  font-size: var(--wp--preset--font-size--large);
  line-height: 1.5;
  color: var(--wp--preset--color--muted);
  max-width: 62ch;
  margin-top: 0;
}

/* --- Archive cards ------------------------------------- */
.pbts-post-list .pbts-post-card {
  padding-block: 1.75rem;
  border-bottom: 1px solid var(--wp--preset--color--line);
  margin-block: 0;
}
.pbts-post-list .wp-block-post-template > li:first-child .pbts-post-card {
  border-top: 1px solid var(--wp--preset--color--line);
}

/* Meta row: category + date share one mono line. */
.pbts-card-meta {
  gap: 0.5rem 1.25rem;
  margin-bottom: 0.4rem;
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.pbts-card-cat,
.pbts-card-cat a {
  color: var(--wp--preset--color--lake);
  text-decoration: none;
}
.pbts-card-cat a:hover {
  color: var(--wp--preset--color--deep);
  text-decoration: underline;
  text-underline-offset: 0.12em;
}
.pbts-card-date {
  color: var(--wp--preset--color--muted);
}

/* Title: Fraunces via the heading defaults; the link is
   wayfinding (like nav), so it underlines on hover only. */
.pbts-card-title {
  margin: 0 0 0.4rem;
  font-size: var(--wp--preset--font-size--x-large);
  line-height: 1.2;
}
.pbts-card-title a {
  color: var(--wp--preset--color--deep);
  text-decoration: none;
}
.pbts-card-title a:hover {
  color: var(--wp--preset--color--lake);
  text-decoration: underline;
  text-underline-offset: 0.12em;
  text-decoration-thickness: 1px;
}

.pbts-card-excerpt {
  color: var(--wp--preset--color--ink);
  max-width: 68ch;
}
.pbts-card-excerpt p {
  margin: 0;
}
/* If a "read more" link renders, keep it quiet. Cleanest is
   the block's own toggle: hide the more link in the template. */
.pbts-card-excerpt .wp-block-post-excerpt__more-link {
  display: none;
}

/* Pagination in the utility voice. */
.pbts-pagination {
  margin-top: 2rem;
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.pbts-pagination a {
  color: var(--wp--preset--color--lake);
  text-decoration: none;
}
.pbts-pagination a:hover {
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

/* --- Single post header: Eyebrow + Title + Date ---------- */
.pbts-post-header {
  margin-bottom: 2.25rem;
}
.pbts-post-header .pbts-card-cat {
  margin-bottom: 0.6rem;
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.pbts-post-header h1 {
  margin-top: 0;
  margin-bottom: 0.6rem;
}
.pbts-post-header .pbts-card-date {
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wp--preset--color--muted);
}

/* --- Data-post furniture: tables & figures ---------------
   The single template serves two shapes — chart/table-heavy
   data posts and short prose reading posts. Prose needs
   nothing; tables get the brand's data voice. A table (or
   any block) set to Wide alignment stretches to 1200px. --- */
.wp-block-post-content .wp-block-table table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--wp--preset--font-size--small);
}
.wp-block-post-content .wp-block-table th {
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wp--preset--color--muted);
  text-align: left;
  border-bottom: 2px solid var(--wp--preset--color--line);
  padding: 0.5rem 0.6rem;
}
.wp-block-post-content .wp-block-table td {
  border-bottom: 1px solid var(--wp--preset--color--line);
  padding: 0.5rem 0.6rem;
  vertical-align: top;
}
.wp-block-post-content .wp-block-table figcaption,
.wp-block-post-content figure figcaption {
  font-family: var(--wp--preset--font-family--ibm-plex-mono);
  font-size: 0.75rem;
  color: var(--wp--preset--color--muted);
  text-align: left;
  margin-top: 0.5rem;
}

/* --- Prev/next navigation on posts ----------------------- */
.pbts-post-nav {
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--wp--preset--color--line);
  font-size: var(--wp--preset--font-size--small);
}
.pbts-post-nav .wp-block-post-navigation-link {
  max-width: 45%;
}
.pbts-post-nav .post-navigation-link-next {
  text-align: right;
  margin-left: auto;
}
.pbts-post-nav a {
  color: var(--wp--preset--color--lake);
  text-decoration: none;
}
.pbts-post-nav a:hover {
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

/* =========================================================
   Category colors (added v1.9.0)
   ---------------------------------------------------------
   Three categories, three voices, three accent colors — the
   brand sheet names "category chips" as Lupine's job, so this
   is spending the palette where it was budgeted.

     Book World Data  → Lake       (the analyst; the brand's
                                    working color, and the
                                    Insight Studio's voice)
     The MLIS Shelf   → Lupine     (the student; the rare
                                    accent for a rare topic)
     Reading Life     → Wild Rose  (the reader; the warmest
                                    text-capable accent for
                                    the most personal voice)

   Sun Gold is deliberately NOT here: it's AA-Large only, so
   Design Law 3 disqualifies it from 11px labels. It earns its
   keep as a rule instead (see the section below).

   Law 1 holds — the category NAME is always present, so color
   is decoration, never the sole carrier of meaning.

   Targeting: the post-terms block renders plain <a> tags with
   no slug class, so these match on the category URL. If a
   category slug ever changes, update the selector to match.
   ========================================================= */

/* --- On cards and post headers (the term link itself) --- */
.pbts-card-cat a[href*="/category/book-world-data"] {
  color: var(--wp--preset--color--lake);
}
.pbts-card-cat a[href*="/category/mlis-shelf"] {
  color: var(--wp--preset--color--lupine);
}
.pbts-card-cat a[href*="/category/reading-life"] {
  color: var(--wp--preset--color--wild-rose);
}
/* Hover deepens rather than switching hue, so the category
   identity survives the interaction. */
.pbts-card-cat a[href*="/category/"]:hover {
  color: var(--wp--preset--color--deep);
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

/* --- On category archive pages -------------------------
   WordPress puts a category-<slug> class on <body>, which
   lets the archive's own eyebrow + gold rule pick up the
   category's color. The H1 stays Deep: a full-size Fraunces
   heading in an accent color would overpower the page. */
body.category-book-world-data .pbts-page-header .is-style-pbts-eyebrow {
  color: var(--wp--preset--color--lake);
}
body.category-mlis-shelf .pbts-page-header .is-style-pbts-eyebrow {
  color: var(--wp--preset--color--lupine);
}
body.category-reading-life .pbts-page-header .is-style-pbts-eyebrow {
  color: var(--wp--preset--color--wild-rose);
}

/* =========================================================
   Sun Gold rule (added v1.9.0)
   ---------------------------------------------------------
   One warm note in a cool palette. A short gold rule closes
   the page header — decorative use only, which is exactly
   what Sun Gold is licensed for (Law 3: never small text).
   Deliberately short and left-aligned rather than a full-
   width band: it reads as a mark, not a divider.
   ========================================================= */
.pbts-page-header::after,
.pbts-post-header::after {
  content: "";
  display: block;
  width: 3rem;
  height: 3px;
  margin-top: 1.5rem;
  background-color: var(--wp--preset--color--sun-gold);
  border-radius: 2px;
}

/* On category archives, the rule takes the category's color
   instead — the header then reads as belonging to that
   category rather than to the site generally. */
body.category-book-world-data .pbts-page-header::after {
  background-color: var(--wp--preset--color--lake);
}
body.category-mlis-shelf .pbts-page-header::after {
  background-color: var(--wp--preset--color--lupine);
}
body.category-reading-life .pbts-page-header::after {
  background-color: var(--wp--preset--color--wild-rose);
}

/* =========================================================
   Left-align constrained children (fix, v1.9.1)
   ---------------------------------------------------------
   A constrained-layout group centers any child narrower than
   the content width, which made the lede and card excerpts
   sit indented from the titles above them. Their max-widths
   are for line length, not for centering — so pin them left.
   ========================================================= */
.pbts-page-header .is-style-pbts-lede,
.pbts-page-header .wp-block-term-description,
.pbts-card-excerpt {
  margin-inline: 0;
}

/* =========================================================
   Brand Rule separator (added v1.9.2)
   ---------------------------------------------------------
   The same short Sun Gold rule the blog templates draw
   automatically, available as a Separator block style so it
   can be placed by hand in page content — where the header
   is assembled from the template's title plus the page's own
   blocks, and CSS can't know where the header ends.

   Insert a Separator, then Styles → Brand Rule.
   ========================================================= */
.wp-block-separator.is-style-pbts-rule:not(.is-style-wide):not(.is-style-dots) {
  /* The element spans the full content column and is centered
     by the constrained layout exactly like the paragraphs above
     it — so its left edge lines up with the text. Only the first
     3rem is painted, which produces the same short mark the blog
     templates draw. Fighting the layout's auto margins (an
     earlier attempt) aligned the rule to the container instead,
     which sits further left than the text. */
  width: 100%;
  height: 3px;
  border: 0;
  opacity: 1;
  background-color: transparent;
  background-image: linear-gradient(
    to right,
    var(--wp--preset--color--sun-gold) 0 3rem,
    transparent 3rem
  );
  margin-block: 1.5rem 2rem;
}

/* =========================================================
   Mobile navigation overlay — focus ring (fix, v1.9.2)
   ---------------------------------------------------------
   When the overlay opens, WordPress moves focus to the first
   item inside it (a modal focus trap — correct accessibility
   behavior, not a bug). The visible ring was neither the
   brand's nor keyboard-only, so it read as a stuck selection.

   Below: any ring inside the open overlay is Sun Gold, and
   only keyboard focus draws one. The plain :focus reset is
   scoped to the overlay alone so the site-wide accessibility
   floor is untouched everywhere else.
   ========================================================= */
.wp-block-navigation__responsive-container.is-menu-open a:focus,
.wp-block-navigation__responsive-container.is-menu-open button:focus,
.wp-block-navigation__responsive-container.is-menu-open
  .wp-block-navigation-item__content:focus {
  outline: none;
  box-shadow: none;
}
.wp-block-navigation__responsive-container.is-menu-open a:focus-visible,
.wp-block-navigation__responsive-container.is-menu-open button:focus-visible,
.wp-block-navigation__responsive-container.is-menu-open
  .wp-block-navigation-item__content:focus-visible {
  outline: 2px solid var(--wp--preset--color--sun-gold);
  outline-offset: 2px;
}

/* =========================================================
   Floated images unfloat on small screens (added v1.9.7)
   ---------------------------------------------------------
   A float reserves no space of its own — text simply flows
   into whatever gap is left beside it. At a phone width a
   300px portrait leaves a channel too narrow to set type in,
   so a paragraph breaks after one or two words and the rest
   waits for the float to clear, leaving a tall empty column.

   Core WordPress does not unfloat images at small widths and
   neither does Twenty Twenty-Five, so the rule lives here.
   Applies site-wide: pages today, blog posts later.

   Breakpoint is 781px to match where WordPress stacks
   Columns, so every side-by-side arrangement on the site
   collapses at the same width.

   The !important is required because the block's width
   control writes an inline style onto the <img> itself.
   ========================================================= */
@media (max-width: 781px) {
  .wp-block-image.alignleft,
  .wp-block-image.alignright {
    float: none;
    margin-inline: auto;
  }

  .wp-block-image.alignleft img,
  .wp-block-image.alignright img {
    width: min(100%, 18rem) !important;
    height: auto;
  }
}
