/* deckle theme stylesheet — Showcase.
 *
 * Photography carries the page: a full-bleed image hero with the headline
 * over it, cards as image tiles with the text on the picture, a photo that
 * runs to the viewport edge beside the text, and a dark band that closes
 * the page into a dark footer. Bone page, one dark tone, one amber accent.
 *
 * Fork guide
 *
 * - Palette, type and rhythm live in the custom properties on :root below.
 *   Rebrand by editing that one block; every colour and size in the rules
 *   comes from a token. Each colour token states its role and its WCAG
 *   contrast — re-check the ratios if you change a value.
 * - Breakpoints (mobile first, nothing scrolls sideways from 320px up):
 *     < 40em   one column; tiles 4:3; menu behind the Menu button
 *     >= 40em  image and card grids go to two columns; tiles 4:5
 *     >= 48em  horizontal nav with dropdowns; 3/4-column grids; text-media
 *              side by side; form fields side by side; footer three
 *              columns; two-col backend layout 3:1
 *   They are plain @media queries; search for "40em" / "48em" to move them.
 * - Dark surfaces (header, footer, hero, cta, card tiles, video, lightbox)
 *   never use amber for text, links, markers, icons, buttons or focus
 *   rings: amber on the dark tone is only 3.17:1. Each dark surface
 *   redefines the hooks the base layer reads — --color-link,
 *   --color-link-strong, --color-focus, --color-marker, --color-icon (and
 *   --color-rule / --color-panel for tables) — so rich text placed on it
 *   recolours itself. Muted text belongs on bone/surface only; on dark use
 *   --color-dark-muted. Buttons on dark are light (the "dark pairing").
 * - Fonts are self-hosted (assets/fonts, published at /fonts/ by
 *   baseof.html): Fraunces (display, variable, upright + italic) and Karla
 *   (body, variable). No third-party request, ever. To swap a family,
 *   replace the woff2 files and the @font-face rules, then --font-display /
 *   --font-body.
 * - The base layer (element defaults: headings, links, lists, images) is
 *   written with :where() at zero specificity, so any class rule wins over
 *   it — no link rule can ever override a button's text colour. Buttons
 *   always declare background AND colour, in every state.
 * - Element markup (the ce- classes) is a stable contract documented in
 *   the theme README. Style hooks only: templates carry no inline styles
 *   (the GFM table alignment hook is the one documented exception).
 * - Spacing between elements is never a margin. Every block element sits
 *   in a div.ce-frame that pads --frame above and below (see "frames"),
 *   so a background put on the frame fills the gap and two dark elements
 *   stacked meet edge to edge.
 */

/* ----------------------------------------------------------------- fonts */

/* Variable faces: one file covers the weights the theme uses (400, 500,
   600). Fraunces' optical-size axis (opsz 9-144) follows the font size
   automatically (font-optical-sizing: auto is the default). The CSS is
   served at /css/theme.css, so ../fonts/ is the published /fonts/. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/fraunces-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/fraunces-italic-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Karla";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/karla-variable.woff2") format("woff2");
}

/* ---------------------------------------------------------------- tokens */

:root {
  /* Palette. Ratios are WCAG 2.2 contrast (AA: 4.5:1 text, 3:1 large text
     and UI). One palette, no dark mode: the dark tone is part of the
     design, not a scheme. */
  --color-bg: #faf9f6;             /* bone: page background */
  --color-surface: #f0ede6;        /* panels: form, teasers, table head */
  --color-text: #1b1917;           /* body copy, headings: 16.65:1 on bone, 14.99:1 on surface */
  --color-muted: #5f5a53;          /* leads, captions, secondary copy: 6.49:1 on bone, 5.84:1 on surface. Never on dark */
  --color-border: #dcd7cd;         /* hairlines, input borders, table rules (decorative) */
  --color-accent: #8c5a12;         /* amber: links, list markers, icons, primary button, focus ring on light. 5.56:1 on bone, 5.01:1 on surface; 3.17:1 on dark, so never used there */
  --color-accent-strong: #6f4609;  /* amber hover: 7.80:1 on bone */
  --color-accent-contrast: #ffffff;/* text on amber: 5.86:1 (8.22:1 on amber strong) */
  --color-accent-tint: #f3ead9;    /* reserved; unused in v1 */
  --color-dark: #15130f;           /* the dark tone: header, footer, cta, hero without photo, card tiles, video; text on the light button (16.76:1) */
  --color-dark-text: #f6f3ee;      /* copy on dark: 16.76:1; also the light button's background */
  --color-dark-muted: #bdb6ab;     /* secondary copy on dark (cta lead, footer address, video note): 9.23:1 */
  --color-dark-strong: #ffffff;    /* headings, brand, hover and focus ring on dark: 18.55:1 */
  --overlay: 21 19 15;             /* --color-dark as an RGB triplet, for translucent gradients over photos and the lightbox scrim: rgb(var(--overlay) / .78). White on a photo is only placed over the 78%+ part (>= 8:1 on the lightest photo) */
  --on-dark: 255 255 255;          /* white as an RGB triplet, for translucent hairlines, rings and lightbox controls on dark: rgb(var(--on-dark) / .12) */

  /* Spacing scale (rem). Also drives the spacer sizes s/m/l/xl = 3/5/6/7. */
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2.5rem;
  --space-6: 4rem;
  --space-7: 6rem;
  --section-gap: var(--space-7);   /* vertical rhythm between the elements of a slot */
  --frame: calc(var(--section-gap) / 2); /* each element's share of it: the padding above and below its frame (see "frames") */

  /* Type. Display (Fraunces) for headings, brand, quotes, teaser titles,
     accordion summaries; body (Karla) for everything else. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body: "Karla", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display-weight: 600;           /* headings and brand */
  --display-tracking: -0.015em;    /* headings letter-spacing */
  --text-base: clamp(1rem, .96rem + .2vw, 1.0625rem);  /* body copy, line-height 1.6 */
  --text-sm: .9rem;                /* captions, copyright, video note, quote attribution */
  --text-h1: clamp(2.5rem, 1.4rem + 5vw, 5.2rem);      /* page title, hero headline */
  --text-h2: clamp(1.9rem, 1.3rem + 2.2vw, 3rem);      /* section headings: cta, text-media, form */
  --text-h3: clamp(1.45rem, 1.2rem + .9vw, 2rem);      /* card heading, text h3, quote */
  --text-h4: clamp(1.2rem, 1.1rem + .5vw, 1.45rem);    /* teaser title, accordion summary, video label */

  /* Layout */
  --radius: 6px;                   /* images, tiles, buttons, inputs, panels */
  --measure: 42rem;                /* max width of running text, quote, accordion, form, page header */
  --container: 80rem;              /* max width of the content shell (.container) */
  --gutter: clamp(1rem, 4vw, 2rem);/* side padding of the shell; >= 16px at every width */
  --bleed: calc((100vw - min(var(--container), 100vw)) / 2 + var(--gutter)); /* content edge to viewport edge: a full-bleed block uses margin-inline: calc(-1 * var(--bleed)) and, for a band, the same as padding */
}

/* ------------------------------------------------------------------ base */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* A column at least the viewport tall, so the footer sits at the bottom
   of a short page (404) instead of leaving bone below it. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* classic scrollbars make 100vw (and so --bleed) overshoot by the bar
     width; clip those few px so full-bleed blocks never scroll sideways */
  overflow-x: clip;
}

/* Zero-specificity defaults: every class rule below wins over these. */
:where(h1, h2, h3, h4, h5, h6) {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  line-height: 1.15;
  letter-spacing: var(--display-tracking);
  margin: 0 0 var(--space-3);
  overflow-wrap: break-word;
  text-wrap: balance;
}

:where(h1) { font-size: var(--text-h1); }
:where(h2) { font-size: var(--text-h2); }
:where(h3) { font-size: var(--text-h3); }
:where(h4) { font-size: var(--text-h4); }

:where(p, ul, ol, address) { margin: 0 0 var(--space-3); }

:where(address) { font-style: normal; }

:where(blockquote) {
  margin: 0 0 var(--space-3);
  padding-inline-start: var(--space-3);
  border-inline-start: 2px solid var(--color-rule, var(--color-border));
}

/* List markers, links and icons read their colour from hooks that dark
   surfaces redefine (see "dark surfaces" below). */
:where(li)::marker { color: var(--color-marker, var(--color-accent)); }

:where(a) {
  color: var(--color-link, var(--color-accent));
  text-underline-offset: .18em;
  text-decoration-thickness: from-font;
}

:where(a:hover) { color: var(--color-link-strong, var(--color-accent-strong)); }

:where(img, svg, video, iframe) { max-width: 100%; height: auto; }

:where(img) { display: block; }

:where(pre) { overflow-x: auto; }

/* Focus: 3px amber ring, 3px offset on light surfaces; dark surfaces set
   --color-focus to white. Never removed. */
:focus-visible {
  outline: 3px solid var(--color-focus, var(--color-accent));
  outline-offset: 3px;
}

.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* White on amber (5.86:1); when focused it sits over the dark header, so
   its ring is white. */
.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 100;
  padding: var(--space-2) var(--space-3);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  border-radius: var(--radius);
  font-weight: 600;
  text-decoration: none;
  --color-focus: var(--color-dark-strong);
}

.skip-link:focus {
  left: var(--space-2);
  top: var(--space-2);
  color: var(--color-accent-contrast);
}

/* Visually hidden, still in the accessibility tree. */
.sr-only,
.page--home .page__header {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------- dark surfaces */

/* Every dark surface recolours the hooks the base layer reads, so links,
   list markers, icons, tables and focus rings inside rich text placed on
   it stay light (amber is never used on dark). Card tiles are not listed:
   a tile holds no rich text, and its own focus ring is drawn outside it,
   on the bone page, so it stays amber. */
.site-header,
.site-footer,
.ce-frame--dark,
.ce-video,
.ce-lightbox__dialog {
  --color-link: var(--color-dark-text);
  --color-link-strong: var(--color-dark-strong);
  --color-focus: var(--color-dark-strong);
  --color-marker: var(--color-dark-muted);
  --color-icon: currentColor;
  --color-rule: rgb(var(--on-dark) / .2);
  --color-panel: rgb(var(--on-dark) / .08);
}

/* ---------------------------------------------------------------- header */

/* A dark bar the hero photo continues from. Markup: partials/header.html. */
.site-header {
  position: relative;
  background: var(--color-dark);
  color: var(--color-dark-text);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  padding-block: var(--space-3);
}

.site-header__brand {
  display: block;
  min-width: 0;
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 1.45rem;
  line-height: 1.2;
  letter-spacing: var(--display-tracking);
  overflow-wrap: break-word;
  color: var(--color-dark-strong);
  text-decoration: none;
}

.site-header__brand:hover { color: var(--color-dark-strong); }

.site-nav__menu,
.site-nav__sub {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* 55% white outline; 44px+ tall through its padding. */
.site-nav__toggle {
  flex: none;
  font: inherit;
  font-weight: 600;
  color: var(--color-dark-strong);
  background: transparent;
  border: 1px solid rgb(var(--on-dark) / .55);
  border-radius: var(--radius);
  padding: .55em .9em;
  cursor: pointer;
}

.site-nav__toggle:hover {
  color: var(--color-dark-strong);
  background: transparent;
  border-color: var(--color-dark-strong);
}

.site-nav__link,
.site-nav__sublink {
  display: block;
  color: inherit;
  font-weight: 500;
  text-decoration: none;
  padding: .5em .8em;
}

.site-nav__link:hover,
.site-nav__sublink:hover {
  color: var(--color-dark-strong);
  text-decoration: underline;
  text-underline-offset: .3em;
}

.site-nav__link[aria-current="page"],
.site-nav__sublink[aria-current="page"] { color: var(--color-dark-strong); }

/* Phone: the menu is hidden until the toggle sets aria-expanded="true"
   (assets/js/nav.js; Escape closes it), then drops below the bar, full
   width, in the same dark. Sub-pages render inline, indented, dark muted.
   Links are 44px+ tall through their padding. */
@media (max-width: 47.99em) {
  .site-nav__menu {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    z-index: 20;
    background: var(--color-dark);
    border-top: 1px solid rgb(var(--on-dark) / .15);
    padding: var(--space-2) var(--gutter) var(--space-3);
  }
  .site-nav__toggle[aria-expanded="true"] + .site-nav__menu { display: block; }
  .site-nav__link,
  .site-nav__sublink { padding: .6em 0; }
  .site-nav__link { font-size: 1.05rem; }
  .site-nav__sub { padding-left: var(--space-3); }
  .site-nav__sublink { color: var(--color-dark-muted); }
}

/* Desktop: a horizontal menu; one dropdown level per section, opened by
   hover or keyboard focus (:focus-within — every entry is a real link, so
   tabbing through the section link walks the dropdown, no JavaScript). */
@media (min-width: 48em) {
  .site-nav__toggle { display: none; }
  .site-nav__menu {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: var(--space-1);
  }
  .site-nav__link,
  .site-nav__sublink { font-size: .95rem; }
  .site-nav__item--parent { position: relative; }
  .site-nav__sub {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 14rem;
    z-index: 10;
    background: var(--color-dark);
    border: 1px solid rgb(var(--on-dark) / .18);
    border-radius: var(--radius);
    padding: var(--space-1);
  }
  .site-nav__item--parent:hover > .site-nav__sub,
  .site-nav__item--parent:focus-within > .site-nav__sub { display: block; }
}

/* Language switch (multilingual sites only; markup: partials/header.html):
   a small row of language labels after the main nav, the current one
   outlined. With a switch in the bar the nav gives up its space-between
   slot and sits at the right beside it, so on a phone the bar reads
   brand · menu toggle · languages, and the dropped-down menu is unaffected.
   Links are 44px+ tall on a phone through their padding. */
.site-header__inner:has(> .site-lang) > .site-nav { margin-left: auto; }

.site-lang__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-lang__link {
  display: block;
  color: var(--color-dark-muted);
  font-size: .85rem;
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: .5em .6em;
}

.site-lang__link:hover {
  color: var(--color-dark-strong);
  text-decoration: underline;
  text-underline-offset: .3em;
}

.site-lang__link[aria-current="page"] {
  color: var(--color-dark-strong);
  border-color: rgb(var(--on-dark) / .55);
}

@media (max-width: 47.99em) {
  .site-lang__link { padding: .95em .6em; }
}

/* ------------------------------------------------------- main, page header */

.site-main {
  flex: 1 0 auto;
  padding-block: 0 var(--space-7);
}

/* When the page ends in a full-bleed dark band (a dark frame: cta, hero),
   the band meets the footer (the footer's 12% white hairline separates
   them). */
.site-main:has(> .container > .page > .page__content:last-child > .ce-layout > .ce-layout__slot:last-child > .ce-frame--dark.ce-frame--bleed:last-child) {
  padding-bottom: 0;
}

/* Title at h1 size, lead 1.25rem muted, both capped at the measure; 4rem
   of air above, 2.5rem below. */
.page__header {
  padding-top: var(--space-6);
  max-width: var(--measure);
}

.page__title {
  font-size: var(--text-h1);
  line-height: 1.02;
  margin-bottom: var(--space-2);
}

.page__lead {
  font-size: 1.25rem;
  line-height: 1.5;
  color: var(--color-muted);
  margin: 0;
}

.page__header + .page__content { margin-top: var(--space-5); }

/* Home: the header is visually hidden (above, with .sr-only) because the
   hero is the lead. A hero that opens the page sits flush under the dark
   bar; anything else gets the usual air above it. */
.page--home .page__header + .page__content { margin-top: var(--space-6); }

.page--home .page__header + .page__content:is(
  :has(> .ce-layout--one-col > .ce-layout__slot--main:first-child > .ce-frame--hero:first-child),
  :has(> .ce-frame--hero:first-child)
) { margin-top: 0; }

/* The no-layout fallback (backendlayout/render.html emitting plain
   .Content, no slot wrappers) needs no rule of its own: every element
   brings its frame, and plain markdown paragraphs keep their own margins. */

/* Section list pages (list.html): the child-page teasers follow the body. */
.page__content ~ .ce-teasers { margin-top: var(--space-6); }

/* ---------------------------------------------------------------- footer */

/* Dark, three columns from 48em (2:1:1): brand and about, footer nav,
   copyright bottom right. Markup: partials/footer.html. */
.site-footer {
  background: var(--color-dark);
  color: var(--color-dark-text);
  border-top: 1px solid rgb(var(--on-dark) / .12);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-4);
  padding-block: var(--space-6) var(--space-5);
}

.site-footer__brand {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 1.3rem;
  line-height: 1.2;
  letter-spacing: var(--display-tracking);
  color: var(--color-dark-strong);
  margin-bottom: var(--space-2);
}

.site-footer__about > :not(.site-footer__brand) {
  color: var(--color-dark-muted);
  margin-bottom: var(--space-2);
  max-width: 30rem;
}

.site-footer__about > :last-child { margin-bottom: 0; }

.site-footer__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-1);
}

.site-footer__link {
  display: inline-block;
  padding-block: var(--space-1);
  color: inherit;
  font-weight: 500;
  text-decoration: none;
}

.site-footer__link:hover {
  color: var(--color-dark-strong);
  text-decoration: underline;
  text-underline-offset: .3em;
}

.site-footer__copy {
  color: var(--color-dark-muted);
  font-size: var(--text-sm);
  margin: 0;
}

@media (min-width: 48em) {
  .site-footer__inner {
    grid-template-columns: 2fr 1fr 1fr;
    gap: var(--space-6);
  }
  .site-footer__copy {
    grid-column: -2 / -1;
    text-align: right;
    align-self: end;
  }
}

/* -------------------------------------------------------------- controls */

/* Buttons (.ce-btn: the button element, and the submit of deckle-hosted's
   hosted-contact-form element — README "Hosted contact form"). Karla
   600, 44px+ tall through the padding. Each variant declares background
   AND colour in every state; on dark surfaces (hero, cta) the parent
   restyles the same two variants into the dark pairing — there is no third
   variant, so the sidecar's primary | secondary options stay as they are. */
.ce-btn {
  display: inline-block;
  font: inherit;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  border: 0;
  border-radius: var(--radius);
  padding: .8em 1.4em;
}

/* light surfaces: white on amber (5.86:1), hover amber strong (8.22:1) */
.ce-btn--primary {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

.ce-btn--primary:hover {
  background: var(--color-accent-strong);
  color: var(--color-accent-contrast);
}

/* light surfaces: text-colour ring; hover fills with the text colour */
.ce-btn--secondary {
  background: transparent;
  color: var(--color-text);
  box-shadow: inset 0 0 0 1.5px var(--color-text);
}

.ce-btn--secondary:hover {
  background: var(--color-text);
  color: var(--color-bg);
  box-shadow: inset 0 0 0 1.5px var(--color-text);
}

/* dark surfaces: dark text on the light button (16.76:1), hover white */
:is(.ce-hero, .ce-cta) .ce-btn--primary {
  background: var(--color-dark-text);
  color: var(--color-dark);
}

:is(.ce-hero, .ce-cta) .ce-btn--primary:hover {
  background: var(--color-dark-strong);
  color: var(--color-dark);
}

/* dark surfaces: white text, 75% white ring; hover full white ring */
:is(.ce-hero, .ce-cta) .ce-btn--secondary {
  background: transparent;
  color: var(--color-dark-strong);
  box-shadow: inset 0 0 0 1.5px rgb(var(--on-dark) / .75);
}

:is(.ce-hero, .ce-cta) .ce-btn--secondary:hover {
  background: transparent;
  color: var(--color-dark-strong);
  box-shadow: inset 0 0 0 1.5px var(--color-dark-strong);
}

/* Links in running text: amber, underlined (base layer). Navigation,
   footer, brand, card and teaser links inherit their colour and are not
   underlined at rest (their own blocks). Focus: base layer. */

/* ==================================================================== */
/* Frames                                                               */
/* ==================================================================== */

/* Every block element is wrapped in one div.ce-frame.ce-frame--<name>
   (the shortcode name), emitted by its template; the frame carries the
   id="c-<uid>" anchor (partials/ce/attrs.html).
   The frame does the spacing, and only the frame: --frame (half of
   --section-gap) of padding above and below, so two neighbours sit one
   section gap apart and nothing between elements is ever a margin. A
   background therefore belongs on the frame (ce-frame--dark): it fills
   the padding, and two dark elements stacked meet edge to edge with no
   bone between them. The element inside is content. A band measures its
   own padding against the frame (hero, cta below); a tile such as the
   video box or the form panel simply sits in it. The first and last
   frame of a slot drop the outer edge (rules under "backend layouts");
   the page header above and the footer below set those distances. */
.ce-frame {
  --frame-start: var(--frame);
  --frame-end: var(--frame);
  padding-block: var(--frame-start) var(--frame-end);
}

/* A dark frame lights its copy and recolours the rich-text hooks (see
   "dark surfaces" above). */
.ce-frame--dark {
  background: var(--color-dark);
  color: var(--color-dark-text);
}

/* A full-bleed frame runs to the viewport edge (README, "Full-bleed
   blocks"): the one place a margin is used, and it is horizontal. The
   element inside adds the same value back as padding-inline to keep its
   content on the shell edge. */
.ce-frame--bleed { margin-inline: calc(-1 * var(--bleed)); }

/* ==================================================================== */
/* Element library (ce- vocabulary), one block per element             */
/* ==================================================================== */

/* --- hero -------------------------------------------------------------- */

/* The page lead, in a dark full-bleed frame. With the optional image
   (ce-hero--image): a full-bleed photo behind a gradient, the headline at
   its foot. The FRAME is the photo's box (the img and the gradient are
   positioned against it), so the photo covers the frame padding too and
   sits flush under the dark bar when the hero opens the page. Without an
   image: the same type on the dark band, so the photo can be added later.
   The photo is decorative (alt=""); text sits only over the 78%+ part of
   the overlay (the bottom 40%). */
.ce-frame--hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

/* The frame's padding is part of the photo, so it comes off the height. */
.ce-hero--image {
  min-height: calc(clamp(30rem, 72vw, 46rem) - var(--frame-start) - var(--frame-end));
  display: flex;
  align-items: flex-end;
}

.ce-hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  z-index: -2;
}

.ce-hero--image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top,
    rgb(var(--overlay) / .95) 0%,
    rgb(var(--overlay) / .78) 40%,
    rgb(var(--overlay) / .2) 100%);
}

/* The content sits in a container-width box with the gutter, so it lines
   up with the page content. */
.ce-hero--image .ce-hero__inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-6) var(--gutter);
}

/* No image: the band's padding (4-6rem in all, the frame's share
   included; the bleed sideways) places the text on the content edge. */
.ce-hero:not(.ce-hero--image) {
  --band-pad: clamp(var(--space-6), 8vw, var(--space-7));
  padding: calc(var(--band-pad) - var(--frame-start)) var(--bleed) calc(var(--band-pad) - var(--frame-end));
}

.ce-hero:not(.ce-hero--image) .ce-hero__inner {
  max-width: var(--container);
  margin-inline: auto;
}

.ce-hero__heading {
  font-size: var(--text-h1);
  line-height: 1.02;
  max-width: 16ch;
  margin-bottom: var(--space-3);
  color: var(--color-dark-strong);
}

.ce-hero__body {
  font-size: 1.15rem;
  line-height: 1.5;
  max-width: 34rem;
}

.ce-hero__body > :last-child { margin-bottom: 0; }

/* A paragraph of button chips: .5rem / 1rem gaps when they wrap. */
.ce-hero__body p:has(.ce-btn) {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
}

.ce-hero__body > * + p:has(.ce-btn) { margin-top: var(--space-4); }

/* --- text -------------------------------------------------------------- */

/* The rte workhorse, capped at the measure. */
.ce-text {
  max-width: var(--measure);
  overflow-wrap: break-word;
}

.ce-text > :last-child { margin-bottom: 0; }

.ce-text h2 { font-size: var(--text-h2); margin-top: var(--space-5); }
.ce-text h3 { font-size: var(--text-h3); margin-top: var(--space-4); }
.ce-text h4 { font-size: var(--text-h4); margin-top: var(--space-4); }

.ce-text > :is(h2, h3, h4):first-child { margin-top: 0; }

.ce-text :is(ul, ol) { padding-left: 1.2em; }

/* Inline button chips: wrapped lines must not touch. */
.ce-text .ce-btn { margin-block: .15em; }

/* GFM pipe tables in any rich-text body or plain content, wrapped by the
   table render hook (layouts/_default/_markup/render-table.html) in a
   focusable (tabindex="0") box that scrolls sideways instead of
   overflowing the page. Per-cell alignment arrives as an inline style from
   the hook and always wins; nothing here sets text-align on a cell. */
.ce-table {
  overflow-x: auto;
  margin: var(--space-4) 0;
  border: 1px solid var(--color-rule, var(--color-border));
  border-radius: var(--radius);
}

.ce-table__table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-variant-numeric: tabular-nums;
}

.ce-table__table :is(th, td) {
  padding: .65em .9em;
  border-bottom: 1px solid var(--color-rule, var(--color-border));
  vertical-align: top;
}

.ce-table__table thead th {
  background: var(--color-panel, var(--color-surface));
  font-weight: 600;
  font-size: var(--text-sm);
}

.ce-table__table tbody tr:last-child td { border-bottom: 0; }

/* --- button (inline) --------------------------------------------------- */

/* a.ce-btn.ce-btn--primary|--secondary: see "controls" above; the dark
   pairing applies automatically inside hero and cta bodies. An icon chip
   inside a button takes the button's text colour. */
.ce-btn .ce-icon { color: inherit; }

/* --- icon (inline) ----------------------------------------------------- */

/* Built-in stroke glyph set (layouts/partials/icon.html), sized to the
   text, tinted through currentColor: amber on light (AA on bone and
   surface), the surrounding text colour on dark. An unknown name renders
   an empty span. Forks restyle via ce-icon--<name> / [data-icon]. */
.ce-icon {
  display: inline-block;
  vertical-align: -.125em;
  color: var(--color-icon, var(--color-accent));
}

.ce-icon svg {
  display: block;
  width: 1em;
  height: 1em;
}

/* --- image, with its hidden img rows ----------------------------------- */

/* .ce-images.ce-images--cols-N[data-lightbox] > figure.ce-figure. One
   column, two from 40em, cols-3/4 reach 3/4 from 48em: cols is a maximum.
   text-media's media pane is the same grid (see text-media). */
.ce-images {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 40em) {
  .ce-images--cols-2,
  .ce-images--cols-3,
  .ce-images--cols-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 48em) {
  .ce-images--cols-3 { grid-template-columns: repeat(3, 1fr); }
  .ce-images--cols-4 { grid-template-columns: repeat(4, 1fr); }
}

/* img (hidden row) / standalone figure. A linked image wraps in its own
   <a> (always wins); with the lightbox on, a linkless image wraps in
   a.ce-lightbox (dialog styles at the end of this file). */
.ce-figure { margin: 0; min-width: 0; }

.ce-figure > a {
  display: block;
  border-radius: var(--radius);
}

.ce-figure__img {
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius);
}

.ce-images .ce-figure__img { aspect-ratio: 4 / 3; }

.ce-figure__caption {
  font-size: var(--text-sm);
  color: var(--color-muted);
  padding-top: var(--space-2);
}

.ce-lightbox { cursor: zoom-in; }

/* --- text-media -------------------------------------------------------- */

/* Body text beside the media pane (.ce-text-media__media, a ce-images grid
   that always comes first in the markup).
   One image (cols-1): below 48em the photo bleeds edge to edge above the
   text, caption inside the gutter; from 48em a 2:3 grid (text:photo) with
   the photo bleeding to the outer edge of its side, radius only on the
   inner corners, at least 30rem tall and filling the row.
   Several images (cols 2-4): a small grid inside the container, no bleed,
   4:3 photos with full radius; 3:2 photos:text for side left. */
.ce-text-media {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

.ce-text-media__media,
.ce-text-media__body { min-width: 0; overflow-wrap: break-word; }

.ce-text-media__body > :last-child { margin-bottom: 0; }

.ce-text-media__body h3 { font-size: var(--text-h2); }

.ce-text-media__body :is(ul, ol) { padding-left: 1.2em; }

/* One image (any media pane that is not cols-2/3/4): the photo bleeds. The
   :not() keeps these rules out of the several-images grid entirely. */
.ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) {
  margin-inline: calc(-1 * var(--bleed));
}

.ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure {
  display: grid;
  grid-template-rows: 1fr auto;
  height: 100%;
}

.ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__img {
  height: 100%;
  border-radius: 0;
}

.ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__caption {
  padding-inline: var(--gutter);
}

/* Several images: a contained grid of 4:3 photos with full radius (the
   image-grid rules above), tighter gap. */
.ce-text-media__media:is(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) { gap: var(--space-2); }

/* no images at all: the body alone, at the measure */
.ce-text-media:not(:has(> .ce-text-media__media)) .ce-text-media__body { max-width: var(--measure); }

@media (min-width: 48em) {
  .ce-text-media {
    grid-template-columns: 2fr 3fr;
    gap: var(--space-6);
  }
  .ce-text-media--left { grid-template-columns: 3fr 2fr; }
  .ce-text-media:not(:has(> .ce-text-media__media)) { grid-template-columns: 1fr; }
  .ce-text-media--right .ce-text-media__media { order: 2; }

  /* one image: bleed to the outer edge only, at least 30rem tall, filling
     the row; radius on the inner corners only */
  .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) {
    margin-inline: 0;
    align-self: stretch;
  }
  .ce-text-media--right .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) { margin-inline-end: calc(-1 * var(--bleed)); }
  .ce-text-media--left .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) { margin-inline-start: calc(-1 * var(--bleed)); }
  .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__img { min-height: 30rem; }
  .ce-text-media--right .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__img { border-radius: var(--radius) 0 0 var(--radius); }
  .ce-text-media--left .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__img { border-radius: 0 var(--radius) var(--radius) 0; }
  .ce-text-media--right .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__caption { padding-inline: 0 var(--gutter); }
  .ce-text-media--left .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__caption { padding-inline: var(--gutter) 0; }
}

/* --- cards, with its hidden card rows ---------------------------------- */

/* .ce-cards.ce-cards--cols-N > a.ce-card | div.ce-card. A card is a dark
   tile: the photo (decorative, alt="") covers it under a gradient, the
   heading (white) and text (dark text) are pinned to the bottom, over the
   78%+ part of the gradient. A linked card zooms its photo 4% on hover.
   Without a photo it is the dark tile, text only. Tiles 4:3 below 40em,
   4:5 above. One column, two from 40em, cols-3/4 from 48em. */
.ce-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 40em) {
  .ce-cards--cols-2,
  .ce-cards--cols-3,
  .ce-cards--cols-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 48em) {
  .ce-cards--cols-3 { grid-template-columns: repeat(3, 1fr); }
  .ce-cards--cols-4 { grid-template-columns: repeat(4, 1fr); }
}

.ce-card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-width: 0;
  aspect-ratio: 4 / 3;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-4);
  border-radius: var(--radius);
  background: var(--color-dark);
  color: var(--color-dark-text);
}

a.ce-card {
  color: var(--color-dark-text);
  text-decoration: none;
}

a.ce-card:hover { color: var(--color-dark-text); }

.ce-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  z-index: -2;
  transition: transform .5s ease;
}

.ce-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top,
    rgb(var(--overlay) / .92) 0%,
    rgb(var(--overlay) / .55) 45%,
    rgb(var(--overlay) / 0) 100%);
}

a.ce-card:is(:hover, :focus-visible) .ce-card__img { transform: scale(1.04); }

.ce-card__heading {
  font-size: var(--text-h3);
  margin: 0 0 var(--space-1);
  color: var(--color-dark-strong);
}

.ce-card__text {
  margin: 0;
  font-size: .95rem;
  max-width: 26rem;
  color: var(--color-dark-text);
}

/* no photo: the dark tile, at least 12rem tall */
.ce-card:not(:has(.ce-card__img)) {
  aspect-ratio: auto;
  min-height: 12rem;
}

@media (min-width: 40em) {
  .ce-card { aspect-ratio: 4 / 5; }
}

/* --- quote ------------------------------------------------------------- */

/* figure > blockquote __body + figcaption __attribution. Centred serif
   italic with a generated amber opening mark (not read aloud). */
.ce-quote {
  margin: 0 auto;
  max-width: var(--measure);
  text-align: center;
}

.ce-quote__body {
  margin: 0;
  padding: 0;
  border: 0;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--text-h3);
  line-height: 1.3;
}

.ce-quote__body::before {
  content: "\201C";
  content: "\201C" / "";
  display: block;
  font-style: normal;
  font-size: 4rem;
  line-height: .6;
  color: var(--color-accent);
  margin-bottom: .25em;
}

.ce-quote__body > :last-child { margin-bottom: 0; }

.ce-quote__attribution {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* --- video-embed (click-to-load facade) -------------------------------- */

/* A 16:9 dark box; the consent button fills it (nothing loads until it is
   pressed, assets/js/consent.js), then the iframe does. The button sits in
   the flow of a one-cell grid, so on a narrow phone, where the play button,
   label and note do not fit 16:9, the box grows instead of clipping them
   (no overflow: hidden; the corners are rounded on the children). */
.ce-video {
  position: relative;
  display: grid;
  aspect-ratio: 16 / 9;
  background: var(--color-dark);
  border-radius: var(--radius);
  color: var(--color-dark-text);
}

.ce-video__consent {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  background: linear-gradient(to top, rgb(var(--overlay) / .95), rgb(var(--overlay) / .55));
  border: 0;
  border-radius: var(--radius);
  color: inherit;
  font: inherit;
  cursor: pointer;
  padding: var(--space-4) var(--space-3);
  text-align: center;
}

/* The button covers the whole box and a ring outside it would be white on
   bone, so the white ring is drawn inside the button. */
.ce-video__consent:focus-visible { outline-offset: -6px; }

.ce-video__play {
  width: 4.5rem;
  height: 4.5rem;
  flex: none;
  border-radius: 50%;
  background: var(--color-dark-text);
  position: relative;
  margin-bottom: var(--space-2);
  transition: transform .15s ease;
}

.ce-video__consent:is(:hover, :focus-visible) .ce-video__play {
  transform: scale(1.06);
  background: var(--color-dark-strong);
}

.ce-video__play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-38%, -50%);
  border-style: solid;
  border-width: .8rem 0 .8rem 1.3rem;
  border-color: transparent transparent transparent var(--color-dark);
}

.ce-video__label {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: var(--text-h4);
  line-height: 1.25;
  color: var(--color-dark-strong);
}

.ce-video__note {
  font-size: var(--text-sm);
  color: var(--color-dark-muted);
}

.ce-video__iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: var(--radius);
}

/* --- accordion and accordion-item -------------------------------------- */

/* Native details/summary. Hairline above the list and under every item;
   a generated amber + (- when open) replaces the native marker. */
.ce-accordion {
  max-width: var(--measure);
  border-top: 1px solid var(--color-border);
}

.ce-accordion__item { border-bottom: 1px solid var(--color-border); }

.ce-accordion__summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: var(--text-h4);
  line-height: 1.25;
  letter-spacing: var(--display-tracking);
  cursor: pointer;
}

.ce-accordion__summary::-webkit-details-marker { display: none; }

.ce-accordion__summary::after {
  content: "+";
  content: "+" / "";
  flex: none;
  width: 1.5rem;
  text-align: center;
  color: var(--color-accent);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 1.6rem;
  line-height: 1;
}

.ce-accordion__item[open] > .ce-accordion__summary::after {
  content: "\2212";
  content: "\2212" / "";
}

.ce-accordion__summary:hover { color: var(--color-accent); }

.ce-accordion__body {
  padding: 0 2.5rem var(--space-4) 0;
  max-width: 60ch;
}

.ce-accordion__body > :last-child { margin-bottom: 0; }

.ce-accordion__body :is(ul, ol) { padding-left: 1.2em; }

/* --- spacer ------------------------------------------------------------ */

/* Added on top of the section gap. Renders nothing visible. */
.ce-spacer--s  { height: var(--space-3); }
.ce-spacer--m  { height: var(--space-5); }
.ce-spacer--l  { height: var(--space-6); }
.ce-spacer--xl { height: var(--space-7); }

/* --- page-teasers, and section lists ----------------------------------- */

/* section.ce-teasers > ul __list > li __item (shared with list.html and the
   news / categories bundles). Surface panels in a responsive grid; the
   title link carries a generated amber arrow. */
.ce-teasers__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
}

.ce-teasers__item {
  min-width: 0;
  background: var(--color-surface);
  border-radius: var(--radius);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.ce-teasers__title {
  font-size: var(--text-h4);
  line-height: 1.25;
  margin: 0;
}

.ce-teasers__link {
  color: inherit;
  text-decoration: none;
}

.ce-teasers__link::after {
  content: " \2192";
  content: " \2192" / "";
  color: var(--color-accent);
}

.ce-teasers__link:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

.ce-teasers__summary {
  color: var(--color-muted);
  margin: 0;
  font-size: .95rem;
}

/* --- cta --------------------------------------------------------------- */

/* The full-bleed dark band that closes a page (a dark, bleeding frame):
   centred, inner at the measure, heading (h3) at h2 size in white, body
   dark muted, buttons in the dark pairing. The band's 4-6rem of padding
   includes the frame's share. */
.ce-cta {
  --band-pad: clamp(var(--space-6), 9vw, var(--space-7));
  padding: calc(var(--band-pad) - var(--frame-start)) var(--bleed) calc(var(--band-pad) - var(--frame-end));
  text-align: center;
}

.ce-cta__inner {
  max-width: var(--measure);
  margin-inline: auto;
}

.ce-cta__heading {
  font-size: var(--text-h2);
  color: var(--color-dark-strong);
  margin-bottom: var(--space-3);
}

.ce-cta__body {
  color: var(--color-dark-muted);
  font-size: 1.1rem;
}

.ce-cta__body > :last-child { margin-bottom: 0; }

.ce-cta__body :is(ul, ol) { text-align: left; }

.ce-cta__body p:has(.ce-btn) {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
}

.ce-cta__body > * + p:has(.ce-btn) { margin-top: var(--space-4); }

/* --- ce-form (deckle-hosted's hosted-contact-form) -------------------- */

/* deckle ships no contact form. These ce-form* classes are the contract of
   deckle-hosted's hosted-contact-form element (README "Hosted contact
   form") and must survive a redesign. A surface panel. Inputs are 16px so
   phones do not zoom on focus; focus is a 3px amber ring with the border
   turning amber. */
.ce-form {
  max-width: var(--measure);
  background: var(--color-surface);
  border-radius: var(--radius);
  padding: var(--space-4);
}

.ce-form__heading {
  font-size: var(--text-h2);
  margin-bottom: var(--space-4);
}

.ce-form__form {
  display: grid;
  gap: var(--space-3);
}

.ce-form__field { margin: 0; min-width: 0; }

.ce-form__label {
  display: block;
  font-weight: 600;
  font-size: .95rem;
  margin-bottom: var(--space-1);
}

.ce-form__input,
.ce-form__textarea {
  display: block;
  width: 100%;
  font: inherit;
  font-size: 1rem;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: .7em .9em;
}

.ce-form__input:focus-visible,
.ce-form__textarea:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 0;
  border-color: var(--color-accent);
}

.ce-form__textarea {
  resize: vertical;
  min-height: 8rem;
}

.ce-form__submit {
  justify-self: start;
  margin-top: var(--space-1);
}

@media (min-width: 48em) {
  .ce-form { padding: var(--space-5); }
  .ce-form__form { grid-template-columns: 1fr 1fr; }
  .ce-form__field:has(.ce-form__textarea),
  .ce-form__submit { grid-column: 1 / -1; }
}

/* --- html (developer raw HTML) ----------------------------------------- */

/* Emitted verbatim; only capped at the measure and scrolls if wider. */
.ce-html {
  overflow-x: auto;
  max-width: var(--measure);
}

/* ------------------------------------------------------- backend layouts */

/* The slot grids emitted by layouts/partials/backendlayouts/*.html. A
   layout partial and its rules here are edited together, like an element
   template and its rules. This block comes after the frames and elements
   on purpose: the slot-edge rules below must win over the frame's own
   padding. */

/* A slot's first and last frame drop the outer edge: the page header
   above and the footer (or the footer band's hairline) below set those
   distances. */
.ce-layout__slot > .ce-frame:first-child { --frame-start: 0px; }

.ce-layout__slot > .ce-frame:last-child { --frame-end: 0px; }

.ce-layout__cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
  min-width: 0; /* long words must shrink, not overflow */
}

.ce-layout__slot--main,
.ce-layout__slot--sidebar { min-width: 0; }

/* The footer band: a section gap of padding, then a hairline with 2.5rem
   of air under it, drawn by a generated block so that no margin is
   involved. */
.ce-layout__slot--footer { padding-top: var(--section-gap); }

.ce-layout__slot--footer::before {
  content: "";
  display: block;
  box-sizing: content-box; /* the hairline on top of the 2.5rem, not inside it */
  height: var(--space-5);
  border-top: 1px solid var(--color-border);
}

/* The 3fr/1fr split is the colspan 3 + colspan 1 that two-col.yaml
   declares to the editor — keep them equal or the page module's grid will
   lie about the page. */
@media (min-width: 48em) {
  .ce-layout--two-col .ce-layout__cols { grid-template-columns: 3fr 1fr; }
}

/* Inside the columns a viewport bleed would cross the neighbouring
   column: dark frames (hero, cta) become contained, rounded blocks with
   2.5rem side padding, and two dark frames in a row merge into one block;
   a text-media photo stays inside its column. */
.ce-layout__cols .ce-frame--bleed { margin-inline: 0; }

.ce-layout__cols .ce-text-media .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) { margin-inline: 0; }

.ce-layout__cols .ce-frame--dark { border-radius: var(--radius); }

.ce-layout__cols .ce-frame--dark:has(+ .ce-frame--dark) { border-end-start-radius: 0; border-end-end-radius: 0; }

.ce-layout__cols .ce-frame--dark + .ce-frame--dark { border-start-start-radius: 0; border-start-end-radius: 0; }

.ce-layout__cols :is(.ce-hero:not(.ce-hero--image), .ce-cta) { padding-inline: var(--space-5); }

.ce-layout__cols .ce-hero--image { min-height: calc(30rem - var(--frame-start) - var(--frame-end)); }

.ce-layout__cols .ce-hero--image .ce-hero__inner { padding-inline: var(--space-5); }

.ce-layout__cols .ce-text-media .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__img {
  min-height: 0;
  border-radius: var(--radius);
}

.ce-layout__cols .ce-text-media .ce-text-media__media:not(.ce-images--cols-2, .ce-images--cols-3, .ce-images--cols-4) .ce-figure__caption { padding-inline: 0; }

/* The sidebar is one narrow column at every width: grids stay single
   column and lead headings step down so words do not break. */
.ce-layout__slot--sidebar :is(.ce-cards, .ce-images) { grid-template-columns: 1fr; }

.ce-layout__slot--sidebar :is(.ce-hero__heading, .ce-cta__heading) { font-size: var(--text-h3); }

/* -------------------------------------------------------------- lightbox */

/* One shared <dialog>, built by assets/js/lightbox.js (close, prev, next,
   img) over a dark scrim. It fills the viewport as a flex box, so any empty
   area is the dialog itself (a click there closes it). Prev/next carry the
   hidden attribute when the grid has one image. Controls are round 12%
   white buttons with white glyphs and a white focus ring. */
.ce-lightbox__dialog {
  padding: 0;
  border: 0;
  width: 100vw;
  height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
  background: transparent;
  color: var(--color-dark-strong);
}

.ce-lightbox__dialog[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}

.ce-lightbox__dialog::backdrop { background: rgb(var(--overlay) / .92); }

.ce-lightbox__img {
  display: block;
  max-width: min(92vw, 90rem);
  max-height: 86vh;
  width: auto;
  height: auto;
  border-radius: var(--radius);
}

.ce-lightbox__close,
.ce-lightbox__prev,
.ce-lightbox__next {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  background: rgb(var(--on-dark) / .12);
  color: var(--color-dark-strong);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  font-size: 1.5rem;
  line-height: 1;
}

.ce-lightbox__close:hover,
.ce-lightbox__prev:hover,
.ce-lightbox__next:hover {
  background: rgb(var(--on-dark) / .24);
  color: var(--color-dark-strong);
}

.ce-lightbox__close { top: var(--space-3); right: var(--space-3); }

.ce-lightbox__prev,
.ce-lightbox__next {
  top: 50%;
  transform: translateY(-50%);
}

.ce-lightbox__prev { left: var(--space-3); }

.ce-lightbox__next { right: var(--space-3); }

/* the display: flex above would otherwise override [hidden] */
.ce-lightbox__prev[hidden],
.ce-lightbox__next[hidden] { display: none; }

.ce-lightbox__close:focus-visible,
.ce-lightbox__prev:focus-visible,
.ce-lightbox__next:focus-visible {
  outline: 3px solid var(--color-dark-strong);
  outline-offset: 3px;
}

/* ------------------------------------------------------- feature bundles */

/* The news and categories bundles reuse the teaser markup above and
   inherit the tokens; these few rules only lay out their extra parts. */
.ce-news-list__image,
.news-item__image {
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius);
}

.news-item__media { margin: 0 0 var(--space-5); }

:is(.ce-news-list__date, .news-item__date, .news-item__author) {
  display: block;
  color: var(--color-muted);
  font-size: var(--text-sm);
}

:is(.ce-news-list__categories, .news-item__categories) {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
}

.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-5);
}

.pager__pages {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.pager__number,
.pager__link {
  display: inline-block;
  min-width: 2.75rem;
  padding: .6em .8em;
  text-align: center;
}

.pager__number[aria-current="page"] {
  color: var(--color-text);
  font-weight: 600;
  text-decoration: none;
}

.pager__link[aria-disabled="true"] { color: var(--color-muted); }

/* --------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  .ce-card__img,
  .ce-video__play { transition: none; }
  a.ce-card:is(:hover, :focus-visible) .ce-card__img,
  .ce-video__consent:is(:hover, :focus-visible) .ce-video__play { transform: none; }
}
