/*
 * The layout primitives.
 *
 * Namespaced `sys-` on purpose. site.css already owns `.sec`, `.wrap` and
 * `.prose`, and two stylesheets fighting over one class name is how spacing
 * ends up depending on which file loaded last. Nothing here shares a name with
 * anything in the older sheet.
 *
 * Every length is a token. There are no numbers in this file.
 */

.sys-sec {
  padding-block: var(--density-normal);
  padding-inline: var(--space-gutter);
}
.sys-sec[data-density="tight"] { padding-block: var(--density-tight); }
.sys-sec[data-density="open"]  { padding-block: var(--density-open); }

/* Two sections of the same ground read as one run of colour, so they get one
 * run of padding rather than two stacked.
 *
 * A band is excluded at both ends. It carries the same tone as its neighbours
 * so the strip beside a shorter picture matches the page, but it is a
 * photograph, not a continuation of the colour: collapsing the padding after
 * one put the first line of body text hard against the bottom of the image. */
.sys-sec.tone-paper:not([data-band])   + .sys-sec.tone-paper:not([data-band]),
.sys-sec.tone-raised:not([data-band])  + .sys-sec.tone-raised:not([data-band]),
.sys-sec.tone-sand:not([data-band])    + .sys-sec.tone-sand:not([data-band]),
.sys-sec.tone-deep:not([data-band])    + .sys-sec.tone-deep:not([data-band]),
.sys-sec.tone-deepest:not([data-band]) + .sys-sec.tone-deepest:not([data-band]) { padding-block-start: 0; }

/*
 * A hairline between one section and the next, which is what the home page
 * does and the system pages did not.
 *
 * `.sec` in site.css has carried `border-top: var(--rule)` from the beginning.
 * It is the cheapest device on the page and it does the most work: without it
 * a run of sections on one ground is a scroll of paragraphs, and with it the
 * page reads as composed of parts.
 *
 * Only where the ground does not already change. A rule at a colour boundary
 * is redundant, and a rule directly under a full bleed photograph cuts it off
 * from the words that belong to it.
 */
.sys-sec.tone-paper:not([data-band])   + .sys-sec.tone-paper:not([data-band]),
.sys-sec.tone-raised:not([data-band])  + .sys-sec.tone-raised:not([data-band]),
.sys-sec.tone-sand:not([data-band])    + .sys-sec.tone-sand:not([data-band]),
.sys-sec.tone-deep:not([data-band])    + .sys-sec.tone-deep:not([data-band]),
.sys-sec.tone-deepest:not([data-band]) + .sys-sec.tone-deepest:not([data-band]) {
  /* The collapse above removed the padding so the two would read as one run of
     colour. With a rule between them they are two sections again, and the rule
     needs air on both sides. */
  padding-block-start: var(--density-normal);
}
.sys-sec[data-band] + .sys-sec { border-block-start: 0; }

/* Children are spaced by the layout, not by margins.
 *
 * This used to be `.sys-wrap > * + * { margin-block-start: ... }`, which lost
 * every argument with a component that resets its own margin. `.t-title`,
 * `.steps` and others all declare `margin: 0` at the same specificity further
 * down the file, so the last one written won and the gap silently became zero.
 * Nothing failed. The pages just quietly lost their rhythm. A grid gap cannot
 * be overridden by a child at all, which is the point. */
.sys-wrap {
  margin-inline: auto; min-width: 0; width: 100%;
  display: grid; align-content: start; gap: var(--space-block);
  /* One column the width of the wrap, never wider. Left to size itself, the
   * column grew to the widest thing inside it, which on a phone at 200% zoom
   * pushed every block on the page past the right edge (ECHOSTUDIO-762). */
  grid-template-columns: minmax(0, 1fr);
}

/* A grid stretches its children. Things that are shaped by their own content
 * say so. */
.sys-wrap > .btn-cta, .sys-wrap > .crumbs { justify-self: start; }

/* An eyebrow belongs to the heading under it, not to the block above it. */
.sys-wrap hgroup { display: grid; gap: var(--space-tight); }
.sys-wrap[data-measure="prose"] { max-width: var(--measure-prose); }
.sys-wrap[data-measure="wide"]  { max-width: var(--measure-wide); }
.sys-wrap[data-measure="full"]  { max-width: none; }

/* ---- type roles. A component picks a role, never a size. ---- */
.t-display, .t-title, .t-heading, .t-lede, .t-body, .t-small, .t-label { margin: 0; }
.t-display { font: var(--text-display-weight) var(--text-display-size)/var(--text-display-leading) var(--text-display-family); letter-spacing: var(--text-display-tracking); text-wrap: balance; }
.t-title   { font: var(--text-title-weight) var(--text-title-size)/var(--text-title-leading) var(--text-title-family); letter-spacing: var(--text-title-tracking); text-wrap: balance; }
.t-heading { font: var(--text-heading-weight) var(--text-heading-size)/var(--text-heading-leading) var(--text-heading-family); letter-spacing: var(--text-heading-tracking); text-wrap: balance; }
.t-lede    { font: var(--text-lede-weight) var(--text-lede-size)/var(--text-lede-leading) var(--text-lede-family); color: var(--muted, inherit); }
.t-body    { font: var(--text-body-weight) var(--text-body-size)/var(--text-body-leading) var(--text-body-family); }
.t-small   { font: var(--text-small-weight) var(--text-small-size)/var(--text-small-leading) var(--text-small-family); color: var(--muted, inherit); }
.t-label   { font: var(--text-label-weight) var(--text-label-size)/var(--text-label-leading) var(--text-label-family); letter-spacing: var(--text-label-tracking); text-transform: uppercase; color: var(--muted, inherit); }

/* Paragraph rhythm inside a block is tighter than the gap between blocks. */
.sys-prose > * + * { margin-block-start: var(--space-base); }

/* ---- the one button. Colour comes from the surrounding tone. ---- */
.btn-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-tight);
  padding: var(--space-snug) var(--space-roomy);
  background: var(--cta-bg);
  color: var(--cta-fg);
  border-radius: var(--radius-sm);
  text-decoration: none;
  font: var(--text-label-weight) var(--text-small-size)/1 var(--text-label-family);
  letter-spacing: var(--text-label-tracking);
  text-transform: uppercase;
}
.btn-cta:hover { background: var(--cta-hover); }
.btn-cta--small { padding: var(--space-tight) var(--space-base); }

/*
 * The system button, made the same object as the home page's.
 *
 * Hers is a pill carrying a dark circle with an arrow in it, and it is the
 * single most recognisable thing on the page. The system pages had a small
 * square uppercase chip instead, which is a different design speaking a
 * different language on the same site.
 *
 * The circle is drawn here rather than added to the markup of a dozen call
 * sites, and it works on both grounds without a variant: on parchment the
 * button is orange with a teal circle, on teal it is parchment with a teal
 * circle, and the arrow is light in both.
 */
.btn-cta {
  gap: var(--space-base);
  padding: var(--space-tight) var(--space-tight) var(--space-tight) var(--space-roomy);
  border-radius: var(--radius-pill);
  /* A button is the size of its label. Without this a grid stretches it, and
     "Book with Maggie" became a 460px bar across half the page. The home
     page's button has carried this from the beginning. fit-content, not
     max-content: the same size whenever the label fits, but a max-content
     button counted its whole label as the narrowest its column could be, so
     at 200% zoom on a phone every block beside it went off the screen (ECHOSTUDIO-762). */
  width: fit-content;
  max-width: 100%;
  font: var(--text-body-weight) var(--text-body-size)/1 var(--text-body-family);
  letter-spacing: 0;
  text-transform: none;
  min-height: 3.125rem;
}
.btn-cta::after {
  content: "";
  inline-size: 2.375rem; block-size: 2.375rem; flex: none;
  border-radius: var(--radius-pill);
  background: var(--tone-deepest-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23F7F1E6' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8h10M9 4l4 4-4 4'/%3E%3C/svg%3E") center / 0.9375rem no-repeat;
  transition: transform .3s var(--ease, ease);
}
.btn-cta:hover::after { transform: rotate(-45deg); }
/* The same button as a <button>: no browser border. Not `font: inherit`, which
   outranks .btn-cta's own font by specificity. */
button.btn-cta { border: 0; cursor: pointer; }
.btn-cta--small { min-height: 2.625rem; padding-inline-start: var(--space-base); font-size: var(--text-small-size); }
.btn-cta--small::after { inline-size: 2rem; block-size: 2rem; }
/* A button that is only an arrow, for a row that already says where it goes. */
.btn-cta--bare { padding: 0; background: none; color: inherit; min-height: 0; }
.btn-cta--bare:hover { background: none; color: var(--muted, inherit); }

/* ---- prices: a list, because one column of numbers is a list ---- */
.pricelist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-snug); }
.pricelist > li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-tight) var(--space-base);
  padding-block: var(--space-snug);
  border-block-end: var(--space-hair) solid var(--rule-colour);
}
.pricelist > li > :first-child { flex: 1 1 14rem; }
.pricelist .price { font-variant-numeric: tabular-nums; }
/* Several durations on one treatment: each on its own line, never run together. */
.prices { flex: 0 1 auto; display: grid; gap: var(--space-tight); justify-items: start; }
.pricerow {
  display: flex; gap: var(--space-snug); align-items: baseline;
  font-variant-numeric: tabular-nums;
}
.pricerow > b { font-weight: 600; }

/* ---- cards ---- */
.cards {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-roomy);
  /* auto-fit, not auto-fill. auto-fill keeps making empty columns once the
   * items run out, so eight practitioners on a 2560px page sat in eight
   * cramped columns with a ninth left empty on the right. auto-fit collapses
   * the empty tracks and the cards share the room instead. */
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}
/* No maximum track width here, deliberately. Capping the card at 22rem looked
 * right in the abstract and put eight practitioners into six columns and a
 * second row of two, with a quarter of the page empty beside them. Letting the
 * tracks stretch keeps whatever the row holds spread evenly across it, which is
 * what the grid is for. */
.cards > li > a { display: grid; gap: var(--space-tight); text-decoration: none; color: inherit; }
.cards img { width: 100%; height: auto; border-radius: var(--radius-sm); }

.crumbs { font: var(--text-small-weight) var(--text-small-size)/1.4 var(--text-small-family); color: var(--muted, inherit); }
.crumbs a { color: inherit; }

/* Wide content scrolls inside itself so the page never scrolls sideways. */
.overflow-guard { overflow-x: auto; max-width: 100%; }

/* ------------------------------------------------------------------ blocks
 * One rule per block wrapper. Most only need to say how their own children sit
 * together; spacing between blocks is the Section's job and is never set here.
 */

.blk-hero { display: grid; gap: var(--space-roomy); }

/* A heading and the words under it. Spaced by a gap rather than margins, for
 * the same reason as .sys-wrap: every type role resets its own margin, so a
 * margin rule here lost to .t-title and .t-lede and the heading sat on the
 * paragraph below it. */
.blk-text { display: grid; gap: var(--space-base); align-content: start; }
/* The designed pages set a label and a display heading against the prose rather
 * than stacking everything into one reading column. */
.blk-text--head { gap: var(--space-base) var(--space-block); align-items: start; }
/* The same two columns as a section head, and packed left for the same
 * reason: a fractional heading column takes every spare pixel, so the words
 * were pushed against the right edge with a gap in the middle of the page. */
@media (min-width: 900px) {
  .blk-text--head { grid-template-columns: minmax(0, var(--head-col)) minmax(0, 1fr); }
}
.blk-text--head > div:first-child { display: grid; gap: var(--space-tight); align-content: start; }
.blk-text--head > .prose { max-width: 54ch; }
/* The hero's own photograph only. `.blk-hero img` also caught the laurels in
   the rating badges and drew each one the full width of the page. */
.blk-hero > img { width: 100%; height: auto; border-radius: var(--radius-sm); }

.blk-split {
  display: grid;
  gap: var(--space-roomy) var(--space-block);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .blk-split { grid-template-columns: 1fr 1fr; }
  .blk-split[data-side="left"] > :first-child { order: 2; }
}
/*
 * The photograph fills its half of the section.
 *
 * Half her library is a 1800x536 banner crop, so `height: auto` drew a letter
 * box sliver beside three paragraphs: the foot bath on About was 253px tall in
 * an 850px column. The picture is given the height of the words beside it and
 * covers it, with a floor so a two line section still gets a photograph rather
 * than a strip.
 */
.blk-split img { width: 100%; border-radius: var(--radius-sm); aspect-ratio: 4 / 3; object-fit: cover; }
@media (min-width: 900px) {
  .blk-split { align-items: stretch; }
  .blk-split > div { align-content: center; }
  /* A floor and a ceiling rather than a ratio: her library runs from 1800x536
   * to square, and left alone one drew a 253px strip and the other a 670px
   * tower beside the same three paragraphs. Between these two the photograph
   * is the height of the words wherever the words allow it. */
  .blk-split img { height: 100%; aspect-ratio: auto; min-height: 22rem; max-height: 32rem; }
  /* The photograph touches the edges of its section: the outer page edge on
     its own side, and the top and bottom of the band. Phil: it was "just
     sitting there within the section, not touching any borders". The words
     keep the page gutter and the grid; only the picture leaves the frame, by
     the section's own padding, so nothing else moves. */
  .blk-split img {
    margin-block: calc(-1 * var(--density-normal));
    height: calc(100% + 2 * var(--density-normal));
    min-height: calc(22rem + 2 * var(--density-normal));
    max-height: calc(32rem + 2 * var(--density-normal));
    border-radius: 0;
  }
  /* max-width: none, or the global image cap holds the picture at its column
     width and the right hand one stops a gutter short of the edge. */
  .blk-split[data-side="right"] img { margin-inline-end: calc(-1 * var(--space-gutter)); width: calc(100% + var(--space-gutter)); max-width: none; }
  .blk-split[data-side="left"] img { margin-inline-start: calc(-1 * var(--space-gutter)); width: calc(100% + var(--space-gutter)); max-width: none; }
  .sys-sec:has(> .sys-wrap > .blk-split) { overflow: hidden; }
}
.blk-split > div { display: grid; gap: var(--space-base); justify-items: start; }

.blk-statement { margin: 0; display: grid; gap: var(--space-snug); justify-items: start; }
.blk-statement blockquote { margin: 0; }

.blk-grid, .blk-people, .blk-reviews, .blk-events, .blk-journal,
.blk-prices, .blk-faq, .blk-steps, .blk-where, .blk-itinerary,
.blk-cta, .blk-retreat, .blk-enquiry, .blk-ebook {
  display: grid;
  gap: var(--space-roomy);
  justify-items: start;
}
.blk-grid > ul, .blk-people > ul, .blk-reviews > ul, .blk-events > ul,
.blk-journal > ul, .blk-prices > ul, .blk-retreat > ul { width: 100%; }

.blk-cta { justify-items: start; }

/* A one line notice and the thing to do about it.
 *
 * On a finished retreat this is "this one has run, the next is in October"
 * and a button. Stacked, the two of them used 15% of a 2560px page and 27% of
 * a 1440 one, which made a band of colour look like a mistake rather than a
 * message. Side by side, with the action against the right edge. */
.noticebar { display: grid; gap: var(--space-roomy); align-items: center; width: 100%; }
@media (min-width: 900px) {
  .noticebar { grid-template-columns: 1fr auto; column-gap: var(--space-block); }
  .noticebar > .btn-cta { justify-self: end; }
}
.noticebar .t-body { max-width: 68ch; }
/* The left hand side can be a heading and a line rather than a bare sentence. */
.noticebar > div { display: grid; gap: var(--space-snug); align-content: start; }

/* The enquiry block is a heading, a few questions people ask, and the form.
 * Stacked, it used 39% of a 2560px page with the rest empty. The words and
 * the questions go on the left, the form on the right, which is the same
 * arrangement as every section opener on the site.
 *
 * Columns are assigned rather than taken in order, because the form is the
 * last of several siblings and the document order is worth leaving alone: a
 * screen reader should still meet the answers before the form. */
.blk-enquiry { justify-items: start; width: 100%; }
@media (min-width: 1000px) {
  .blk-enquiry { grid-template-columns: 1fr auto; align-items: start; column-gap: var(--space-block); justify-items: stretch; }
  .blk-enquiry > :not(.enquiry-wrap) { grid-column: 1; justify-self: start; }
  .blk-enquiry > .enquiry-wrap { grid-column: 2; grid-row: 1 / span 4; justify-self: end; width: min(30rem, 100%); }
}

/* The newsletter block is a short invitation and two fields, and stacked it
 * used half the page and left the other half empty. Beside each other they
 * read as one thing and the section uses its width, which is the same move as
 * the section opener: words on the left, the thing you do on the right. */
.blk-ebook { width: 100%; }
@media (min-width: 900px) {
  .blk-ebook { grid-template-columns: 1fr auto; align-items: start; column-gap: var(--space-block); }
  /* The heading and the invitation are siblings of the form rather than being
   * wrapped, in both places this block is used, so the columns are assigned
   * rather than taken in order. */
  .blk-ebook > :not(.ebook-form) { grid-column: 1; }
  .blk-ebook > .ebook-form { grid-column: 2; grid-row: 1 / span 3; justify-self: end; min-width: 22rem; }
}

/* Reviews read as quotes, not cards in a shop. */
.blk-reviews .cards > li { display: grid; gap: var(--space-tight); }

/* A row of short pieces, which is what the block is for: the four doshas,
 * what to bring, what a respite stay includes. It had only ever been a stack,
 * so on /about "Treading lightly" was three sentences down the left hand side
 * using 36% of a 2560px page. Wide enough to keep each one readable, and they
 * wrap to fewer columns rather than getting narrower. */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-block); width: 100%; }
@media (min-width: 900px) {
  .steps { grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); gap: var(--space-block) var(--space-roomy); }
}
.steps > li { display: grid; gap: var(--space-tight); justify-items: start; }
.steps[data-numbered="true"] { counter-reset: step; }
.steps[data-numbered="true"] > li { counter-increment: step; }
.steps[data-numbered="true"] > li > h3::before {
  content: counter(step) ". ";
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.steps img { max-width: 13rem; height: auto; }

.blk-faq .faq { width: 100%; border-block-end: var(--space-hair) solid var(--rule-colour); padding-block: var(--space-snug); }
.blk-faq summary { cursor: pointer; }
.blk-faq .faq > p { margin-block-start: var(--space-tight); color: var(--muted); }

.hours { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-tight); }
.hours > li { display: flex; gap: var(--space-base); align-items: baseline; }

.blk-itinerary section { display: grid; gap: var(--space-snug); width: 100%; }
.blk-itinerary ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-tight); }
.blk-itinerary li { display: flex; gap: var(--space-base); align-items: baseline; }

.blk-gallery {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-roomy);
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
}
.blk-gallery img { width: 100%; height: auto; border-radius: var(--radius-sm); }

.blk-drawing, .blk-media { margin: 0; display: grid; gap: var(--space-snug); justify-items: start; }
.blk-drawing img { max-width: 44rem; width: 100%; height: auto; }
.blk-media img { width: 100%; height: auto; border-radius: var(--radius-sm); }
/* A video as a still until it is clicked (ECHOSTUDIO-207): 16:9, a play disc
   in the middle, the player swapped in on the same box so nothing moves. */
.blk-media--video { width: 100%; max-width: 56rem; }
.video-facade { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; border-radius: var(--radius-sm); overflow: hidden; background: var(--rule-colour); }
.video-facade img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
.video-facade iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-play { position: absolute; top: 50%; left: 50%; translate: -50% -50%; display: grid; place-items: center; width: 4.5rem; aspect-ratio: 1; border-radius: 50%; background: rgba(6, 38, 39, .82); color: var(--parchment, #f7f1e6); transition: transform .3s ease, background .3s ease; }
.video-play svg { width: 42%; margin-left: 6%; }
.video-facade:hover .video-play, .video-facade:focus-visible .video-play { transform: scale(1.08); background: rgba(6, 38, 39, .95); }
@media (prefers-reduced-motion: reduce) { .video-play { transition: none; } }

/* Vagaro paints its own white interface inside an iframe we cannot style, so
 * the join is made from the outside. The container carries the ground, the
 * hairline and the radius, and the widget sits in it like a card rather than a
 * hole cut in the page. Anything that would need to line up with their layout
 * is kept off this section entirely. */
.blk-vagaro { display: grid; gap: var(--space-snug); width: 100%; }

.vagaro-embed {
  position: relative;
  width: 100%;
  min-height: 34rem;
  background: var(--hue-white);
  border: var(--space-hair) solid var(--rule-colour, var(--hue-hair));
  border-radius: var(--radius-lg);
  overflow: hidden;
}

/* The scaffolding the loader needs, built in VagaroWidget rather than in JSX.
 * Their own stylesheet styles everything from .vagaro-container inwards. */
.vagaro-outer { display: block; width: 100%; }
.vagaro-embed iframe { display: block; width: 100%; border: 0; }
/* Their footer repeats the attribution we already carry once, below the card. */
.vagaro-embed .vagaro-footer, .vagaro-embed .vagaro-download { display: none; }

/* Held space in the widget's own shape: a header bar, then rows of times. */
.vagaro-skeleton {
  position: absolute; inset: 0;
  display: grid; gap: var(--space-base); align-content: start;
  padding: var(--space-pad);
  background: var(--hue-white);
}
.vagaro-skeleton > span {
  display: block; height: var(--space-block);
  background: var(--tone-raised-bg);
  border-radius: var(--radius-sm);
  animation: vagaro-breathe 1.8s ease-in-out infinite;
}
.vagaro-skeleton > span:nth-child(1) { width: 45%; }
.vagaro-skeleton > span:nth-child(2) { width: 100%; animation-delay: .15s; }
.vagaro-skeleton > span:nth-child(3) { width: 78%; animation-delay: .3s; }

@keyframes vagaro-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  .vagaro-skeleton > span { animation: none; }
}

.vagaro-fallback { padding: var(--space-pad); }

/* Vagaro's terms ask for the attribution. It is a footnote, not a feature. */
.vagaro-by { justify-self: end; }
.vagaro-by a { color: inherit; }

.vagaro-frame { position: relative; display: block; width: 100%; min-height: 34rem; border: 0; }

.screening { width: 100%; display: grid; gap: var(--space-tight); }
.enquiry, .ebook-form { width: 100%; display: grid; gap: var(--space-tight); max-width: var(--measure-prose); }
.enquiry input, .enquiry textarea, .ebook-form input {
  font: inherit;
  padding: var(--space-snug);
  border: var(--space-hair) solid var(--rule-colour);
  border-radius: var(--radius-sm);
  background: var(--tone-paper-bg);
  color: var(--tone-paper-fg);
  width: 100%;
}
.enquiry button, .ebook-form button { justify-self: start; margin-block-start: var(--space-tight); }

/* The honeypot. Off screen rather than display:none, because some bots skip
 * hidden fields and a screen reader should not announce it either. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.enquiry-done { display: grid; gap: var(--space-tight); }
.enquiry-problem { color: var(--hue-orange-action-deep); }

.inclusions { margin: 0; padding-left: var(--space-roomy); display: grid; gap: var(--space-tight); }

/* ------------------------------------------------------------------ bands
 *
 * A picture that is the section, edge to edge.
 *
 * Meadowell alternate a flat colour field carrying words with a full bleed
 * picture carrying almost none, and that alternation is what separates their
 * sections. No card, no radius, no shadow, no gutter: the change of ground is
 * the separation. `.sys-sec[data-band]` drops the section's own padding so the
 * image touches the sections above and below it.
 */
.sys-sec[data-band] { padding-inline: 0; padding-block: 0; }
.sys-sec[data-band] .sys-wrap { max-width: none; gap: 0; }
.band-figure { margin: 0; display: block; }
.band-figure img {
  display: block; width: 100%; height: clamp(18rem, 46vw, 34rem);
  object-fit: cover; border-radius: var(--radius-none);
}
/* A small photograph at its own size, centred, rather than upscaled to soft. */
.band-figure--native { padding: var(--space-block) var(--gutter, 1.25rem); }
.band-figure--native img {
  width: auto; max-width: 100%; height: auto; margin-inline: auto;
  border-radius: var(--radius-sm);
}
/* A band is a landscape frame and a head shot is not, so one run through the
 * other comes out as a strip across somebody's eyes. Faces get their own
 * container instead: the picture at its own aspect on one side, the words on
 * the other, which is where a portrait has always gone in print. */
.portrait {
  display: grid; gap: var(--space-block) var(--space-block); width: 100%;
  align-items: start;
}
.portrait > figure { margin: 0; display: grid; gap: var(--space-snug); }
.portrait img { width: 100%; height: auto; border-radius: var(--radius-none); display: block; }
.portrait > .portrait-words { display: grid; gap: var(--space-roomy); align-content: start; }
.portrait .t-body, .portrait .t-lede { max-width: 58ch; }
@media (min-width: 900px) {
  /* The picture grows with the page, the words do not.
   *
   * A fixed 22rem plate beside a 58ch column is a third of a 2560px screen and
   * two thirds of nothing, while every other section on the page runs gutter to
   * gutter. Prose cannot be the thing that fills the space, because a longer
   * line is harder to read and not more generous. A photograph can, and at this
   * size it stops being a thumbnail of somebody and becomes their portrait. */
  .portrait { grid-template-columns: minmax(0, clamp(22rem, 40vw, 64rem)) minmax(0, 1fr); }
  /* Three paragraphs against a full height portrait leaves the hole at the
   * bottom of the column rather than spread through it. Set against the
   * picture, not hung from its top corner. */
  .portrait > .portrait-words { align-self: center; }
}

/* ------------------------------------------------------------------ tlist
 *
 * A list of treatments, set like a page of a menu rather than a grid of cards.
 *
 * `.cards` packs into as many 16rem columns as fit, which at 1440 is four
 * cramped ones. Two columns with a rule between rows gives each treatment a
 * full line of its own, which is how a long list stays readable.
 */
.tlist {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 0;
  border-block-start: var(--space-hair) solid var(--rule-colour);
}
@media (min-width: 900px) {
  .tlist { grid-template-columns: 1fr 1fr; column-gap: var(--space-block); }
}
.tlist > li { border-block-end: var(--space-hair) solid var(--rule-colour); }
.tlist > li > a {
  display: grid; gap: var(--space-tight); text-decoration: none; color: inherit;
  padding-block: var(--space-roomy);
}
.tlist > li > a:hover .t-heading {
  text-decoration: underline; text-underline-offset: var(--space-tight);
}
.tlist .t-small { max-width: 46ch; }

/* The page container, wider than any reading measure. */
.sys-wrap[data-measure="page"] { max-width: var(--measure-page); }

/*
 * The line every two-up hangs from. A section head, a CMS words block and a
 * set of notes all take their left column from this, so their right hand
 * columns start at the same x down a page. It used to be each heading's own
 * width, and one page had its body text starting at three different places.
 * A percentage so a tablet keeps a usable right column; a cap so a 2560px
 * screen does not push the words into the middle of nowhere.
 */
.sys-wrap { --head-col: min(36rem, 40%); }

/*
 * Running text keeps a reading measure even inside the page container.
 *
 * `page` is 82rem so a grid and a picture band can use the full width. A
 * paragraph at 16px across 82rem is about 200 characters a line, which nobody
 * can read, so the text roles hold themselves to the prose measure. Headings
 * are exempt: a heading is scanned, not read, and running one wide is the
 * point of the scale.
 */
.sys-wrap[data-measure="page"] > .t-lede,
.sys-wrap[data-measure="page"] > .t-body,
.sys-wrap[data-measure="page"] > .t-small,
.sys-wrap[data-measure="page"] > p { max-width: var(--measure-prose); }

/* ------------------------------------------------------------------ svchead
 *
 * A treatment opens with its name beside its drawing.
 *
 * The forty three engraved drawings exist because Marye will never have a
 * photograph of every individual treatment and forty stock photos would look
 * like a stock library. Forty drawings read as one set. The drawing sits
 * straight on the ground with no card, no plate and no border, because a panel
 * behind it makes it read as interface rather than as content.
 */
.svchead { display: grid; gap: var(--space-block); align-items: start; }
@media (min-width: 900px) { .svchead { grid-template-columns: 1.2fr 0.8fr; } }
.svchead .svchead-words { display: grid; gap: var(--space-base); align-content: start; }
.svchead .svchead-words > .t-lede { max-width: var(--measure-prose); }
.svchead .svchead-art { display: flex; justify-content: flex-end; }
.svchead .svchead-art img { width: 100%; max-width: 22rem; height: auto; }
@media (max-width: 899px) { .svchead .svchead-art { justify-content: flex-start; } }

/* A price table, set full width like their list of labs rather than squeezed
 * into a reading column. The row is a line in a menu: what you get, what it
 * costs, and the way to book it. */
.pricetable { list-style: none; margin: 0; padding: 0; display: grid; gap: 0;
  border-block-start: var(--space-hair) solid var(--rule-colour); }
.pricetable > li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-base) var(--space-roomy);
  padding-block: var(--space-roomy);
  border-block-end: var(--space-hair) solid var(--rule-colour);
}
.pricetable > li > .what { flex: 1 1 18rem; }
.pricetable > li > .amt { font-variant-numeric: tabular-nums; }
.pricetable > li > .btn-cta { margin-inline-start: auto; }

/* ------------------------------------------------------------------ sechead
 *
 * Their signature opener: the heading on the left, one 16px paragraph on the
 * right, both starting on the same line.
 *
 * Every wide section on meadowell.com opens this way. "Foundational labs" at
 * 100px sits on the left with four lines of 16px sitting in the top right
 * corner beside it, and "Meadowell Method" does the same. Stacking the
 * paragraph under the heading is what leaves the right half of the page empty,
 * which is the single biggest reason our sections were not using the width.
 *
 * The paragraph is deliberately small and deliberately short. It is a caption
 * to the heading, not an introduction to the section.
 */
.sechead { display: grid; gap: var(--space-roomy) var(--space-block); align-items: start; }
@media (min-width: 900px) {
  /*
   * Two columns that pack from the left, not a heading that eats the page.
   *
   * This was `1fr auto` with the paragraph pushed to the far edge. A `1fr`
   * heading column takes every spare pixel, so the two halves were only ever
   * as close as the page was narrow. With a long heading that reads as a
   * spread; with a short one it is a void, and a page opener's heading is a
   * name. "Maggie" sat seven hundred pixels away from the words about her.
   *
   * fit-content caps the heading column at a width a display line can
   * actually fill, and shrinks it to the words when they are shorter, so a
   * one word name and a full sentence both sit next to their paragraph.
   */
  .sechead { grid-template-columns: minmax(0, var(--head-col)) minmax(0, 1fr); align-items: start; }
  .sechead > .sechead-aside { padding-block-start: var(--space-snug); }
}
.sechead > .sechead-words { display: grid; gap: var(--space-snug); align-content: start; }
/* 42ch here was a caption's measure, and it is right for one sentence beside a
 * heading. Four paragraphs of it is a narrow gutter of text down the middle of
 * the page with the heading's column empty beneath it, so the cap is a reading
 * measure rather than a caption's. */
.sechead > .sechead-aside { display: grid; gap: var(--space-base); align-content: start; max-width: 54ch; }
/* A button in the aside (the gift voucher opening) sits at its own width. */
.sechead-aside > .btn-cta { justify-self: start; }
/* Inside a sechead the paragraph is already in its own column, so the page
 * container's prose clamp would narrow it twice. */
.sechead .t-lede, .sechead .t-body, .sechead .t-small { max-width: none; }

/* ------------------------------------------------------------------ rowlist
 *
 * A list where every entry gets the full width of the page.
 *
 * Their foundational labs list: a thumbnail, a name at display size, a small
 * caps line under it, and an affordance pushed to the far right, separated by
 * dotted rules. It reads as a list rather than as a grid of cards, which is
 * what a long menu of treatments actually is, and it gives each of the forty
 * three engraved drawings somewhere to be.
 */
.rowlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 0;
  border-block-start: var(--space-hair) dashed var(--rule-colour); }
.rowlist > li { border-block-end: var(--space-hair) dashed var(--rule-colour); }
.rowlist > li > a {
  display: grid; align-items: center; gap: var(--space-base) var(--space-roomy);
  grid-template-columns: auto 1fr auto;
  padding-block: var(--space-roomy);
  text-decoration: none; color: inherit;
}
.rowlist .rowlist-art { width: 4.5rem; flex: none; }
.rowlist .rowlist-art img { display: block; width: 100%; height: auto; }
.rowlist .rowlist-words { display: grid; gap: var(--space-tight); min-width: 0; }
/* Wide enough that the description reaches towards the price rather than
 * stopping halfway and leaving a corridor of nothing across the row. Still a
 * measure: past about 80 characters a line is hard to track back from. */
.rowlist .rowlist-words .t-small { max-width: 78ch; }
.rowlist .rowlist-amt { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Held on one line, "Saturday 31 October" or "60 min · $155" ran off the right
 * edge of a phone at 200% text (ECHOSTUDIO-762). The cell still gets its whole
 * line first, since an auto column is filled before the 1fr beside it; it only
 * wraps once the row can't hold it, which at normal sizes it always can. */
@media (max-width: 560px) { .rowlist .rowlist-amt { white-space: normal; } }
/* The right hand cell is a price almost everywhere, and a price that wraps
 * reads as two prices, hence the nowrap above. On the practitioners list it is
 * the days someone works, which is a sentence: "Tuesdays, Wednesdays and
 * Fridays, and alternate Saturdays" held on one line pushed a 390px page out
 * to 543px. This is the same cell, told it may wrap. */
.rowlist .rowlist-amt--words { white-space: normal; max-width: 20ch; }
.rowlist > li > a:hover .t-heading { text-decoration: underline; text-underline-offset: var(--space-tight); }
/* The drawing answers the pointer the way a photograph tile does on the home
 * page: a small lift and a touch larger, so a row reads as something to open
 * rather than a line of print. No cursor label here: on a photo tile it covers
 * a picture, on a row it sat over the description somebody was reading. */
.rowlist .rowlist-art img { transition: transform .5s var(--ease, ease); transform-origin: 50% 70%; }
.rowlist > li > a:hover .rowlist-art img { transform: translateY(-4px) scale(1.08) rotate(-2deg); }
@media (prefers-reduced-motion: reduce) {
  .rowlist .rowlist-art img, .rowlist > li > a:hover .rowlist-art img { transition: none; transform: none; }
}
/* Not every treatment has a drawing yet. The column is still reserved, so the
 * names down the list all start at the same place instead of stepping in and
 * out as the set fills up. */
.rowlist > li > a.no-art .rowlist-art { visibility: hidden; }
@media (max-width: 639px) {
  .rowlist > li > a { grid-template-columns: auto 1fr; }
  .rowlist .rowlist-amt { grid-column: 2; text-align: start; }
  .rowlist .rowlist-amt--words { max-width: none; }

}

/* ---------------------------------------------------------- where and when
 *
 * Address, hours and how to reach us, side by side across the page.
 *
 * The shared block rule sets `justify-items: start`, which is right for a block
 * whose content is one button but wrong here: it collapsed the whole thing to
 * the width of its longest line, so "Where and when" was a 233px column in the
 * middle of a 1440px page. These are three separate facts and they read better
 * as three columns than as one stack.
 */
.blk-where { justify-items: stretch; width: 100%; }
@media (min-width: 720px) {
  .blk-where { grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); align-items: start; }
  /* The heading introduces all three columns, so it takes the whole row. */
  .blk-where > :is(h2, .t-title, .t-heading, .sechead) { grid-column: 1 / -1; }
}
.blk-where address { font-style: normal; }
.blk-where .hours { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-tight); }
.blk-where .hours > li { display: grid; gap: var(--space-hair); }


/* The event rows are a .rowlist, which brings its own layout. The block only
 * has to stop the shared rule shrinking it to its content. */
.blk-events { justify-items: stretch; width: 100%; }

/* Inclusions are half a line each, so they read as columns rather than as one
 * narrow stack down the middle of a page that is mostly empty. */
.inclusions--cols { padding-left: 0; list-style: none; }
@media (min-width: 720px) {
  .inclusions--cols {
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--space-base) var(--space-block);
  }
}
.inclusions--cols > li { padding-left: var(--space-roomy); position: relative; }
.inclusions--cols > li::before {
  content: ""; position: absolute; left: 0; top: 0.65em;
  width: var(--space-tight); height: var(--space-hair);
  background: currentColor; opacity: .45;
}

/* ------------------------------------------------------------------ rail
 *
 * A column of facts beside a column of prose.
 *
 * Reading text has to keep a reading measure, so a section that is nothing but
 * a description sits at 740px with half the page empty beside it. The answer is
 * not to stretch the paragraph, it is to put something true in the space. Here
 * that is the things somebody scanning a retreat actually wants: when it runs,
 * what it costs, how long it is.
 */
.withrail { display: grid; gap: var(--space-block); align-items: start; }
@media (min-width: 900px) {
  /* The facts sit in the right hand column, which is where the paragraph
   * beside a section heading sits too, so the two openers on a page agree
   * with each other.
   *
   * It is also the only arrangement that holds up on a wide screen. With the
   * rail on the left in fixed proportions, the prose kept its reading measure
   * and everything to the right of it was empty: on a 2560px screen a
   * treatment's description ran from 24px to 1515px with a thousand pixels of
   * nothing after it. Now the prose starts at the left gutter and the rail
   * ends at the right one, so the section spans the page at any width.
   *
   * Placed explicitly rather than reordered, so the document order is
   * untouched and a screen reader still reads the facts before the
   * description. */
  .withrail { grid-template-columns: minmax(0, 1fr) auto; }
  .withrail > .rail { grid-column: 2; grid-row: 1; justify-self: end; min-width: 12rem; max-width: 24rem; }
  .withrail > .sys-prose { grid-column: 1; grid-row: 1; }
  /* An article: the byline in the heading column and the writing from the
   * grid line, so a post lines up with the opener above it. */
  .withrail--line { grid-template-columns: minmax(0, var(--head-col)) minmax(0, 1fr); column-gap: var(--space-block); }
  .withrail--line > .rail { grid-column: 1; justify-self: start; min-width: 0; }
  .withrail--line > .sys-prose { grid-column: 2; }
}
.withrail .rail, .masthead .rail { display: grid; gap: var(--space-roomy); align-content: start; }
/* In a masthead the rail is a stack of facts rather than a column beside
 * prose, so the rows are separated the way the fact bar's columns are. */
/* The facts are separated by space, not a rule. */
.masthead .rail > div + div {
  padding-block-start: var(--space-tight);
}
.masthead .rail > div { display: grid; gap: var(--space-tight); }
.masthead .rail dt, .masthead .rail dd { margin: 0; }
.withrail .rail > div { display: grid; gap: var(--space-hair); }
.withrail .rail dt, .withrail .rail dd { margin: 0; }


/* ==========================================================================
 * Devices.
 *
 * Each of these exists because some part of her content genuinely has that
 * shape, not because the page needed decoration. A ritual is an ordered
 * sequence, so it gets a numbered run with a rule through it. A retreat has
 * four facts everybody checks before reading a word, so they get a bar. A
 * section that has just made its case gets somewhere to go.
 * ========================================================================== */

/* -------------------------------------------------------------- masthead
 *
 * The top of a page: identity and the thing to do about it on one side, the
 * facts on the other.
 *
 * This is deliberately not the section head. A section head's heading is a
 * sentence that fills its column; an opener's heading is a name, and a name
 * next to a paragraph in the same layout leaves a screen of nothing between
 * them. Here the left column is the whole of the identity, stacked as it reads
 * aloud, and the right column is the facts, which is content rather than air.
 */
.masthead { display: grid; gap: var(--space-block); align-items: start; width: 100%; }
.masthead > .masthead-words { display: grid; gap: var(--space-roomy); align-content: start; justify-items: start; }
.masthead > .masthead-words > hgroup { display: grid; gap: var(--space-tight); }
.masthead .t-lede { max-width: 46ch; }
@media (min-width: 900px) {
  .masthead { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); column-gap: var(--space-block); }
}

/* The block wrapper: the heading, then the answers under it. */
.blk-notes { display: grid; gap: var(--space-block); width: 100%; }
.blk-notes > div { display: grid; gap: var(--space-snug); }

/* The portrait in a page opener. Four to five, the proportion a portrait has
 * been printed at for four hundred years, and bottom aligned with the words so
 * the name and the face sit on the same line. */
.masthead-art { margin: 0; justify-self: end; width: 100%; max-width: 32rem; }
.masthead-art img { display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
@media (min-width: 900px) {
  /* The name and the face sit on the same line, and the words take the room
   * they need rather than a fixed fraction: a portrait column and a paragraph
   * column with four hundred pixels of nothing between them is the fault this
   * layout was built to fix. */
  .masthead:has(.masthead-art) { align-items: end; grid-template-columns: minmax(0, 1fr) minmax(0, 32rem); }
  .masthead:has(.masthead-art) .t-lede { max-width: 54ch; }
}

/* ------------------------------------------------------------------ notes
 *
 * The parts of a long description, set beside each other instead of stacked.
 *
 * A retreat description is six paragraphs about six different things: who it
 * is for, the house, the mornings, the treatments, the food, and what to tell
 * us. Run together in one column it is a wall, and the questions inside it are
 * only findable by reading the whole thing. Given their own headings they are
 * answers, and they take the width of the page the way the rest of it does.
 *
 * Not numbered, and not ruled into one line like the arc. These are parts of a
 * thing rather than steps through it, and nothing is lost by reading the food
 * before the bedrooms.
 */
.notes { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-block); width: 100%; }
/* No rule above each answer (Phil, 17 Sep): the swatch and heading already
   start each one, and a line over every answer read as a form. */
.notes > li {
  display: grid; gap: var(--space-base); align-content: start;
}
.notes .t-body { max-width: 46ch; }
.notes .note-head { display: flex; align-items: center; gap: var(--space-base); }
.notes .note-head .t-heading { margin: 0; }
@media (min-width: 640px) {
  .notes { grid-template-columns: 1fr 1fr; column-gap: var(--space-block); }
}

/* ------------------------------------------------------------------ aboutgrid
 *
 * A heading and its opening paragraph on the left, the answers two by two on
 * the right. The left column is the page's grid line, the same one every
 * section head uses, and it stays in view while the answers scroll past it, so
 * the question the section is answering is never off screen.
 *
 * Built for "What it is" on a retreat, where the answers were six paragraphs
 * in one column: the page's empty space is on the left under the heading, on
 * purpose, rather than scattered through a wall of words.
 */
.aboutgrid { display: grid; gap: var(--space-block); width: 100%; align-items: start; }
.aboutgrid > .aboutgrid-head { display: grid; gap: var(--space-roomy); align-content: start; }
.aboutgrid > .aboutgrid-head .t-lede,
.aboutgrid > .aboutgrid-head .t-body { max-width: 42ch; }
@media (min-width: 900px) {
  .aboutgrid { grid-template-columns: minmax(0, var(--head-col)) minmax(0, 1fr); column-gap: var(--space-block); }
  .aboutgrid > .aboutgrid-head { position: sticky; top: calc(var(--head-h, 68px) + var(--space-roomy)); }
}
/* Whatever runs under it, the day by day arc, takes the full width again. */
.aboutgrid + .arc { margin-block-start: var(--space-block); }

/* ------------------------------------------------------------------ photorow
 *
 * Photographs side by side, three to a row, no captions. For a place: the house,
 * the room, the fire. They are proof, not links, so they do not move on hover.
 */
.photorow { display: grid; gap: var(--space-base); width: 100%; }
.photorow-im { border-radius: var(--radius-sm); overflow: hidden; aspect-ratio: 4 / 3; background: var(--rule-colour); }
.photorow-im img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 720px) { .photorow { grid-template-columns: repeat(3, 1fr); } }
/* A small photograph at its own size, centred in its column, not upscaled. */
.photorow-im--native { aspect-ratio: auto; background: none; justify-self: center; align-self: center; width: 100%; max-width: var(--native-w); }
.photorow-im--native img { height: auto; }
/* More than three (Marye, 5 Oct 2026: the Sacred Return and the cottages on
 * Personalised): rows of three that wrap, two a row on a phone, and a short
 * last row centred rather than left hanging against one edge. */
.photorow--many { display: flex; flex-wrap: wrap; justify-content: center; }
.photorow--many > .photorow-im { flex: 0 0 calc((100% - var(--space-base)) / 2); }
@media (min-width: 720px) { .photorow--many > .photorow-im { flex-basis: calc((100% - 2 * var(--space-base)) / 3); } }
.photorow--many > .photorow-im--native { flex: 0 1 var(--native-w); max-width: min(var(--native-w), calc((100% - var(--space-base)) / 2)); }

/* ------------------------------------------------------------ circlefeature
 *
 * A photograph in a large circle beside its words: the answer swatch at full
 * scale, so the inner pages share one signature shape. After August Health's
 * circular masks. Photographs only; a texture belongs in a swatch. The circle
 * sits on the page's grid line; the words take the other column.
 */
.circlefeature { display: grid; gap: var(--space-block); align-items: center; width: 100%; }
.circlefeature-art { margin: 0; justify-self: center; width: min(100%, 30rem); }
.circlefeature-art img {
  display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: 50%; background: var(--rule-colour);
}
.circlefeature-words { display: grid; gap: var(--space-roomy); align-content: center; }
.circlefeature-words .t-body, .circlefeature-words .t-lede { max-width: 54ch; }
@media (min-width: 900px) {
  .circlefeature { grid-template-columns: minmax(0, var(--head-col)) minmax(0, 1fr); column-gap: var(--space-block); }
  .circlefeature-art { justify-self: start; }
  /* Photograph on the right: the words take the wide column, so the pair
     doesn't leave a gap between a narrow column of text and the circle. */
  .circlefeature--right { grid-template-columns: minmax(0, 1fr) minmax(0, var(--head-col)); }
  .circlefeature--right .circlefeature-art { grid-column: 2; grid-row: 1; justify-self: end; }
  .circlefeature--right .circlefeature-words { grid-column: 1; grid-row: 1; }
}

/* The portrait variant (ECHOSTUDIO-207): upright, the small radius, the face
   kept in the top third. Narrower than the circle so it does not take over. */
.circlefeature--portrait .circlefeature-art { width: min(100%, 26rem); }
.circlefeature--portrait .circlefeature-art img {
  aspect-ratio: 4 / 5; border-radius: var(--radius-sm); object-position: 50% 25%;
}

/* ------------------------------------------------------------------ ttiles
 *
 * Options somebody chooses between: a gift, a membership, a rebate. Each is a
 * tinted tile with no border and no shadow, a large round texture, its name,
 * what it costs, one line, and where to go. After the tinted feature cards of
 * Function Health and Leandra Isler. The tile takes the other tone from its
 * section, so it lifts off paper and sinks into raised.
 */
.ttiles-wrap { display: grid; gap: var(--space-block); width: 100%; }
.ttiles { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-base); width: 100%; }
@media (min-width: 640px) { .ttiles { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); } }
.ttile {
  --tile-bg: var(--tone-raised-bg);
  background: var(--tile-bg); border-radius: 16px;
  padding: clamp(1.5rem, 2.4vw, 2.25rem);
  display: grid; grid-template-rows: auto auto auto 1fr auto; gap: var(--space-snug); align-content: start;
}
.tone-raised .ttile, .tone-sand .ttile { --tile-bg: var(--tone-paper-bg); }
.ttile-art { display: block; inline-size: 7rem; block-size: 7rem; border-radius: 50%; object-fit: cover; margin-block-end: var(--space-snug); background: var(--rule-colour); }
/* A drawing is not a swatch: it sits on the tile with no plate behind it and no
 * crop, because the cast shadow is part of the drawing. Pulled left by its own
 * optical margin, the way the treatment pages place them. */
.ttile-draw {
  display: block; inline-size: min(11rem, 70%); block-size: auto;
  margin-inline-start: -0.5rem; margin-block-end: var(--space-snug);
}
.ttile-price { font-variant-numeric: tabular-nums; }
/* Fixed rows, so a tile without a price keeps its words and button level with
 * the tile beside it instead of moving up one row. */
.ttile > .ttile-price { grid-row: 3; }
.ttile > .t-body, .ttile > span:not(.ttile-art) { grid-row: 4; }
.ttile > .ttile-link { grid-row: 5; }

/* The journal tiles under a section heading on a post: the heading already
 * separates them, and there are no hairlines above content. The layout gap
 * spaces them, so the older sheet's margin and padding go too. */
.sys-wrap > .jgrid { margin-block-start: 0; padding-block-start: 0; border-block-start: 0; }

/*
 * A short left column stays with its section.
 *
 * `.aboutgrid` has done this since it was built and it is right everywhere the
 * same shape appears: a heading, or a heading and a line, on the grid line with
 * something long beside it. Sticky costs nothing when the two columns are the
 * same height, so it is safe on every one of them.
 */
@media (min-width: 900px) {
  .sechead > .sechead-words,
  .blk-text--head > div:first-child,
  .circlefeature-words,
  .withrail--line > .rail {
    position: sticky;
    top: calc(var(--head-h, 68px) + var(--space-roomy));
  }
}
.ttile .t-body { max-width: 40ch; }
.ttile-link { justify-self: start; margin-block-start: var(--space-snug); }
/* A tile with two ways on: the button, and a quieter link beside it. */
.ttile-links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-snug) var(--space-base); }
.ttile-more { font-size: var(--text-small-size); color: inherit; text-decoration: underline; text-underline-offset: 0.2em; }
.ttile-more:hover { text-decoration-thickness: 2px; }

/* ------------------------------------------------------------------ figures
 *
 * A few numbers that show scale at a glance, in the display serif, each with a
 * small texture beside its label. Only facts: dates from her sources, counts
 * from Site settings.
 */
.figures { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-block) var(--space-base); width: 100%; }
@media (min-width: 640px) { .figures { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .figures { grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); } }
.figures > li { display: grid; gap: var(--space-snug); align-content: start; }
.figures-value {
  font-family: var(--text-display-family); font-weight: var(--text-display-weight);
  font-size: clamp(3rem, 6vw, 5rem); line-height: .95; letter-spacing: -.02em; font-variant-numeric: lining-nums;
}
.figures-label { display: flex; align-items: center; gap: var(--space-base); }
.figures-label .swatch { inline-size: 2.5rem; block-size: 2.5rem; }
.figures-label .t-body { max-width: 26ch; }

/* ------------------------------------------------------------------ topics
 *
 * Pill links that jump to the sections of a long page, each with its texture.
 * Anchored sections leave room for the sticky header.
 */
.topics { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-snug); }
.topics a {
  display: inline-flex; align-items: center; gap: .65rem; min-height: 3rem;
  padding: .35rem 1.1rem .35rem .35rem; border-radius: var(--radius-pill);
  background: var(--tone-raised-bg); color: inherit; text-decoration: none;
  transition: background .25s var(--ease, ease);
}
.tone-raised .topics a { background: var(--tone-paper-bg); }
.topics a:hover { background: var(--rule-colour); }
.topics .swatch { inline-size: 2.3rem; block-size: 2.3rem; }
[id].blk-faq { scroll-margin-top: calc(var(--head-h, 68px) + 1.5rem); }

/* ------------------------------------------------------------------ swatch
 *
 * A small round crop of one of the film stills, beside the name of a thing.
 *
 * Not a picture of the thing. "Food" is not a photograph of food and "The
 * house" is not the house: they are macro crops of clay, creek water, dry
 * grass and haze from the six stills the bands already use, so the set shares
 * one palette and one hand, the way Meadowell pair a symptom with a texture
 * rather than an illustration of it. They are decoration, so they carry no
 * alt text and are hidden from screen readers.
 */
.swatch {
  inline-size: 3.75rem; block-size: 3.75rem; flex: none; border-radius: var(--radius-pill);
  background-image: var(--sw);
  background-position: var(--sw-at);
  background-size: var(--sw-zoom);
  background-repeat: no-repeat;
  background-color: var(--rule-colour);
}
/* A generated texture of the answer's own: the image fills the circle. */
img.swatch--image { display: block; object-fit: cover; background: var(--rule-colour); }
.swatch--clay    { --sw: url("/assets/img/w/film-band-clay-800.webp");    --sw-at: 82% 72%; --sw-zoom: 700%; }
.swatch--pool    { --sw: url("/assets/img/w/film-band-pool-800.webp");    --sw-at: 52% 48%; --sw-zoom: 500%; }
.swatch--straw   { --sw: url("/assets/img/w/film-band-ridge-800.webp");   --sw-at: 35% 88%; --sw-zoom: 900%; }
.swatch--water   { --sw: url("/assets/img/w/film-band-river-800.webp");   --sw-at: 66% 74%; --sw-zoom: 700%; }
.swatch--haze    { --sw: url("/assets/img/w/film-band-ridge-800.webp");   --sw-at: 62% 36%; --sw-zoom: 900%; }
.swatch--tussock { --sw: url("/assets/img/w/film-band-tussock-800.webp"); --sw-at: 32% 62%; --sw-zoom: 550%; }
.swatch--mist    { --sw: url("/assets/img/w/film-band-river-800.webp");   --sw-at: 58% 18%; --sw-zoom: 650%; }
.swatch--meadow  { --sw: url("/assets/img/w/film-band-running-800.webp"); --sw-at: 8% 85%;  --sw-zoom: 650%; }

/* ---------------------------------------------------------------- eyebrow
 *
 * "02  PRACTITIONERS", the way the home page sets it: the number first in the
 * muted ink, the name of the section after it. It tells somebody where they
 * are in a page, which a bare label does not.
 */
.eyebrow { display: flex; align-items: baseline; gap: var(--space-snug); }
.eyebrow > .n { font-variant-numeric: tabular-nums; color: var(--muted, inherit); }

/* ------------------------------------------------------------------- arc
 *
 * An ordered run of steps with a rule through it and a dot on each one.
 *
 * For the things that really are sequences: a spa ritual is a foot soak, then
 * a massage, then a facial, then tea, in that order and no other; a retreat
 * runs Friday to Sunday; panchakarma has stages. Setting those as a bulleted
 * list throws away the one thing that matters most about them.
 *
 * The rule is carried on each step rather than the container, and the steps
 * are flush, so the segments join into one line across the page.
 */
.arc { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-block); width: 100%; }
.arc > li {
  display: grid; gap: var(--space-snug); align-content: start;
  padding-block-start: var(--space-roomy); position: relative;
  border-block-start: var(--space-hair) solid var(--rule-colour);
}
/* The dot sits on the rule, not under it. */
.arc > li::before {
  content: ""; position: absolute; inset-block-start: -0.3125rem; inset-inline-start: 0;
  inline-size: 0.5625rem; block-size: 0.5625rem; border-radius: var(--radius-pill);
  background: currentColor;
}
.arc .n { font-variant-numeric: tabular-nums; color: var(--muted, inherit); }
.arc .t-body { max-width: 42ch; }
@media (min-width: 900px) {
  /* No column gap, so the segments of rule join into one line across the page.
   * A row gap all the same: five steps on a 960px screen wrap to a second row,
   * and with gap:0 that row's rule was drawn straight through the last line of
   * the step above it. */
  .arc { grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); column-gap: 0; row-gap: var(--space-block); }
  .arc > li { padding-inline-end: var(--space-block); }
}

/* The same run of steps when there are a dozen of them rather than four, and
 * they are things included rather than things that happen in order: two
 * columns, the number against the left, still ruled and still counted. */
.arc--dense > li { grid-template-columns: auto 1fr; align-items: baseline; column-gap: var(--space-base); padding-block: var(--space-snug); }
.arc--dense > li::before { display: none; }
.arc--dense .t-body { max-width: 52ch; }
@media (min-width: 900px) {
  .arc--dense { grid-template-columns: 1fr 1fr; column-gap: var(--space-block); }
  .arc--dense > li { padding-inline-end: 0; }
}

/* ----------------------------------------------------------------- chips
 *
 * Short facts in a row, each in its own outline: twelve to thirty-six weeks,
 * two nights, all meals, sixteen places. They are read at a glance and never
 * in sentences, which is exactly what a list of them should look like.
 *
 * Square rather than a capsule. The rest of this design is nearly square and
 * that was a decision, so a row of lozenges would be a visitor from another
 * site.
 */
.chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-tight); }
.chips > li {
  border: var(--space-hair) solid var(--rule-colour);
  border-radius: var(--radius-sm);
  padding: var(--space-tight) var(--space-snug);
  font: var(--text-small-weight) var(--text-small-size)/1.2 var(--text-small-family);
}

/* --------------------------------------------------------------- factbar
 *
 * The four things somebody checks before they read anything: when, where, how
 * long, how much. Across the page under the opener, divided by hairlines.
 */
.factbar {
  display: grid; gap: var(--space-roomy); width: 100%;
  padding-block: var(--space-roomy);
}
.factbar > div { display: grid; gap: var(--space-tight); align-content: start; }
.factbar dt, .factbar dd { margin: 0; }
@media (min-width: 720px) {
  /* Packed from the left and capped, rather than stretched across the page.
     Two facts spread over 1440px put a hairline divider in the middle of
     nowhere with a screen between the label and the next one. */
  .factbar { grid-template-columns: repeat(auto-fit, minmax(11rem, 18rem)); justify-content: start; gap: 0; }
  .factbar > div + div {
    border-inline-start: var(--space-hair) solid var(--rule-colour);
    padding-inline-start: var(--space-roomy);
  }
  .factbar > div { padding-inline-end: var(--space-roomy); }
}

/* ---------------------------------------------------------------- ctarow
 *
 * A section that has made its case, and the thing to do about it.
 *
 * Every page used to keep all of its invitations for the very bottom, so a
 * reader convinced by the second section had nowhere to go but the scrollbar.
 */
.ctarow {
  display: grid; gap: var(--space-roomy); width: 100%;
  padding-block-start: var(--space-roomy);
}
.ctarow .t-body, .ctarow .t-lede { max-width: 58ch; }
@media (min-width: 900px) {
  .ctarow { grid-template-columns: 1fr auto; align-items: center; column-gap: var(--space-block); }
  .ctarow > .btn-cta { justify-self: end; }
}

/* A small picture at its own size, centred in its column, never bled to the
   edges or stretched to the height of the words (ECHOSTUDIO-207). */
.blk-split.blk-split--inset img,
.blk-split.blk-split--inset[data-side] img {
  justify-self: center; align-self: center;
  width: min(100%, var(--inset-w, 340px)); max-width: 100%;
  height: auto; min-height: 0; max-height: none; aspect-ratio: auto;
  margin: 0; border-radius: var(--radius-sm);
}
