/*
  Build your own — the base the AI builder starts from, copied from the kit's starter. One column, the
  platform's default blocks styled just enough to read, and every value that has
  a house name read from it: the colors, the two fonts, the type steps and their
  line heights, the gaps, the page width and gutter, the section padding, the
  corner radius, the line weight and the motion timings (docs/template-folder.md,
  "The house design system"). The platform writes those names on every site, from
  the settings in template.json and the house numbers; everything else is yours to
  redesign.

  The house widths are 640, 768 and 1024 px. The type, the gutter and the section
  padding step up at 768 and 1024 on their own; the rules below only move the
  layout.

  Prefix your own class names (here `s-`) so they never collide with the
  renderer's `t-*` (the block wrapper, the platform's default blocks) or
  `wi-*` (the map, the lightbox, the consent banner).
*/

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

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

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

body {
  margin: 0;
  background: var(--t-main);
  color: var(--t-main-ink);
  font-family: var(--t-body);
  font-size: var(--t-text-body);
  line-height: var(--t-leading-body);
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--t-accent); }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--t-accent);
  outline-offset: 2px;
}
/* On the accent band an accent ring would vanish into it, so the ring reads the band's ink
   token instead. Not currentColor: since the buttons-are-exempt fix above, a focused element's
   own color is tuned for ITS fill (a button's label), not the band behind it — a ring drawn in
   that color can fall under 3:1 against the band itself (measured: the accent outline button's
   own label reads 1.00:1 on the accent band). The ink token is built to read on the band. */
.t-tone-accent :focus-visible { outline-color: var(--t-accent-ink); }
/* Same reasoning for the dark band: its own ink (--t-support-ink) is built to read on it. */
.t-tone-dark :focus-visible { outline-color: var(--t-support-ink); }

h1, h2, h3 {
  font-family: var(--t-display);
  font-weight: 400;
  margin: 0 0 0.5em;
  text-wrap: balance;
  overflow-wrap: break-word;
}
h1 { font-size: var(--t-text-h1); line-height: var(--t-leading-h1); }
h2 { font-size: var(--t-text-h2); line-height: var(--t-leading-h2); }
h3 { font-size: var(--t-text-h3); line-height: var(--t-leading-h3); }
p { margin: 0 0 1em; }

/* width: contain — the page box every plain section already sits in; `.s-content-contain`
   is the same box under the Content wrapper's own name, aliased here rather than
   repeated below. */
.s-wrap, .s-content-contain { width: min(100% - 2 * var(--t-page-gutter), var(--t-page-width)); margin-inline: auto; }

/* Read by a screen reader, never drawn: the listing's title inside each card's "Quick view" link. */
.s-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* The label step: uppercase and spaced, never under 12px. */
.s-eyebrow, .t-eyebrow, .s-status, .t-status, .s-specs dt {
  font-size: var(--t-text-label); line-height: var(--t-leading-label);
  letter-spacing: 0.08em; text-transform: uppercase;
}

/* ---- the block wrapper: tone bands and spacing ------------------------- */

.t-block { padding-block: var(--t-section-m); }
.t-space-compact { padding-block: var(--t-section-s); }
.t-space-spacious { padding-block: var(--t-section-l); }
/* No padding at all — a section that should sit flush against the one above or below it. */
.t-space-none { padding-block: 0; }
.t-tone-surface { background: color-mix(in srgb, var(--t-support) 5%, var(--t-main)); }
.t-tone-accent { background: var(--t-accent); color: var(--t-accent-ink); }
/* Off buttons: a plain link inherits the band's own ink, but a button already carries its own
   readable color (paper reads --t-main-ink, brand reads --t-button-ink or the agent's own
   --s-btn-ink) — "a { color: inherit }" at (0,1,1) beats a button's own (0,1,0) rule and
   overwrites it with whatever the band's ink happens to be, which is not built to read on the
   button's own fill. Same fix below for the dark band. */
.t-tone-accent a:not(.s-btn):not(.t-btn) { color: inherit; }
/* The fourth ground: `--t-support` filled, `--t-support-ink` on it — the same pair `--t-support-ink`
   is built to read on, so every template already carries a passing pair for it. */
.t-tone-dark { background: var(--t-support); color: var(--t-support-ink); }
.t-tone-dark a:not(.s-btn):not(.t-btn) { color: inherit; }

/* The platform's default blocks are one column of semantic HTML; give them the page width.
   ".t-block > :not(.s-wrap)" is two classes, (0,2,0) — higher than any single chrome class,
   by design (see specimen.test.mjs), but lower than .s-content-breakout below, which wins
   outright by specificity rather than by being named here or declared later. */
.t-block > :not(.s-wrap) { width: min(100% - 2 * var(--t-page-gutter), var(--t-page-width)); margin-inline: auto; }

/* ---- layout wrappers: Content (layout, width, sticky) ------------------
   Shared Content-wrapper classes a block's own markup applies for itself — never a
   second source of truth: a block still decides its own markup (whether a photo
   exists, which side it sits on) the way it always has, and these are just the
   shared rules two or more blocks used to each write for themselves. */

/* width: breakout — no page box, full width of whatever holds it. The doubled class gives
   ".t-block > .s-content-breakout.s-content-breakout" three classes, (0,3,0) — strictly
   higher than the wrap-width rule above's (0,2,0), so this wins by specificity alone,
   whichever of the two rules is declared first. Never `100vw` (it overruns a scrollbar's
   own width and forces a sideways scroll); a section that wants to fill its whole band
   reaches past `.t-block`'s padding on its own. Only works as a direct child of `.t-block`
   (the selector's own `>`) — put it inside `.s-wrap` instead and it stays at column width. */
.t-block > .s-content-breakout.s-content-breakout { width: 100%; }

/* layout: two_col — an equal pair of columns from 1024px, stacked below it: the hero's
   and the Text + image block's own grid, one rule for both instead of two apiece. */
.s-content-two_col { display: grid; gap: var(--t-gap-6); align-items: center; }
.s-content-two_col > * { min-width: 0; }
/* A block that can put either child first (the Text + image block's `image_side`) marks
   the one that should trade places — never `:first-child`, which a caption or another
   element ahead of it would throw off. Scoped to the same rule that turns on the columns:
   below 1024px this is one column and `order` still reorders an auto-placed grid item, so
   applying it any wider than that would send the marked child after its sibling even while
   stacked — a phone must still see the photo first, as the markup writes it. */
@media (min-width: 1024px) {
  .s-content-two_col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .s-content-two_col > .s-content-end { order: 1; }
}

/* sticky — the marked child alone stays put as the page scrolls; a block may set
   `--s-sticky-offset` for its own gap from the top, or leave the house one. No starter
   block reads it yet. */
.s-content-sticky { position: sticky; top: var(--s-sticky-offset, var(--t-gap-5)); }

/* ---- header and footer -------------------------------------------------- */

/* Non-sticky here on purpose — the starter is a blank skeleton, and a template opts into a fixed
   header itself. The recipe (documented in CLAUDE.md, "Motion"): `position: sticky; top: 0;` plus
   a `z-index` above anything else that can sit at the top of the stack — a pin or a scrub's own
   sticky inner view both need to lose to a sticky header, or the header paints under them. */
.s-header {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--t-gap-3) var(--t-gap-5);
  width: min(100% - 2 * var(--t-page-gutter), var(--t-page-width)); margin-inline: auto;
  height: 60px;
  border-bottom: var(--t-stroke-px) solid color-mix(in srgb, var(--t-support) 15%, transparent);
}
@media (min-width: 1024px) { .s-header { height: 76px; } }
.s-brand {
  display: inline-flex; align-items: center; min-height: 44px;
  font-family: var(--t-display); font-size: var(--t-text-h3); line-height: var(--t-leading-h3);
  color: inherit; text-decoration: none;
}
/* The logo: a fixed, capped height it letterboxes into, and a 3:1 box for an SVG with no size of its own.
   With height: auto instead, such an SVG draws 0 px wide. */
.s-logo { width: auto; height: 3rem; max-height: 3rem; object-fit: contain; aspect-ratio: auto 3 / 1; }
/* The desktop nav and the mobile menu are the same site.nav, drawn twice, and CSS alone decides
   which one is on screen — under 1024px the nav is hidden and the menu toggle takes its place; at
   1024px and up the menu (data-motion="menu") is hidden and the nav returns. This is the
   MENU_DESKTOP_WIDTH the script's own auto-close reads (motion.js), so the two never disagree. */
.s-nav { display: none; flex-wrap: wrap; gap: var(--t-gap-1) var(--t-gap-5); }
.s-nav a { color: inherit; text-decoration: none; }
.s-nav a[aria-current="page"], .s-nav a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
@media (min-width: 1024px) {
  .s-nav { display: flex; }
  .s-menu { display: none; }
}

/* ---- the mobile menu (data-motion="menu" — partials/nav.html) ----------- */

/* The <details> itself carries no box of its own; its two children (the toggle and the panel)
   place themselves. motion.css's html:has() rule stops the page behind the panel from scrolling
   while it is open — nothing here needs to do that again. */
.s-menu-toggle {
  list-style: none;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  width: 44px; height: 44px;
  position: relative; z-index: 2; /* above .s-menu-panel, so the close "×" stays reachable */
  cursor: pointer;
}
.s-menu-toggle::-webkit-details-marker { display: none; }
/* Timed with the house motion names, which go to 0 ms under reduced motion and when the Motion setting is None. */
.s-menu-toggle span {
  display: block; width: 22px; height: 2px; background: currentColor;
  transition: transform var(--t-motion-s) var(--t-motion-ease), opacity var(--t-motion-s) var(--t-motion-ease);
}
/* The three bars become an "×" in place — no dimension of the toggle itself changes, only the
   bars inside it, so its box is identical open and closed. */
.s-menu[open] > .s-menu-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.s-menu[open] > .s-menu-toggle span:nth-child(2) { opacity: 0; }
.s-menu[open] > .s-menu-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.s-menu-panel {
  position: fixed; inset: 0; z-index: 1;
  padding-top: 60px; /* the header's own height below 1024px, so the toggle does not shift under the panel */
  background: var(--t-main);
  display: flex; flex-direction: column;
}
.s-menu-panel nav { display: flex; flex-direction: column; }
.s-menu-panel nav a {
  display: flex; align-items: center;
  height: 56px; padding-inline: var(--t-gap-5);
  font-size: var(--t-text-h2); line-height: var(--t-leading-h2); color: inherit; text-decoration: none;
}
.s-menu-call {
  display: flex; align-items: center; justify-content: center;
  height: 48px; margin: auto var(--t-gap-5) var(--t-gap-5); /* margin-top: auto pins it to the bottom of the panel */
  color: inherit; text-decoration: none;
  border: var(--t-stroke-px) solid currentColor; border-radius: var(--t-radius-px);
}

.s-footer {
  margin-top: var(--t-gap-8); padding-block: var(--t-section-s) var(--t-gap-5);
  border-top: var(--t-stroke-px) solid color-mix(in srgb, var(--t-support) 15%, transparent);
  font-size: var(--t-text-small); line-height: var(--t-leading-small);
}
.s-footer p { margin: 0 0 var(--t-gap-1); overflow-wrap: anywhere; }
.s-footer-grid { display: grid; gap: var(--t-gap-5); }
@media (min-width: 640px) { .s-footer-grid { grid-template-columns: 1fr 1fr; } }
.s-footer-name { font-weight: 600; }
.s-footer-nav, .s-socials { list-style: none; margin: 0 0 var(--t-gap-4); padding: 0; display: flex; flex-wrap: wrap; gap: var(--t-gap-2) var(--t-gap-4); }
/* Every link down here is a tap target of its own: 44 × 44 px at least, and 8 px between one and the next
   (a mobile rule the platform's template gate measures). vertical-align: top keeps a line that holds
   one exactly as tall as the link. */
.s-footer-grid a { display: inline-flex; align-items: center; min-width: 44px; min-height: 44px; vertical-align: top; }
.s-footer-grid p:has(> a) { margin-bottom: var(--t-gap-2); }
.s-socials a { justify-content: center; width: 44px; height: 44px; color: inherit; }
.s-socials svg { width: 1.5rem; height: 1.5rem; }
.s-fine { margin-top: var(--t-gap-5); font-size: var(--t-text-label); line-height: var(--t-leading-label); opacity: 0.75; }

/* ---- the hero (blocks/hero.html) ---------------------------------------- */

/* The hero's own grid is the Content wrapper, layout two_col (above) — every
   hero is unconditionally two columns from 1024px, photo or none, as it always was. */
.s-eyebrow { color: var(--t-accent); margin-bottom: var(--t-gap-3); }
.t-tone-accent .s-eyebrow { color: inherit; }
/* var(--t-accent) on the dark band's own background measures 2.19:1, under the 4.5:1 floor;
   the band's own ink reads on it by design. */
.t-tone-dark .s-eyebrow { color: inherit; }
/* The hero's title is the display step, the biggest on the page. */
.s-headline { font-size: var(--t-text-display); line-height: var(--t-leading-display); margin-bottom: var(--t-gap-2); }
.s-sub { font-size: var(--t-text-lead); line-height: var(--t-leading-lead); }
.s-hero-media { margin: 0; }
.s-hero-media picture { display: block; }
.s-hero-media img { width: 100%; border-radius: var(--t-radius-px); }
.s-hero-media figcaption, .s-feature-media figcaption {
  font-size: var(--t-text-small); line-height: var(--t-leading-small); opacity: 0.75; margin-top: var(--t-gap-2);
}
.s-actions { display: flex; flex-wrap: wrap; gap: var(--t-gap-3); }

/* ---- the Text + image block (blocks/feature.html) ----------------------- */

/* Plain on purpose, for a conversion to replace with the drawn block. The photo is first in the
   markup, so a phone stacks it on top of the words; from 1024px the two sit in equal columns —
   the Content wrapper, layout two_col (above), added only when there is a photo, so a
   block with none keeps its words the whole width. `image_side: right` marks the photo
   `s-content-end` to trade places with the words. */
.s-feature-media { margin: 0; }
.s-feature-media img { width: 100%; border-radius: var(--t-radius-px); }

/* ---- buttons: the four tones the editor offers, and the agent's own color ----
 * A brand button is the `button` setting (template.json), behind a button's own color:
 * `--s-btn` is the color an agent gave one button, `--s-btn-ink` the label that reads on
 * it, and `--t-button-ink` the label the platform worked out for `--t-button`. Nothing but
 * a brand button reads `--t-button`. Every filled button's label is one of the platform's
 * inks, never a fixed white. */

.s-btn, .t-btn {
  display: inline-block; padding: var(--t-gap-3) var(--t-gap-5); border-radius: var(--t-radius-px);
  border: var(--t-stroke-px) solid transparent;
  font: inherit; font-weight: 600; text-decoration: none; cursor: pointer;
}
.s-btn-brand { background: var(--s-btn, var(--t-button)); color: var(--s-btn-ink, var(--t-button-ink)); }
.s-btn-ink { background: var(--s-btn, var(--t-support)); color: var(--s-btn-ink, var(--t-support-ink)); }
.s-btn-paper { background: var(--t-main); color: var(--s-btn, var(--t-main-ink)); border-color: currentColor; }
.s-btn-outline { background: transparent; color: var(--s-btn, var(--t-accent)); border-color: currentColor; }
/* On the accent band a brand button in the same color would vanish into it: a line in its label color keeps its edge. */
.t-tone-accent .s-btn-brand { border-color: currentColor; }
.t-tone-accent .t-btn-brand { border-color: currentColor; }
/* The outline button's label (and, via border-color: currentColor above, its border) is plain
   var(--t-accent) by default — on the accent band that IS the band's own background (measured
   1.00:1). The link-color fix above (line 88) explicitly excludes buttons, so it never reaches
   this one; --t-accent-ink reads on the band instead. Each family keeps its own agent-color
   escape hatch (--s-btn for the starter blocks, --t-btn for the platform's default ones). */
.t-tone-accent .s-btn-outline { color: var(--s-btn, var(--t-accent-ink)); }
.t-tone-accent .t-btn-outline { color: var(--t-btn, var(--t-accent-ink)); }
/* On the dark band, two of the four buttons need their own fix, beyond the link-color fix above:
   - the outline button's label is var(--t-accent) by default — 2.19:1 on this band's own
     background, same bug as the eyebrow and the focus ring above; --t-support-ink reads on it.
   - the ink button's own FILL is var(--t-support) — the same color as this band's own
     background (line 84) — so it disappears into it. --t-main is a ground that is actually
     different here, the way .s-btn-paper already reads it. Both keep the --s-btn/--s-btn-ink
     custom-property escape hatch an agent's own color uses. */
.t-tone-dark .s-btn-outline { color: var(--s-btn, var(--t-support-ink)); }
.t-tone-dark .s-btn-ink { background: var(--s-btn, var(--t-main)); color: var(--s-btn-ink, var(--t-main-ink)); }
/* A template built from the starter may drop blocks/feature.html and fall back to the
   platform's own default markup, which writes t-btn — so every s-btn-* band fix above needs
   its t-btn-* twin, or a template with no override keeps the bug the starter itself already
   fixed. Same reasoning, same values, the t-btn/-t-btn-ink escape hatch in place of s-btn/-ink. */
.t-tone-dark .t-btn-outline { color: var(--t-btn, var(--t-support-ink)); }
.t-tone-dark .t-btn-ink { background: var(--t-btn, var(--t-main)); color: var(--t-btn-ink, var(--t-main-ink)); }

/* The platform's default blocks use t-btn with the same tones. */
.t-btn-brand { background: var(--t-btn, var(--t-button)); color: var(--t-btn-ink, var(--t-button-ink)); }
.t-btn-ink { background: var(--t-btn, var(--t-support)); color: var(--t-btn-ink, var(--t-support-ink)); }
.t-btn-paper { background: var(--t-main); color: var(--t-btn, var(--t-main-ink)); border-color: currentColor; }
.t-btn-outline { background: transparent; color: var(--t-btn, var(--t-accent)); border-color: currentColor; }

/* ---- the platform's default blocks, lightly ----------------------------- */

.t-eyebrow { color: var(--t-accent); }
.t-tone-accent .t-eyebrow { color: inherit; }
/* Same fix as .s-eyebrow above, for the platform's default blocks. */
.t-tone-dark .t-eyebrow { color: inherit; }
.t-prose { max-width: 42rem; }
.t-listings, .t-posts, .t-gallery, .t-testimonials { display: grid; gap: var(--t-gap-5); padding: 0; margin: 0; list-style: none; }
@media (min-width: 640px) { .t-listings, .t-posts, .t-gallery, .t-testimonials { grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); } }
/* A neighborhood is its name over its note, each its own item, not one run-on line. */
.t-areas { display: grid; gap: var(--t-gap-4) var(--t-gap-5); padding: 0; margin: 0; list-style: none; }
@media (min-width: 640px) { .t-areas { grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); } }
.t-areas li { display: grid; gap: var(--t-gap-1); padding-top: var(--t-gap-3); border-top: 1px solid color-mix(in srgb, currentColor 20%, transparent); }
.t-area-name { font-family: var(--t-display); font-size: var(--t-text-h3); line-height: var(--t-leading-h3); }
.t-area-note { opacity: 0.85; }
.t-card a { color: inherit; text-decoration: none; }
.t-more { margin-top: var(--t-gap-5); }
.t-more a { display: inline-flex; align-items: center; min-height: 44px; }
/* A question is a tap target: at least 52 px tall, so two that touch still leave 8 px between their 44 px tap
   areas, whatever the Line spacing setting does to the line inside it. */
.t-faq summary { min-height: 52px; padding-block: var(--t-gap-3); cursor: pointer; }
.t-contact a { display: inline-flex; align-items: center; min-height: 44px; vertical-align: top; }
.t-contact p:has(> a) { margin-bottom: var(--t-gap-2); }
.t-card img { border-radius: var(--t-radius-px); margin-bottom: var(--t-gap-3); }
.t-card :is(h2, h3) { font-size: var(--t-text-h3); line-height: var(--t-leading-h3); margin-bottom: var(--t-gap-1); }
/* A post card's link is its cover and its title, or the title alone when the post has no cover: the title is 44px tall at least, a tap target of its own. */
.t-card-post > a { display: block; }
.t-card-post > a > h3 { display: flex; align-items: center; min-height: 44px; }
.t-status { margin: 0; }
.t-price { font-weight: 600; margin: 0; }
.t-facts { display: flex; gap: var(--t-gap-3); font-size: var(--t-text-small); line-height: var(--t-leading-small); opacity: 0.8; }
.t-quote { margin: 0; font-family: var(--t-display); font-size: var(--t-text-h3); line-height: var(--t-leading-h3); }
/* 0.85, not less: on the accent band (its ink on the accent) 0.75 falls to 4.47:1. */
.t-quote footer { font-family: var(--t-body); font-size: var(--t-text-body); line-height: var(--t-leading-body); opacity: 0.85; }
.t-form label, .s-form label { display: block; margin-bottom: var(--t-gap-4); }
/* A field is its own ground, whatever band it sits on: the page color and the text that reads on it. */
.t-form input, .t-form textarea, .s-form input, .s-form textarea {
  display: block; width: 100%; margin-top: var(--t-gap-1); padding: var(--t-gap-2) var(--t-gap-3);
  font: inherit; color: var(--t-main-ink); background: var(--t-main);
  border: var(--t-stroke-px) solid color-mix(in srgb, var(--t-support) 30%, transparent); border-radius: var(--t-radius-px);
}
.t-form-sent, .s-form-sent { padding: var(--t-gap-4); border-left: 4px solid var(--t-accent); }
.t-form-error, .s-form-error { padding: var(--t-gap-4); border-left: 4px solid #B91C1C; }
/* A form with the photo the agent chose beside it; a form with none has no band. As the Text + image
   block: the photo is first in the markup, so a phone stacks it on top, and from 1024px the two sit in
   equal columns with `right` moving the photo after the form. */
.t-form-band { display: grid; gap: var(--t-gap-6); align-items: start; }
.t-form-band > * { min-width: 0; }
@media (min-width: 1024px) {
  .t-form-band { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .t-form-band-right .t-form-media { order: 1; }
}
.t-form-media { margin: 0; }
.t-form-media img { width: 100%; border-radius: var(--t-radius-px); }

/* ---- pages, posts, the listing -------------------------------------------- */

.s-page-head { padding-block: var(--t-section-s) var(--t-gap-2); }
.s-meta { opacity: 0.8; }
/* A row that wraps on a narrow phone, or in a wide system font, keeps 8 px between its lines of 44 px links. */
.s-share { display: flex; flex-wrap: wrap; align-items: center; gap: var(--t-gap-2) var(--t-gap-3); font-size: var(--t-text-small); line-height: var(--t-leading-small); }
.s-share a { display: inline-flex; align-items: center; min-width: 44px; min-height: 44px; }
.s-neighbors { display: flex; justify-content: space-between; gap: var(--t-gap-4); margin-top: var(--t-gap-6); }
.s-neighbors a { display: inline-flex; align-items: center; min-height: 44px; }
.s-404 { padding-block: var(--t-section-m); }

/* The status pill: the listing page itself is the platform's now, but blocks/listings.html's quick view
   still draws its own status badge on the same class names. Sold is the one status in the second accent. */
.s-status-badge {
  display: inline-block; margin: 0; padding: var(--t-gap-1) var(--t-gap-3); border-radius: calc(var(--t-radius-px) / 2);
  background: var(--t-support); color: var(--t-support-ink);
}
.s-status-sold.s-status-badge { background: var(--t-accent2); color: var(--t-accent2-ink); }

/* ---- the quick view (blocks/listings.html): a pop-up with no script ----
   <details> opens and closes itself. Closed, its <summary> is the "Quick view" link at the foot of the card;
   open, that same <summary> is the dimmed backdrop (click anywhere on it, or its Close, to shut the panel)
   and the panel sits fixed in the middle of the window. */
.s-quick { margin-top: var(--t-gap-2); }
.s-quick-toggle {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-text-small); line-height: var(--t-leading-small); font-weight: 600;
  color: var(--t-accent); text-decoration: underline; text-underline-offset: 0.2em;
}
.s-quick-toggle::-webkit-details-marker { display: none; }
.s-quick-toggle::marker { content: ""; }
.s-quick-close { display: none; }
.s-quick[open] > .s-quick-toggle { position: fixed; inset: 0; z-index: 1000; display: block; text-decoration: none; background: color-mix(in srgb, var(--t-support) 60%, transparent); }
.s-quick[open] .s-quick-label { display: none; }
.s-quick[open] .s-quick-close {
  position: absolute; top: var(--t-gap-4); right: var(--t-gap-4); display: inline-block; padding: var(--t-gap-2) var(--t-gap-4);
  color: var(--t-support-ink); background: var(--t-support); border: var(--t-stroke-px) solid currentColor; border-radius: var(--t-radius-px);
}
.s-quick[open] .s-quick-close::after { content: " \00d7"; }
/* nothing scrolls behind it — and no ancestor may keep a transform, filter or will-change while it is open: any of
   those makes the ancestor the containing block of the fixed panel and backdrop, and the pop-up is trapped inside the card */
body:has(.s-quick[open]) { overflow: hidden; }
body:has(.s-quick[open]) :has(.s-quick[open]) { transform: none !important; transition: none !important; animation: none !important; will-change: auto !important; filter: none !important; }
.s-quick-panel { display: none; }
.s-quick[open] > .s-quick-panel {
  display: grid; position: fixed; z-index: 1001; inset: 0; margin: auto; height: fit-content;
  width: min(64rem, calc(100vw - 2rem)); max-height: calc(100vh - 6rem); overflow: auto; overscroll-behavior: contain;
  background: var(--t-main); color: var(--t-main-ink); border-radius: var(--t-radius-px); text-align: left;
}
@media (min-width: 768px) { .s-quick[open] > .s-quick-panel:has(.s-quick-media) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.s-quick-media { padding: var(--t-gap-4); }
.s-quick-media > img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: calc(var(--t-radius-px) / 2); margin: 0; }
/* the four thumbnails under the photo, on one row */
.s-quick-thumbs { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--t-gap-2); margin-top: var(--t-gap-2); }
.s-quick-thumbs img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: calc(var(--t-radius-px) / 2); margin: 0; }
.s-quick-copy { display: flex; flex-direction: column; align-items: flex-start; gap: var(--t-gap-2); padding: var(--t-gap-5); min-width: 0; }
@media (min-width: 768px) { .s-quick-copy { padding: var(--t-gap-6) var(--t-gap-6) var(--t-gap-6) var(--t-gap-4); } }
.s-quick-copy > * { margin: 0; max-width: none; }
.s-quick-kicker { display: flex; align-items: center; gap: var(--t-gap-3); }
.s-quick-kicker .s-eyebrow, .s-quick-kicker .s-status-badge { margin: 0; }
.s-quick-title { font-family: var(--t-display); font-size: var(--t-text-h3); line-height: var(--t-leading-h3); }
.s-quick-desc { opacity: 0.85; }
.s-quick-price-label { margin-top: var(--t-gap-2); }
.s-quick-price { font-size: var(--t-text-h3); line-height: var(--t-leading-h3); font-weight: 600; }
.s-quick-copy .s-actions { margin-top: var(--t-gap-2); }
/* the card's own `.t-card a { color: inherit }` outranks .s-btn-*, so the buttons say their colors again here */
.s-quick-copy .s-btn-ink { color: var(--s-btn-ink, var(--t-support-ink)); }
.s-quick-copy .s-btn-outline { color: var(--s-btn, var(--t-accent)); }
.s-quick-more { font-size: var(--t-text-small); line-height: var(--t-leading-small); }
.s-quick-more a { display: inline-flex; align-items: center; min-height: 44px; }

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

/* Every duration above is a --t-motion-* name, which the platform sets to 0 ms for a visitor who asked for less
   motion, so nothing here has to stop them. This block is where a transition timed by hand is stopped; it names the
   menu's too, so a copy that retimes those bars by hand is already covered. */
@media (prefers-reduced-motion: reduce) {
  .s-menu-toggle span { transition: none; }
}

/* ---- the style panel's menu: one rule per id in template.json → styles ----
   Last in the file, so an agent's pick wins over a block's own face, size or color. */

.t-font-display { font-family: var(--t-display); }
.t-font-body { font-family: var(--t-body); }
.t-size-sm { font-size: 0.875em; }
.t-size-md { font-size: 1em; }
.t-size-lg { font-size: 1.375em; }
.t-color-ink { color: var(--t-support); }
.t-color-accent { color: var(--t-accent); }
.t-color-dim { color: color-mix(in srgb, var(--t-support) 68%, var(--t-main)); }
