/* ============================================================
   ELITE — a compositional visual system.
   Reads only the --e-* tokens the Design Plan emits (see
   app/rendering/elite/tokens.py). Scoped under body.elite so nothing
   here reaches a Basic/Standard/Pro page. Loaded after site-render.css,
   which supplies the infrastructure (editor chrome, lightbox, booking
   widget, cookie banner) and nothing of the look: every rule below that
   repeats a site-render selector is a deliberate override.
   ============================================================ */
/* No @layer: site-render.css is unlayered, and an unlayered rule beats
   any layered one regardless of specificity — body.elite scoping is
   what wins here, not cascade layers. */

  body.elite{font-family:var(--e-font-body);font-size:var(--e-body);line-height:1.55;
    background:var(--e-paper);color:var(--e-ink);-webkit-font-smoothing:antialiased;}
  /* Every viewport-relative length in this file is N * one of these. On a
     visitor's screen they are the real units. In the editor the iframe is
     as tall as the page it holds (editor-bridge.js reports the height and
     the dashboard sizes the frame to it), so a real vh there is a slice of
     the PAGE: a 58svh statement grew with the frame it grew, and a 334px
     paragraph sat centred in 3,006px. The editor instead tells the page
     the height of the screen the owner is designing for (--kd-vp: the same
     height Preview uses), so Edit, Preview and the live site resolve every
     one of these rules to the same pixels — no per-rule editor override
     that a more specific rule can outrank. */
  body.elite{--e-svh:1svh;--e-dvh:1dvh;--e-vh:1vh;}
  body.elite.is-editor-preview{--e-svh:calc(var(--kd-vp, 900px) / 100);--e-dvh:var(--e-svh);--e-vh:var(--e-svh);}
  body.elite h1,body.elite h2,body.elite h3{font-family:var(--e-font-display);font-weight:500;letter-spacing:-0.015em;line-height:1.05;text-wrap:balance;}
  body.elite p{max-width:var(--e-measure);}
  body.elite img{display:block;max-width:100%;height:auto;border-radius:var(--e-radius);}
  body.elite a{color:inherit;}
  body.elite main{display:block;}
  /* break-word, not anywhere: `anywhere` splits inside a word the moment
     it is convenient, and a headline reading "authen / tic Japane / se"
     is worse than a line that runs slightly long. A word only breaks now
     when it genuinely cannot fit on a line of its own. */
  /* Display type takes its measure and its step from its own length
     (see moves/_common.display_fit). One measure of 14ch is right for
     "Built, serviced, ridden" and wrong for "Property and residency
     law, in plain language", which it set as five stacked lines of two
     words each — a wall rather than an opening. */
  body.elite .e-display{font-size:calc(var(--e-display) * var(--e-display-step, 1));
    line-height:0.98;letter-spacing:-0.03em;font-weight:500;
    max-width:var(--e-display-measure, 14ch);overflow-wrap:break-word;}
  /* An image-dominant split gives the words a third of the width: the
     display step comes down to what that column can set on one line.
     The step still applies — this clamp used to replace the font-size
     outright, so display_fit's scaling by headline length was silently
     dropped inside a split, and a twenty-word headline set a 1050px
     wall that pushed the ask 380px below the fold. */
  /* ...but the viewport is not the column. This is the IMAGE-DOMINANT
     split: the words get four of twelve tracks, about 394px at 1440, and
     sizing from the viewport put 76px type in it. A ten-letter word does
     not fit that, and `overflow-wrap: break-word` then breaks it — measured
     live on a customer's home page, where "Madeira's Only Lebanese
     Restaurant" set as "Restauran / t" at the top of the first screen.
     The clamp keeps display_fit's scaling; `cqi` puts a ceiling on it that
     knows how wide the column actually is. */
  body.elite .e-split-4-8 .e-split-text .e-display{
    font-size:calc(min(clamp(2.2rem,1rem + 4.2vw,4.8rem), 13cqi) * var(--e-display-step, 1));}
  body.elite .e-h2{font-size:var(--e-h2);max-width:24ch;}
  body.elite .e-h3{font-size:var(--e-h3);font-family:var(--e-font-display);font-weight:500;}
  body.elite .e-lead{font-size:var(--e-lead);line-height:1.4;color:var(--e-ink);}
  body.elite .e-body{font-size:var(--e-body);}
  body.elite .e-body p+p{margin-top:0.9em;}
  body.elite .e-column .e-h2+.e-lead,body.elite .e-column .e-h2+.e-body,body.elite .e-column .e-lead+.e-body{margin-top:1.4rem;}
  body.elite .e-column .e-list,body.elite .e-column .e-quote:first-of-type,body.elite .e-column .e-faq:first-of-type{margin-top:2rem;}
  body.elite .e-eyebrow{font-size:var(--e-eyebrow);letter-spacing:var(--e-eyebrow-tracking);text-transform:var(--e-eyebrow-transform);
    color:var(--e-muted);margin-bottom:1.1rem;font-weight:500;}
  body.elite .e-label{font-size:var(--e-label);letter-spacing:0.06em;text-transform:uppercase;color:var(--e-muted);font-weight:500;}
  body.elite .e-caption{font-size:var(--e-caption);color:var(--e-muted);margin-top:0.75rem;}
  body.elite .e-note{font-size:var(--e-caption);color:var(--e-muted);border-top:1px solid var(--e-line);padding-top:0.6rem;margin-top:1.4rem;}
  /* The two controls. text-links sites never show .e-button outside a form. */
  body.elite .e-button,body.elite .btn-primary{display:inline-block;padding:0.95rem 1.6rem;background:var(--e-ink);color:var(--e-paper);
    text-decoration:none;font-family:var(--e-font-body);font-size:var(--e-body);font-weight:500;border:1px solid var(--e-ink);
    border-radius:var(--e-radius);cursor:pointer;
    transition:background-color 180ms ease,color 180ms ease,transform 160ms cubic-bezier(.23,1,.32,1);}
  /* Pressing is answered at once, on every device — the one state a
     phone can actually show. */
  body.elite .e-button:active,body.elite .btn-primary:active{transform:scale(0.97);}
  body.elite .e-link,body.elite .btn-secondary{display:inline-block;padding:0.3rem 0;background:none;border:0;color:var(--e-ink);
    text-decoration:none;font-weight:500;border-bottom:1px solid var(--e-ink);border-radius:0;font-size:var(--e-body);}
  /* A text link is still a target: 44px tall on a phone, the underline
     stays on the text, not on the padding. */
  body.elite .e-link{display:inline-flex;align-items:center;min-height:2.75rem;border-bottom:0;
    text-decoration:underline;text-underline-offset:0.35em;text-decoration-thickness:1px;}
  body.elite .e-brand{display:inline-flex;align-items:center;min-height:2.75rem;}
  body.elite .nav-toggle{min-height:2.75rem;min-width:2.75rem;justify-content:center;}
  body.elite .e-nav-links a{display:inline-flex;align-items:center;min-height:2.75rem;}
  body.elite .e-actions{display:flex;flex-wrap:wrap;gap:1.25rem 2rem;align-items:center;margin-top:2.2rem;}
  body.elite .e-stats{display:flex;flex-wrap:wrap;gap:2.5rem;margin-top:2.5rem;padding-top:1.25rem;border-top:1px solid var(--e-line);}
  body.elite .e-stats dt{font-family:var(--e-font-display);font-size:var(--e-h2);line-height:1;font-variant-numeric:tabular-nums;}
  body.elite .e-stats dd{font-size:var(--e-caption);color:var(--e-muted);margin-top:0.35rem;}
  /* Editor chrome inherits the ink so it stays visible on an inverse tone. */
  body.elite .editable-field:hover{outline-color:var(--e-accent);}
  body.elite .edit-add-btn,body.elite .edit-toggle{border-color:var(--e-line);color:var(--e-muted);background:transparent;font-family:var(--e-font-body);}
  body.elite .photo-upload-tile{border:1px dashed var(--e-line);border-radius:var(--e-radius);background:var(--e-surface);color:var(--e-muted);}

  /* Sections: padding from the module × the plan's pad; containers by class. */
  /* The air above and below a section are separate values, set by the
     join each side makes with its neighbour (see grammar.set_rhythm).
     One symmetric --e-pad per role gave a page five near-identical
     gaps, which is what "generated blocks stacked vertically" is. */
  body.elite .e-section{position:relative;
    padding-block:calc(var(--e-module) * var(--e-pad-top, var(--e-pad, 1)))
                  calc(var(--e-module) * var(--e-pad-bottom, var(--e-pad, 1)));
    padding-inline:var(--e-gutter);background:var(--e-paper);color:var(--e-ink);}
  /* ── One page, one left edge ──────────────────────────────────────
     Both containers used to centre their own content independently, so
     at 1440 a wide section began at 96px and a measure section at
     416px — 320px apart. A page of four sections had four left edges,
     and no amount of section-level polish can make that read as one
     designer's work; it is the single reason an Elite page looked like
     four.

     The page now has ONE column, the wide one, centred on the viewport.
     A measure section narrows its content INSIDE that column and starts
     where every other section starts — which is what the reference
     material does (one container, narrowing done by the grid inside
     it), and what any editorial page does. Centring is now something a
     move asks for (`.e-v-centred`), not something a container width
     causes by accident. */
  body.elite .e-section.e-container-measure,
  body.elite .e-section.e-container-wide{
    padding-inline:max(var(--e-gutter), calc((100% - var(--e-wide)) / 2));}
  body.elite .e-section.e-container-measure > *{max-width:var(--e-measure);margin-inline:0;}
  body.elite .e-section.e-container-wide > *{max-width:var(--e-wide);margin-inline:0;}
  /* The exception, asked for rather than inherited: a manifesto that
     genuinely wants the middle of the screen. Scale is NOT the ask — a
     hero with no photograph composes as statement:wordmark at
     monumental scale, and centring it on that basis put the opening of
     the page on a different axis from everything under it. */
  body.elite .e-v-centred > *{margin-inline:auto;text-align:center;}
  body.elite .e-section.e-container-full{padding-inline:0;}
  /* Text in a full-width section starts on the page's one left edge too;
     at the gutter it began 40px left of every other section at 1440. */
  body.elite .e-section.e-container-full > .e-column,body.elite .e-section.e-container-full > .e-statement{
    padding-inline:max(var(--e-gutter), calc((100% - var(--e-wide)) / 2));max-width:none;}
  body.elite .e-tone-inverse{--e-paper:var(--e-inv-paper);--e-ink:var(--e-inv-ink);--e-surface:var(--e-inv-surface);
    --e-line:var(--e-inv-line);--e-muted:var(--e-inv-muted);}
  /* --e-nav-h is how much of the first screen the navigation has
     already taken. A hero sized at a flat 100svh is a full viewport
     placed BELOW the nav, so it overflows by exactly the nav's height —
     and what falls off the bottom of a bleed is its lower-left text
     block, which is where the ask lives. On a wordmark nav (two rows,
     139px) the button sat 32px under the fold on every restaurant,
     salon and bakery: visible only to someone who already scrolled.
     Each nav mode declares its own height below. */
  body.elite .e-role-open{min-height:calc(calc(100 * var(--e-svh)) - var(--e-nav-h));display:flex;flex-direction:column;justify-content:center;}
  body.elite .e-role-open.e-move-bleed{min-height:calc(calc(100 * var(--e-svh)) - var(--e-nav-h));display:block;}
  body.elite .e-role-breathe{padding-block:0;}
  /* Sectional scale — the plan's second axis after padding. compact
     tightens the module, spacious and monumental claim screen height and
     centre their content in it, so the same ledger reads as a footnote
     or as a chapter depending on what the plan asked. */
  body.elite .e-scale-compact{
    padding-block:calc(var(--e-module) * var(--e-pad-top, var(--e-pad,1)) * .6)
                  calc(var(--e-module) * var(--e-pad-bottom, var(--e-pad,1)) * .6);}
  /* A screen-tall band is earned by a statement — words set as an object
     in space. Given to a column of text or a list it only centred a
     paragraph in 500px of nothing: the largest gaps on every page. */
  body.elite .e-scale-spacious.e-move-statement:not(.e-role-open){min-height:calc(58 * var(--e-svh));display:flex;flex-direction:column;justify-content:center;}
  body.elite .e-scale-monumental.e-move-statement:not(.e-role-open){min-height:calc(88 * var(--e-svh));display:flex;flex-direction:column;justify-content:center;}
  @media(max-width:719px){
    /* Claiming most of the screen is how a desktop page says "this
       matters". On a phone it says "scroll past this" — a section with
       three sentences in it took 88% of the viewport and read as an
       empty band. The scale keeps its typographic contrast; it stops
       buying height it has nothing to put in. */
    body.elite .e-scale-spacious:not(.e-role-open){min-height:0;}
    body.elite .e-scale-monumental:not(.e-role-open){min-height:calc(46 * var(--e-svh));}
  }
  body.elite .e-scale-spacious.e-move-bleed,body.elite .e-scale-monumental.e-move-bleed{display:block;min-height:0;}
  body.elite .e-scale-monumental .e-h2{font-size:var(--e-h1);}
  /* A phone's fixed action, from the plan's CTA policy. */
  body.elite .e-mobile-action{display:none;}
  /* Viewport heights in the editor: see --e-svh at the top. What stays
     editor-only is chrome, never geometry — no sticky stack (the frame does
     not scroll) and no phone's fixed action bar over the page. */
  body.elite.is-editor-preview .e-stack-cell{position:relative;}
  body.elite.is-editor-preview .e-mobile-action{display:none;}

  /* Navigation voices. */
  body.elite .e-nav{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
    padding:1.1rem max(var(--e-gutter), calc((100% - var(--e-wide)) / 2));background:color-mix(in srgb,var(--e-paper) 90%,transparent);backdrop-filter:blur(12px);
    border-bottom:var(--e-rule);}
  body.elite .e-brand{font-family:var(--e-font-display);font-size:1.25rem;font-weight:500;text-decoration:none;letter-spacing:-0.01em;}
  body.elite .e-nav-links{display:flex;align-items:center;gap:2rem;}
  body.elite .e-nav-links a{font-size:var(--e-caption);letter-spacing:0.04em;text-decoration:none;color:var(--e-ink);}
  body.elite .e-nav-links a.active{border-bottom:1px solid var(--e-ink);}
  body.elite .e-nav-num{font-variant-numeric:tabular-nums;color:var(--e-muted);margin-right:0.5rem;}
  body.elite .e-nav-action.e-button{padding:0.6rem 1.1rem;font-size:var(--e-caption);}
  body.elite.e-nav-wordmark .e-nav{flex-direction:column;gap:0.75rem;padding-block:1.4rem 1rem;}
  /* Measured, not guessed: 79px for one row, 139px for the wordmark's
     two, nothing at all when the nav floats over the opening. Keep
     these next to the padding rules that produce them. */
  body.elite{--e-nav-h:5rem;}
  body.elite.e-nav-wordmark{--e-nav-h:8.75rem;}
  body.elite.e-nav-overlay{--e-nav-h:0rem;}
  body.elite.e-nav-wordmark .e-brand{font-size:1.7rem;}
  body.elite.e-nav-split .e-nav{border-bottom:1px solid var(--e-line);}
  body.elite.e-nav-overlay .e-nav{position:fixed;left:0;right:0;background:transparent;backdrop-filter:none;border:0;
    --e-ink:var(--e-inv-ink);transition:background .35s var(--e-ease);}
  /* A transparent nav sits on whatever the opening is, and the hero's own
     scrim darkens only the bottom of the photograph — where its text is.
     Over a bright sky the links measured 1.00:1. A short band of shade
     under the nav keeps them legible on any picture, with or without
     script, and gives way to the solid nav once scrolled. */
  body.elite.e-nav-overlay .e-nav:not(.is-scrolled){background:linear-gradient(to bottom,rgba(0,0,0,.68),rgba(0,0,0,.58) 75%,rgba(0,0,0,0));}
  body.elite.e-nav-overlay .e-nav.is-scrolled{background:color-mix(in srgb,var(--e-inv-paper) 85%,transparent);backdrop-filter:blur(12px);}
  body.elite.e-nav-overlay main > .e-role-open:first-child{margin-top:0;}
  body.elite.e-nav-overlay main > :first-child:not(.e-move-bleed){padding-top:6rem;}
  body.elite .nav-toggle span{background:var(--e-ink);}

  /* Colophon: one line, no band. */
  body.elite .e-colophon{padding:calc(var(--e-module) * .5) max(var(--e-gutter), calc((100% - var(--e-wide)) / 2)) 2rem;border-top:1px solid var(--e-line);
    font-size:var(--e-caption);color:var(--e-muted);}
  body.elite .e-colophon-line{display:flex;flex-wrap:wrap;gap:0.5rem 2rem;align-items:baseline;}
  body.elite .e-colophon-name{font-family:var(--e-font-display);font-size:1.05rem;color:var(--e-ink);}
  /* 24px is the WCAG 2.5.8 floor for a target; the privacy link measured 23. */
  body.elite .e-colophon a{color:var(--e-muted);text-decoration:none;border-bottom:1px solid var(--e-line);
    display:inline-flex;align-items:center;min-height:1.5rem;}
  /* The shared skip link is white on --accent, and an Elite accent can be
     a light tone: measured 2.10:1 on the bakery. Ink on paper, inverted,
     is always legible and always the direction's own colours. */
  body.elite .skip-link{background:var(--e-ink);color:var(--e-paper);}
  body.elite .e-colophon-note{margin-top:1rem;font-size:0.78rem;}

  /* Infrastructure that must obey the palette. */
  body.elite .cookie-banner{background:var(--e-ink);color:var(--e-paper);}
  body.elite .mobile-fab .fab-call{background:var(--e-ink);color:var(--e-paper);border-radius:var(--e-radius);}
  body.elite .lightbox{background:color-mix(in srgb,#000 92%,transparent);}

  /* ---- column ---- */
  body.elite .e-column{max-width:var(--e-measure);}
  body.elite .e-role-open .e-column{max-width:min(var(--e-wide),100%);}
  body.elite .e-role-open .e-column .e-lead{max-width:var(--e-measure);margin-top:1.6rem;}
  body.elite .e-column-figure{margin-top:calc(var(--e-module) * .6);max-width:var(--e-narrow);position:relative;}
  body.elite .e-column-figure img{aspect-ratio:4/5;object-fit:cover;}
  body.elite .e-list{list-style:none;margin-top:2rem;border-top:1px solid var(--e-line);}
  body.elite .e-list-item{padding:1.4rem 0;border-bottom:1px solid var(--e-line);display:grid;grid-template-columns:minmax(0,1fr) auto;gap:0.4rem 2rem;}
  body.elite .e-list-title{font-family:var(--e-font-display);font-size:var(--e-h3);}
  body.elite .e-list-text{grid-column:1;color:var(--e-muted);}
  body.elite .e-list-meta{grid-column:2;grid-row:1;font-variant-numeric:tabular-nums;}
  body.elite .e-faq{border-bottom:1px solid var(--e-line);padding:1.1rem 0;}
  body.elite .e-faq summary{cursor:pointer;font-family:var(--e-font-display);font-size:var(--e-h3);list-style:none;display:flex;justify-content:space-between;gap:1rem;}
  body.elite .e-faq summary::-webkit-details-marker{display:none;}
  body.elite .e-faq summary::after{content:"+";color:var(--e-muted);}
  body.elite .e-faq[open] summary::after{content:"−";}
  body.elite .e-faq p{margin-top:0.8rem;color:var(--e-muted);}

  /* ---- statement ---- */
  /* `margin-inline:auto` on a flex item shrink-wraps it to its content
     and centres it — and .e-role-open is a flex column. So every
     statement-role opening, including an inner page's title, came out
     centred and narrow while the whole page under it was left-aligned:
     the one-axis rule broken by two words of CSS. The statement keeps
     its measure and starts where everything else starts; the outer
     centring on a very wide screen belongs to the container. */
  body.elite .e-statement{max-width:var(--e-wide);width:100%;margin-inline:0;}
  body.elite .e-statement-text{font-family:var(--e-font-display);font-size:var(--e-display);line-height:1.02;letter-spacing:-0.03em;
    font-weight:400;max-width:18ch;margin:0;text-wrap:balance;}
  body.elite .e-role-open .e-statement-text{max-width:12ch;}
  /* Statement scale is a composition parameter: monumental fills the
     width at the top of the ramp; narrow is an editorial column at h1. */
  body.elite .e-v-monumental .e-statement-text{font-size:clamp(2.6rem,1rem + 8vw,9rem);max-width:none;letter-spacing:-0.035em;}
  /* Sectional scale: a monumental statement and a closing statement
     occupy a screen's worth of height; a narrow one does not. */
  body.elite .e-v-monumental.e-section,body.elite .e-role-close.e-move-statement:is(.e-scale-spacious,.e-scale-monumental){min-height:calc(60 * var(--e-svh));display:flex;flex-direction:column;justify-content:center;}
  body.elite .e-role-open.e-v-monumental{min-height:calc(calc(100 * var(--e-svh)) - var(--e-nav-h));}
  /* An inner page's title is a title, not a hero. Composed as an
     "open" it inherited the full-screen minimum, so a page holding one
     word claimed the whole first viewport and its content began below
     the fold — which is what an owner sees the moment they add a page. */
  body.elite .e-role-open.e-v-page-title{min-height:0;}
  /* An inner page's name tells the visitor where they are; the home page's
     headline is the thesis. At display size "Services" was the loudest
     thing on a page whose job is the list under it. */
  body.elite .e-v-page-title .e-display{font-size:calc(clamp(2.4rem,1rem + 4vw,4.25rem) * var(--e-display-step, 1));}
  body.elite .e-v-page-title .e-statement-text{font-size:clamp(2.2rem,1rem + 5vw,5.5rem);max-width:20ch;}
  body.elite .e-v-narrow .e-statement{max-width:var(--e-measure);margin-inline:0;}
  body.elite .e-v-narrow .e-statement-text{font-size:var(--e-h1);max-width:none;line-height:1.1;}
  body.elite .e-v-pull-quote .e-statement-text{font-size:clamp(1.9rem,1rem + 3.2vw,4rem);max-width:26ch;font-style:italic;font-weight:400;}
  body.elite .e-v-pull-quote blockquote.e-statement-text::before{content:"\201C";margin-left:-0.45em;}
  body.elite .e-statement-body{margin-top:2rem;max-width:var(--e-measure);}
  body.elite .e-statement-attrib{margin-top:1.4rem;color:var(--e-muted);font-size:var(--e-caption);}
  body.elite .e-statement-sub{margin-top:1.5rem;font-size:var(--e-lead);max-width:var(--e-measure);}
  body.elite .e-role-close .e-statement{text-align:left;}
  body.elite .e-role-close .e-statement-text{font-size:clamp(2.2rem,1rem + 5vw,5.6rem);}

  /* ---- ledger ---- */
  body.elite .e-ledger-wrap{max-width:var(--e-wide);}
  body.elite .e-ledger-head{margin-bottom:calc(var(--e-module) * .35);display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:2rem;align-items:end;}
  body.elite .e-ledger-head .e-lead{grid-column:2;font-size:var(--e-body);color:var(--e-muted);max-width:var(--e-narrow);}
  body.elite .e-ledger{border-top:1px solid var(--e-line);}
  body.elite .e-ledger-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"index name price" "index desc desc";
    align-items:baseline;gap:0.2rem 1.25rem;padding:1.05rem 0;border-bottom:1px solid var(--e-line);}
  body.elite .e-ledger-index{grid-area:index;font-size:var(--e-label);letter-spacing:0.08em;color:var(--e-muted);min-width:2.5rem;font-variant-numeric:tabular-nums;}
  body.elite .e-ledger-name{grid-area:name;font-family:var(--e-font-display);font-size:var(--e-h3);}
  body.elite .e-ledger-leader{display:none;}
  body.elite .e-ledger-price{grid-area:price;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--e-ink);}
  /* Something on this list can be bought. One quiet mark of it, in the
     typography the composition already uses — never a button bolted on. */
  /* Premium is not invisible. A sellable line's action stays in the
     body face and stays small, but it is set in ink on a rule of its
     own colour, so the eye finds it on the first pass. */
  body.elite .kd-item-focus{box-shadow:0 0 0 2px var(--e-accent),0 0 0 8px rgba(0,0,0,0.06);border-radius:2px;}
  body.elite .e-offer-link{margin-left:0.7rem;font-family:var(--e-font-body);font-size:var(--e-caption);
    letter-spacing:0.06em;text-transform:uppercase;color:var(--e-ink);text-decoration:none;
    border-bottom:1px solid var(--e-ink);white-space:nowrap;
    display:inline-block;padding:0.35rem 0 0.2rem;position:relative;}
  /* "Book", "Buy now", "Ask about this" and the item names are the
     actions a customer came for, and they measured 31px and 24px tall on
     a phone. The hit area grows to 44px; the type and the rule under it
     do not move. The horizontal inset stays small so the name and its
     action, a few pixels apart on one row, never share a target. */
  body.elite .e-offer-link::after{content:"";position:absolute;inset:-7px -3px;}
  body.elite .e-item-link::after{content:"";position:absolute;inset:-11px -3px -12px;}
  body.elite .e-ledger-desc{grid-area:desc;color:var(--e-muted);font-size:var(--e-caption);max-width:var(--e-narrow);}
  body.elite .e-ledger-groups{border-top:0;display:grid;gap:calc(var(--e-module) * .6);}
  body.elite .e-ledger-two{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:calc(var(--e-gutter) * 1.5);}
  body.elite .e-ledger-title{font-size:var(--e-h2);margin-bottom:0.6rem;padding-bottom:0.6rem;border-bottom:1px solid var(--e-ink);}
  /* A ledger with no index: the same rows, without the column the
     numbers lived in — see _items_ledger's `numbered`. */
  body.elite .e-ledger-plain .e-ledger-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"name price" "desc desc";}
  body.elite .e-ledger-group .e-ledger-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"name price" "desc desc";}
  /* ── One offer, composed as one offer ────────────────────────────
     A ledger compares several things. With one row it is a one-line
     table under a heading, numbered "01" — which is what a business
     with a single service, the commonest shape there is, was getting.
     The one thing takes the room instead: its name at heading scale,
     its description at reading scale, and the price alone under a rule
     the width of the measure. */
  body.elite .e-spotlight{border-top:1px solid var(--e-ink);padding-top:1.6rem;max-width:var(--e-measure);}
  body.elite .e-spot-name{font-family:var(--e-font-display);font-size:var(--e-h1);line-height:1.05;
    letter-spacing:-0.015em;margin:0;}
  body.elite .e-spot-name .e-offer-link{font-size:var(--e-caption);margin-left:0.9rem;vertical-align:0.35em;}
  body.elite .e-spot-text{font-size:var(--e-lead);line-height:1.45;color:var(--e-muted);margin:1.1rem 0 0;
    max-width:var(--e-narrow);}
  body.elite .e-spot-foot{margin-top:1.6rem;padding-top:1rem;border-top:1px solid var(--e-line);}
  body.elite .e-spot-price{font-family:var(--e-font-display);font-size:var(--e-h3);
    font-variant-numeric:tabular-nums;}

  /* ── Stagger: an offer grid with no shared baseline ───────────────
     Alternate columns drop, so the eye travels diagonally instead of
     scanning a row, and nothing is in a box — the offset is the whole
     structure. Every other offer move Elite had was a list, a ledger
     or a grid of cards; this is the editorial arrangement it could not
     express.

     The drop is a margin, not a transform: a transform would leave the
     section's height measured from the un-offset row and open a gap
     under it. */
  body.elite .e-stagger-head{margin-bottom:calc(var(--e-module) * .45);max-width:var(--e-measure);}
  body.elite .e-stagger{display:grid;gap:clamp(2rem,4vw,3rem) clamp(1.5rem,3vw,2.5rem);}
  body.elite .e-stagger-cell{position:relative;padding-top:1.1rem;border-top:1px solid var(--e-ink);}
  body.elite .e-stagger-name{font-family:var(--e-font-display);font-size:var(--e-h3);line-height:1.12;
    letter-spacing:-0.01em;margin:0;}
  body.elite .e-stagger-name .e-offer-link{font-size:var(--e-caption);margin-left:0.6rem;vertical-align:0.3em;}
  body.elite .e-stagger-text{color:var(--e-muted);margin:0.8rem 0 0;}
  body.elite .e-stagger-meta{font-variant-numeric:tabular-nums;margin:1rem 0 0;}
  @media(min-width:760px){
    body.elite .e-stagger-3{grid-template-columns:repeat(3,minmax(0,1fr));}
    body.elite .e-stagger-4,body.elite .e-stagger-2{grid-template-columns:repeat(2,minmax(0,1fr));}
    body.elite .e-stagger-2 > :nth-child(2){margin-top:clamp(2.5rem,6vw,5rem);}
    /* Two columns on a tablet: the offset alternates by column, so it
       is the even CELL that drops, not every second one. */
    body.elite .e-stagger-4 > :nth-child(2n){margin-top:clamp(2.5rem,6vw,5rem);}
    body.elite .e-stagger-3 > :nth-child(3n-1){margin-top:clamp(2.5rem,6vw,5rem);}
    body.elite .e-stagger-3 > :nth-child(3n){margin-top:calc(clamp(2.5rem,6vw,5rem) * 2);}
  }
  @media(min-width:1080px){
    body.elite .e-stagger-4{grid-template-columns:repeat(4,minmax(0,1fr));}
    body.elite .e-stagger-4 > :nth-child(2n){margin-top:0;}
    body.elite .e-stagger-4 > :nth-child(even){margin-top:clamp(3rem,7vw,7rem);}
  }
  /* A phone has one column, so there is no offset to make — the rule
     above each cell keeps the rhythm instead. Stacking a staggered grid
     with its margins intact would just be a list with random gaps. */
  @media(max-width:759px){
    body.elite .e-stagger > *{margin-top:0 !important;}
    body.elite .e-stagger{gap:2rem;}
  }

  /* Two offers, equal and side by side — no index, because there is no
     sequence to keep your place in. */
  /* The shelf: a complete set of products, each with its photograph.
     Anatomy from the Figma Make portfolio example (Work.tsx): 3:4
     image, hairline, name and figure on one baseline. */
  body.elite .e-shelf{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    gap:clamp(2rem,4vw,3.25rem) clamp(0.9rem,2.5vw,2rem);}
  @media(min-width:720px){
    body.elite .e-shelf-3{grid-template-columns:repeat(3,minmax(0,1fr));}
    body.elite .e-shelf-4{grid-template-columns:repeat(4,minmax(0,1fr));}
  }
  body.elite .e-shelf-cell{min-width:0;}
  body.elite .e-shelf-figure{margin:0 0 0.9rem;aspect-ratio:3/4;overflow:hidden;background:var(--e-surface);}
  body.elite .e-shelf-figure a{display:block;height:100%;}
  body.elite .e-shelf-figure img{width:100%;height:100%;object-fit:cover;border-radius:0;
    transition:transform 700ms cubic-bezier(.25,1,.5,1);}
  body.elite .e-shelf-caption{display:flex;justify-content:space-between;align-items:baseline;gap:0.75rem;
    border-top:1px solid var(--e-line);padding-top:0.75rem;}
  body.elite .e-shelf-name{font-family:var(--e-font-display);font-size:var(--e-h3);line-height:1.15;margin:0;min-width:0;}
  /* The action sits under the name: a narrow cell has no room beside it. */
  body.elite .e-shelf-name .e-offer-link{display:block;width:max-content;margin:0.5rem 0 0;}
  body.elite .e-shelf-price{font-variant-numeric:tabular-nums;white-space:nowrap;}
  body.elite .e-shelf-text{color:var(--e-muted);font-size:var(--e-caption);margin:0.6rem 0 0;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
  body.elite .e-pair{display:grid;gap:clamp(1.75rem,4vw,3.5rem);border-top:1px solid var(--e-ink);padding-top:1.6rem;}
  @media(min-width:760px){body.elite .e-pair{grid-template-columns:repeat(2,minmax(0,1fr));}}
  body.elite .e-pair-name{font-family:var(--e-font-display);font-size:var(--e-h3);line-height:1.15;margin:0;}
  body.elite .e-pair-name .e-offer-link{font-size:var(--e-caption);margin-left:0.7rem;vertical-align:0.3em;}
  body.elite .e-pair-text{color:var(--e-muted);margin:0.7rem 0 0;max-width:34ch;}
  body.elite .e-pair-price{font-variant-numeric:tabular-nums;margin:0.9rem 0 0;padding-top:0.7rem;
    border-top:1px solid var(--e-line);}

  body.elite .e-ledger-figure{margin:0 0 1.2rem;max-width:22rem;position:relative;}
  body.elite .e-ledger-figure img{aspect-ratio:4/5;object-fit:cover;}
  body.elite .e-quote-row .e-ledger-name{font-family:var(--e-font-body);font-size:var(--e-body);font-style:italic;}
  body.elite .e-contact-row .e-ledger-name{font-family:var(--e-font-body);font-size:var(--e-body);}

  /* ---- quotes ---- */
  body.elite .e-quote{margin:0;padding:1.5rem 0;border-top:1px solid var(--e-line);}
  body.elite .e-quote blockquote{font-family:var(--e-font-display);font-size:var(--e-lead);line-height:1.3;max-width:var(--e-measure);}
  body.elite .e-quote-large blockquote{font-size:clamp(1.5rem,1rem + 2vw,2.6rem);}
  body.elite .e-quote figcaption{margin-top:1rem;font-size:var(--e-caption);color:var(--e-muted);display:flex;gap:0.75rem;}
  body.elite .e-rating{letter-spacing:0.1em;}

  /* ---- bleed ---- */
  body.elite .e-bleed{position:relative;margin:0;width:100%;}
  body.elite .e-bleed img.e-bleed-img,body.elite .e-bleed > img{width:100%;height:calc(calc(100 * var(--e-svh)) - var(--e-nav-h));max-height:1100px;object-fit:cover;border-radius:0;}
  body.elite .e-role-breathe .e-bleed > img{height:clamp(22rem,calc(70 * var(--e-vh)),52rem);}
  /* A bleed anywhere but the opening takes its proportion from the
     photograph, not from the viewport. "As tall as the screen" is a
     hero's privilege; used twice on one page it is just a wall. */
  body.elite .e-bleed-landscape img.e-bleed-img,body.elite .e-bleed-landscape > img{
    height:auto;aspect-ratio:16/9;max-height:min(calc(72 * var(--e-svh)),44rem);}
  body.elite .e-bleed-portrait img.e-bleed-img,body.elite .e-bleed-portrait > img{
    height:auto;aspect-ratio:4/5;max-height:min(calc(88 * var(--e-svh)),52rem);}
  body.elite .e-bleed-unknown img.e-bleed-img,body.elite .e-bleed-unknown > img{
    height:auto;aspect-ratio:3/2;max-height:min(calc(72 * var(--e-svh)),44rem);}
  @media(max-width:719px){
    /* A phone is portrait; a 16:9 band on it is a stripe. Every
       mid-page bleed comes back toward the square. */
    body.elite .e-bleed-landscape img.e-bleed-img,body.elite .e-bleed-landscape > img,
    body.elite .e-bleed-unknown img.e-bleed-img,body.elite .e-bleed-unknown > img{aspect-ratio:4/3;}
    body.elite .e-bleed-portrait img.e-bleed-img,body.elite .e-bleed-portrait > img{aspect-ratio:3/4;}
  }
  body.elite .e-scrim{position:absolute;inset:0;background:linear-gradient(to top,rgba(0,0,0,.62) 0%,rgba(0,0,0,.18) 45%,rgba(0,0,0,0) 70%);pointer-events:none;}
  body.elite .e-bleed-text{position:absolute;left:max(var(--e-gutter), calc((100% - var(--e-wide)) / 2));right:max(var(--e-gutter), calc((100% - var(--e-wide)) / 2));bottom:clamp(2rem,calc(7 * var(--e-vh)),5rem);color:#fff;--e-ink:#fff;--e-muted:rgba(255,255,255,.75);--e-line:rgba(255,255,255,.35);}
  /* Over a photograph the measure comes in a step — the words have to
     hold together against what is behind them — but still follows the
     headline's own length rather than being fixed at twelve. */
  body.elite .e-bleed-text .e-display{max-width:calc(var(--e-display-measure, 14ch) * 0.85);
    text-shadow:0 1px 24px rgba(0,0,0,.25);}
  body.elite .e-bleed-text .e-lead{margin-top:1.2rem;max-width:var(--e-narrow);}
  body.elite .e-bleed-text .e-link{border-bottom-color:#fff;color:#fff;}
  body.elite .e-bleed-text .e-button{background:#fff;color:#111;border-color:#fff;}
  body.elite .e-bleed-contact{display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));gap:1.5rem;}
  body.elite .e-contact-line .e-label{display:block;margin-bottom:0.3rem;color:rgba(255,255,255,.7);}
  body.elite .e-bleed .e-caption{padding:0.75rem var(--e-gutter) 0;}
  body.elite.e-img-framed .e-role-breathe .e-bleed{padding-inline:var(--e-img-frame);}
  body.elite.e-img-grain .e-bleed::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:var(--e-img-grain);mix-blend-mode:multiply;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.6'/%3E%3C/svg%3E");}

  /* ---- split ---- */
  body.elite .e-split{display:grid;gap:calc(var(--e-gutter) * 1.2);align-items:center;}
  /* The headline lives in a column that can be a third of the screen, but
     --e-display is scaled off the viewport, so on a wide monitor a 5fr
     column got 130px type and "authentic" had nowhere to go. Sized off
     the column itself now: 15cqi fits a thirteen-letter word, and the
     viewport-based size still wins whenever it is the smaller of the two. */
  body.elite .e-split-text{container-type:inline-size;}
  /* Every override of the display size has to keep the step, or
     display_fit's scaling by headline length is silently dropped
     exactly where headlines are longest — inside a split. */
  body.elite .e-split-text .e-display{font-size:calc(min(var(--e-display),13cqi) * var(--e-display-step, 1));}
  body.elite .e-split-5-7{grid-template-columns:minmax(0,5fr) minmax(0,7fr);}
  body.elite .e-split-4-8{grid-template-columns:minmax(0,4fr) minmax(0,8fr);}
  body.elite .e-split-6-6{grid-template-columns:repeat(2,minmax(0,1fr));}
  body.elite .e-split-7-5{grid-template-columns:minmax(0,7fr) minmax(0,5fr);}
  body.elite .e-split-image-first .e-split-figure{order:-1;}
  @media (min-width:1024px){
    /* One composition, not a picture beside a paragraph: the words sit on
       the photograph's lower edge, so the two share an axis. */
    body.elite .e-role-open .e-split{align-items:end;}
    body.elite .e-role-open .e-split .e-split-text{padding-bottom:clamp(1rem,3vw,2.5rem);}
    /* A story beside the width it has: heading and eyebrow in one column,
       the words in the next, instead of a 38rem column and 60% of empty
       page to its right. */
    body.elite .e-role-anchor.e-move-column.e-container-measure > .e-column{max-width:var(--e-wide);display:grid;
      grid-template-columns:minmax(0,5fr) minmax(0,6fr);column-gap:calc(var(--e-gutter) * 1.5);align-items:start;}
    body.elite .e-role-anchor.e-move-column > .e-column > *{grid-column:2;}
    body.elite .e-role-anchor.e-move-column > .e-column > :is(.e-eyebrow,h2,.e-h2){grid-column:1;}
  }
  body.elite .e-split-8-4{grid-template-columns:minmax(0,8fr) minmax(0,4fr);}
  body.elite .e-split-image-first.e-split-4-8{grid-template-columns:minmax(0,8fr) minmax(0,4fr);}
  body.elite .e-split-image-first.e-split-8-4{grid-template-columns:minmax(0,4fr) minmax(0,8fr);}
  /* Offset: the text column starts a third of the way down its track —
     an editorial stagger instead of a centred pair. Top: both columns
     hang from the same line, the architectural reading. */
  body.elite .e-split-offset{align-items:start;}
  body.elite .e-split-offset .e-split-text{padding-top:clamp(3rem,calc(14 * var(--e-vh)),9rem);}
  body.elite .e-split-top{align-items:start;}
  body.elite .e-split-8-4 .e-split-figure img,body.elite .e-split-image-first.e-split-8-4 .e-split-figure img{aspect-ratio:3/4;}
  body.elite .e-split-image-first.e-split-5-7{grid-template-columns:minmax(0,7fr) minmax(0,5fr);}
  body.elite .e-split-image-first.e-split-4-8{grid-template-columns:minmax(0,8fr) minmax(0,4fr);}
  body.elite .e-split-figure{margin:0;position:relative;}
  body.elite .e-split-figure img{width:100%;aspect-ratio:4/5;object-fit:cover;}
  body.elite .e-role-open .e-split-figure img{aspect-ratio:5/6;max-height:calc(82 * var(--e-svh));}
  body.elite .e-role-locate .e-split-figure img{aspect-ratio:3/2;}
  body.elite .e-split-text .e-lead{margin-top:1.4rem;}
  body.elite .e-split-text .e-body{margin-top:1.4rem;}
  body.elite .e-split-collapsed .e-column{max-width:var(--e-measure);}
  body.elite .e-split-duo figure{margin:0;}
  body.elite .e-split-duo img{aspect-ratio:4/5;object-fit:cover;width:100%;}
  body.elite .e-split-head{margin-bottom:calc(var(--e-module) * .35);}
  body.elite .e-quote-small{border-top:0;}
  body.elite .e-contact-list{margin-top:1.8rem;display:grid;gap:1rem;}
  body.elite .e-contact-list dt{margin-bottom:0.25rem;}
  body.elite.e-img-framed .e-split-figure{padding:var(--e-img-frame);background:var(--e-surface);}

  /* ---- overlap ---- */
  body.elite .e-overlap{position:relative;display:grid;grid-template-columns:repeat(12,1fr);align-items:center;min-height:calc(70 * var(--e-svh));}
  body.elite .e-overlap-field{grid-column:1/8;grid-row:1;height:100%;background:var(--e-surface);}
  body.elite .e-overlap-figure{grid-column:5/11;grid-row:1;margin:0;z-index:1;}
  body.elite .e-overlap-figure img{aspect-ratio:4/5;object-fit:cover;width:100%;}
  body.elite .e-overlap-text{grid-column:1/7;grid-row:1;z-index:2;padding:var(--e-gutter);mix-blend-mode:normal;}
  body.elite .e-overlap-extra{grid-column:10/13;grid-row:1;align-self:end;margin:0 0 -3rem;z-index:1;}

  /* ---- strip ---- */
  /* width:100% is load-bearing. `margin:0 auto` on a flex item
     shrink-wraps it to its content and centres that — and the opening
     role is a flex column, so a stacked opening's headline sat in the
     middle of a page whose every other line is on the left edge. Same
     bug, same fix, as .e-statement. */
  body.elite .e-show-head,body.elite .e-rows-head{padding-inline:var(--e-gutter);max-width:var(--e-wide);width:100%;margin:0 auto calc(var(--e-module) * .35);}
  body.elite .e-container-wide .e-show-head,body.elite .e-container-wide .e-rows-head{padding-inline:0;}
  /* The stacked opening: the headline stands on its own line of the
     page, the sequence begins under it. Left, not centred — one axis,
     the same one every other opening uses. */
  body.elite .e-show-head-open{margin:calc(var(--e-module) * .5) auto calc(var(--e-module) * .55);}
  body.elite .e-show-head-open .e-actions{margin-top:calc(var(--e-module) * .3);}
  body.elite .e-role-open.e-move-stack{justify-content:flex-start;min-height:0;}
  body.elite .e-strip{display:flex;gap:var(--e-gutter);overflow-x:auto;scroll-snap-type:x mandatory;padding-inline:var(--e-gutter);
    scrollbar-width:none;-webkit-overflow-scrolling:touch;}
  body.elite .e-strip::-webkit-scrollbar{display:none;}
  body.elite .e-strip-cell{flex:0 0 auto;scroll-snap-align:start;}
  body.elite .e-strip-cell .e-photo img{height:clamp(18rem,calc(58 * var(--e-vh)),40rem);width:auto;object-fit:cover;}
  body.elite .e-strip-cell .e-photo.e-o-portrait img{aspect-ratio:4/5;}
  body.elite .e-strip-card{width:min(22rem,78vw);}
  body.elite .e-strip-card .e-photo img{width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;}
  body.elite .e-strip-card .e-h3{margin-top:1rem;}
  body.elite .e-strip-items{list-style:none;margin-top:0.6rem;}
  /* baseline, not stretch: a row carrying a "Buy now" link is taller, and its price floated above the name. */
  body.elite .e-strip-items li{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;padding:0.4rem 0;border-bottom:1px solid var(--e-line);font-size:var(--e-caption);}

  /* ---- stack ---- */
  body.elite .e-stack{display:grid;}
  body.elite .e-stack-cell{position:sticky;top:0;}
  body.elite .e-stack-cell .e-photo{margin:0;}
  body.elite .e-stack-cell img{width:100%;height:calc(92 * var(--e-svh));object-fit:cover;border-radius:0;}

  /* ---- mosaic ---- */
  body.elite .e-mosaic{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(12rem,22vw);grid-auto-flow:dense;gap:clamp(0.6rem,1.4vw,1.4rem);}
  body.elite .e-mosaic-triptych{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:minmax(16rem,34vw);}
  body.elite .e-mosaic-triptych .e-span-2x1{grid-column:span 2;}
  body.elite .e-mosaic-cell{position:relative;min-width:0;}
  body.elite .e-mosaic-cell .e-photo,body.elite .e-mosaic-cell a{display:block;height:100%;margin:0;}
  body.elite .e-mosaic-cell img{width:100%;height:100%;object-fit:cover;}
  body.elite .e-span-2x2{grid-column:span 2;grid-row:span 2;}
  body.elite .e-span-2x1{grid-column:span 2;}
  body.elite .e-span-1x2{grid-row:span 2;}
  /* A gallery of one photograph: the pattern asks for the whole row, and
     without this rule the cell took one column of four — a quarter-width
     square crop beside three empty columns. */
  body.elite .e-span-4x2{grid-column:1 / -1;grid-row:span 2;}
  body.elite .e-mosaic-triptych .e-span-2x2{grid-column:span 2;grid-row:span 1;}
  body.elite .e-photo{margin:0;position:relative;}
  /* Mosaic character: editorial keeps air between framed cells and a
     text cell; sparse is two or three cells with the grid's whitespace
     doing the composing. */
  body.elite .e-v-editorial .e-mosaic{gap:clamp(1.5rem,4vw,4rem);grid-auto-rows:minmax(12rem,18vw);}
  body.elite .e-v-sparse .e-mosaic{grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(2rem,6vw,6rem);grid-auto-rows:minmax(14rem,26vw);}
  body.elite .e-v-sparse .e-mosaic-cell:nth-child(n+3){display:none;}
  body.elite .e-v-sparse .e-mosaic-cell:nth-child(2){grid-column:2 / span 2;margin-top:clamp(2rem,calc(8 * var(--e-vh)),6rem);}
  body.elite .e-v-sparse .e-span-2x2,body.elite .e-v-sparse .e-span-2x1{grid-column:span 2;grid-row:span 1;}
  body.elite .e-v-sparse .e-span-1x2,body.elite .e-v-sparse .e-span-1x1{grid-column:span 1;grid-row:span 1;}
  body.elite.e-img-framed .e-mosaic-cell{padding:calc(var(--e-img-frame) * .35);background:var(--e-surface);}

  /* ---- rows ---- */
  body.elite .e-rows{display:grid;gap:calc(var(--e-module) * .7);}
  body.elite .e-rows-row{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:var(--e-gutter);align-items:center;}
  body.elite .e-rows-right .e-rows-figure{order:2;}
  body.elite .e-rows-figure{margin:0;position:relative;}
  body.elite .e-rows-figure img{width:100%;aspect-ratio:5/4;object-fit:cover;}
  body.elite .e-rows-noimg{grid-template-columns:minmax(0,1fr);}

  /* ---- cards (pricing only) ---- */
  body.elite .e-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:0;border:1px solid var(--e-line);}
  body.elite .e-card{padding:2rem;border-right:1px solid var(--e-line);}
  body.elite .e-card:last-child{border-right:0;}
  body.elite .e-card-featured{background:var(--e-ink);color:var(--e-paper);--e-line:var(--e-inv-line);--e-muted:var(--e-inv-muted);}
  body.elite .e-price{font-family:var(--e-font-display);font-size:var(--e-h2);margin:0.6rem 0 1rem;font-variant-numeric:tabular-nums;}
  body.elite .e-features{list-style:none;}
  body.elite .e-features li{padding:0.5rem 0;border-top:1px solid var(--e-line);font-size:var(--e-caption);}

  /* ---- grid-lines ---- */
  body.elite .e-move-grid-lines{overflow:hidden;}
  body.elite .e-grid{position:absolute;inset:0 var(--e-gutter);display:grid;grid-template-columns:repeat(12,1fr);pointer-events:none;max-width:var(--e-wide);margin-inline:auto;}
  body.elite .e-grid i{border-left:1px solid var(--e-line);}
  body.elite .e-grid i:last-child{border-right:1px solid var(--e-line);}
  body.elite .e-grid-content{position:relative;display:grid;grid-template-columns:repeat(12,1fr);gap:0 1rem;align-items:end;max-width:var(--e-wide);margin-inline:auto;width:100%;padding-inline:var(--e-gutter);}
  /* 1/-1, not 1/13: on a phone the grid has four columns, and a span to
     line 13 added eight implicit ones — with their gaps, the headline, facts
     and actions of a no-photo opening sat in a 207px column of 335. */
  body.elite .e-grid-content .e-eyebrow{grid-column:1/-1;}
  /* Sized to its nine-column span, not the viewport: at the full display
     size an eight-word headline took five lines of an 848px column. */
  body.elite .e-grid-content .e-display{grid-column:1/10;max-width:none;font-weight:700;letter-spacing:-0.04em;
    font-size:calc(min(var(--e-display), 7vw) * var(--e-display-step, 1));}
  body.elite .e-grid-facts,body.elite .e-grid-lead{grid-column:10/13;align-self:end;padding-bottom:0.5rem;}
  body.elite .e-grid-facts div{padding:0.6rem 0;border-top:1px solid var(--e-line);}
  body.elite .e-grid-facts dt{font-family:var(--e-font-display);font-size:var(--e-h3);}
  body.elite .e-grid-facts dd{font-size:var(--e-caption);color:var(--e-muted);}
  body.elite .e-grid-content .e-actions{grid-column:1/-1;border-top:1px solid var(--e-ink);padding-top:1.2rem;margin-top:2.5rem;}
  body.elite .e-grid-lead{font-size:var(--e-body);color:var(--e-muted);}

  /* ---- widget ---- */
  body.elite .e-widget{display:grid;gap:calc(var(--e-gutter) * 1.5);max-width:var(--e-wide);}
  body.elite .e-widget-with-aside{grid-template-columns:minmax(0,5fr) minmax(0,7fr);align-items:start;}
  body.elite .e-section.e-container-measure > .e-widget-with-aside{max-width:min(64rem,100%);}
  body.elite .e-section.e-container-measure > .e-ledger-wrap{max-width:min(56rem,100%);}
  /* A shelf is pictures side by side: it takes the page's wide column,
     not the reading measure a ledger of names needs, and the ledger's
     own top rule goes — each caption already carries one. */
  body.elite .e-section.e-container-measure > .e-ledger-wrap:has(.e-shelf){max-width:var(--e-wide);}
  body.elite .e-ledger:has(> .e-shelf){border-top:0;}
  body.elite .e-widget-aside{margin-top:2rem;}
  /* Head and action belong together: the column gap was also the gap from
     a heading to its own button. */
  body.elite .e-widget{row-gap:clamp(1.25rem,2.5vw,2rem);}
  body.elite .e-widget-head .e-h2+.e-lead{margin-top:1rem;}
  /* A ledger whose page title already named it has only a lead; in the
     second column it floated 400px right of the rows it introduces. */
  body.elite .e-ledger-head > .e-lead:only-child{grid-column:1 / -1;}
  body.elite .e-form{display:grid;gap:1.4rem;max-width:var(--e-measure);}
  body.elite .e-field{display:grid;gap:0.4rem;font-size:var(--e-label);letter-spacing:0.06em;text-transform:uppercase;color:var(--e-muted);}
  body.elite .e-field input,body.elite .e-field textarea,body.elite .booking-widget-card input,body.elite .booking-widget-card select{
    font:inherit;font-size:var(--e-body);letter-spacing:0;text-transform:none;color:var(--e-ink);background:transparent;border:0;
    border-bottom:1px solid var(--e-line);border-radius:0;padding:0.7rem 0;outline:none;width:100%;}
  body.elite .e-field input:focus,body.elite .e-field textarea:focus{border-bottom-color:var(--e-ink);}
  body.elite .e-form .e-button{justify-self:start;margin-top:0.5rem;}
  body.elite .booking-widget-card{border:0;padding:0;background:transparent;box-shadow:none;max-width:var(--e-measure);}
  body.elite .booking-widget-card label{display:grid;gap:0.4rem;font-size:var(--e-label);letter-spacing:0.06em;text-transform:uppercase;color:var(--e-muted);margin-bottom:1.2rem;}
  body.elite .booking-widget-card .btn-secondary{margin-top:0.4rem;font:inherit;}
  body.elite .booking-slot-btn{border:1px solid var(--e-line);background:transparent;color:var(--e-ink);border-radius:var(--e-radius);padding:0.5rem 0.8rem;margin:0.25rem 0.4rem 0.25rem 0;font:inherit;cursor:pointer;}
  body.elite .booking-slot-btn.is-selected{background:var(--e-ink);color:var(--e-paper);}
  body.elite .booking-widget-placeholder{border:1px dashed var(--e-line);padding:2rem;color:var(--e-muted);border-radius:var(--e-radius);}
  body.elite .lead-form-status,body.elite .booking-status{font-size:var(--e-caption);color:var(--e-muted);}
  body.elite .booking-slots-message:empty,body.elite .booking-slots:empty{display:none;}
  body.elite .booking-status:empty{margin:0;}
  /* The WhatsApp agreements are sentences the customer reads before ticking
     — not field labels: sentence case, a real checkbox, nothing uppercase. */
  body.elite .booking-consent{border:0;margin:0 0 1.2rem;padding:0;min-width:0;}
  body.elite .booking-consent legend{font-size:var(--e-label);letter-spacing:0.06em;text-transform:uppercase;color:var(--e-muted);padding:0;margin-bottom:0.6rem;}
  body.elite .booking-widget-card .booking-consent-option{display:flex;align-items:flex-start;gap:0.6rem;font-size:var(--e-body);letter-spacing:0;text-transform:none;color:var(--e-ink);margin-bottom:0.6rem;line-height:1.45;}
  body.elite .booking-widget-card .booking-consent-option input{width:1.05rem;height:1.05rem;flex:none;margin:0.2rem 0 0;padding:0;border:1px solid var(--e-line);accent-color:var(--e-ink);}
  body.elite .booking-consent-note{margin:0;font-size:var(--e-caption);color:var(--e-muted);}

  /* ---- before/after in the elite frame ---- */
  body.elite .before-after-grid{display:grid;gap:var(--e-gutter);grid-template-columns:repeat(auto-fit,minmax(20rem,1fr));}
  body.elite .before-after-card{background:transparent;border:0;box-shadow:none;padding:0;}

  @media (max-width:1024px){
    /* Display type in a split's text column: the column is ~300px on a
       tablet and a single word at 9vw will not fit. Even columns, and
       the ramp steps down. */
    body.elite .e-role-open .e-split{grid-template-columns:repeat(2,minmax(0,1fr)) !important;}
    body.elite .e-split .e-display{font-size:calc(clamp(2.2rem,1rem + 5vw,5rem) * var(--e-display-step, 1));}
    body.elite .e-ledger-two{grid-template-columns:minmax(0,1fr);}
    body.elite .e-overlap-figure{grid-column:4/12;}
    body.elite .e-overlap-text{grid-column:1/8;}
    body.elite .e-mosaic{grid-auto-rows:minmax(10rem,26vw);}
  }
  @media (max-width:760px){
    /* 60svh is how a desktop close says "this is the end"; on a phone it
       left 150px of blank page under a two-line invitation. */
    body.elite .e-v-monumental.e-section:not(.e-role-open),body.elite .e-role-close.e-move-statement{min-height:0;}
    /* A testimony row on a phone: the quote first, full width, its author
       under it. As two columns the author ("Local homeowner, Roanoke
       area") took the auto column and the quote was set one word a line
       in what was left — measured on a fresh production site. */
    body.elite .e-quote-row{grid-template-columns:minmax(0,1fr) !important;grid-template-areas:"name" "index" !important;}
    body.elite .e-quote-row .e-ledger-index{min-width:0;margin-top:0.4rem;}
    body.elite .e-display{font-size:calc(clamp(2.4rem,9.5vw,3.8rem) * var(--e-display-step, 1));max-width:none;}
    body.elite .e-statement-text{font-size:clamp(2rem,8.5vw,3.4rem);max-width:none;}
    body.elite .e-role-close .e-statement-text{font-size:clamp(1.9rem,7.5vw,3rem);}
    body.elite .e-role-open{min-height:auto;padding-block:calc(var(--e-module) * .8);}
    body.elite .e-role-open.e-move-bleed{min-height:calc(100 * var(--e-svh));padding:0;}
    /* split: image first for open/locate, text first for a story; the
       image becomes a wide 4:3 rather than a tall portrait. */
    /* The opening's selector too: the tablet rule above is more specific
       (.e-role-open .e-split, also !important) and both media queries
       apply on a phone, so an opening split stayed two columns at 375 and
       set a nine-word headline in a 155px column, six lines tall. */
    body.elite .e-split,body.elite .e-role-open .e-split{grid-template-columns:minmax(0,1fr) !important;gap:1.6rem;}
    body.elite .e-split-text-first .e-split-figure{order:2;}
    body.elite .e-split-figure img,body.elite .e-role-open .e-split-figure img{aspect-ratio:4/3;max-height:none;}
    body.elite .e-split-duo{grid-template-columns:repeat(2,minmax(0,1fr)) !important;gap:0.6rem;}
    /* ledger: the price wraps under the name; the index stays. */
    body.elite .e-ledger-head{grid-template-columns:minmax(0,1fr);}
    body.elite .e-ledger-head .e-lead{grid-column:1;}
    body.elite .e-ledger-row{grid-template-columns:auto minmax(0,1fr);grid-template-areas:"index name" "index price" "index desc";}
    body.elite .e-ledger-group .e-ledger-row{grid-template-columns:minmax(0,1fr);grid-template-areas:"name" "price" "desc";}
    /* mosaic reflows to a strip: the phone gets the sequence, not a
       grid of thumbnails. */
    body.elite .e-mosaic,body.elite .e-mosaic-triptych{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;gap:0.75rem;scrollbar-width:none;grid-auto-rows:auto;}
    body.elite .e-mosaic-cell{flex:0 0 80vw;scroll-snap-align:start;height:auto;}
    body.elite .e-mosaic-cell img{height:60vw;aspect-ratio:auto;}
    body.elite .e-strip-cell .e-photo img{height:60vw;}
    body.elite .e-stack-cell{position:relative;}
    /* except in an opening, where the whole point is that the first
       photograph is held while the next arrives over it. A phone that
       scrolls three full-height pictures in a row reads as a wall. */
    body.elite .e-role-open .e-stack-cell{position:sticky;top:0;}
    /* A gallery page takes its whole pool, and seven photographs at 68svh
       each stacked into a 4560px wall on a phone (measured on two fresh
       production sites). Past three, a showing stack becomes a two-up
       grid there; the opening keeps its sequence. */
    body.elite .e-role-show .e-stack:has(> :nth-child(4)){grid-template-columns:repeat(2,minmax(0,1fr));gap:0.5rem;}
    body.elite .e-role-show .e-stack:has(> :nth-child(4)) .e-stack-cell{position:relative;}
    body.elite .e-role-show .e-stack:has(> :nth-child(4)) .e-stack-cell img{height:auto;aspect-ratio:3/4;}
    body.elite .e-stack-cell img{height:calc(68 * var(--e-svh));}
    body.elite .e-overlap{display:block;min-height:0;}
    body.elite .e-overlap-field{display:none;}
    body.elite .e-overlap-figure{margin:0;}
    body.elite .e-overlap-text{padding:1.5rem 0 0;}
    body.elite .e-overlap-text .e-display{margin-top:-2.2rem;margin-left:1rem;position:relative;}
    body.elite .e-overlap-extra{display:none;}
    body.elite .e-rows-row{grid-template-columns:minmax(0,1fr);}
    body.elite .e-rows-right .e-rows-figure{order:0;}
    body.elite .e-grid{inset:0 var(--e-gutter);grid-template-columns:repeat(4,1fr);}
    body.elite .e-grid i:nth-child(n+5){display:none;}
    body.elite .e-grid-content{grid-template-columns:repeat(4,1fr);}
    body.elite .e-grid-content .e-display{grid-column:1/-1;font-size:calc(clamp(2.4rem,9.5vw,3.8rem) * var(--e-display-step, 1));}
    body.elite .e-grid-facts,body.elite .e-grid-lead{grid-column:1/5;margin-top:1.5rem;}
    body.elite .e-grid-content .e-actions{grid-column:1/5;}
    body.elite .e-widget-with-aside{grid-template-columns:minmax(0,1fr);}
    body.elite .e-bleed-text{bottom:clamp(1.5rem,calc(6 * var(--e-vh)),3rem);}
    body.elite .e-bleed-contact{grid-template-columns:minmax(0,1fr);}
    body.elite .e-nav{padding-block:0.9rem;}
    /* One row on a phone, wordmark included. */
    body.elite,body.elite.e-nav-wordmark{--e-nav-h:4.25rem;}
    body.elite.e-nav-overlay{--e-nav-h:0rem;}
    body.elite.e-nav-wordmark .e-nav{flex-direction:row;}
    body.elite.e-nav-wordmark .e-brand{font-size:1.25rem;}
    body.elite .nav-toggle{display:flex;}
    body.elite .e-nav-links{display:none;position:absolute;top:100%;left:0;right:0;flex-direction:column;align-items:flex-start;gap:1rem;
      padding:1.25rem var(--e-gutter) 1.5rem;background:var(--e-paper);border-bottom:1px solid var(--e-line);}
    body.elite .e-nav-links.is-open{display:flex;opacity:1;transform:none;
      transition:opacity 180ms ease-out,transform 180ms cubic-bezier(.23,1,.32,1);}
    @starting-style{body.elite .e-nav-links.is-open{opacity:0;transform:translateY(-4px);}}
    body.elite.e-nav-overlay .e-nav-links{background:var(--e-inv-paper);}
    body.elite .e-stats{gap:1.5rem;}
    body.elite .e-colophon-line{flex-direction:column;gap:0.4rem;}
    body.elite .e-mobile-action{display:block;position:fixed;left:var(--e-gutter);right:var(--e-gutter);bottom:0.9rem;z-index:30;}
    body.elite .e-mobile-action .e-button{display:block;text-align:center;box-shadow:0 8px 30px rgba(0,0,0,.18);}
    body.elite .e-mobile-action{transition:opacity 200ms ease-out,transform 200ms cubic-bezier(.23,1,.32,1);}
    body.elite .e-mobile-action.is-aside{opacity:0;transform:translateY(0.75rem);pointer-events:none;visibility:hidden;
      transition:opacity 200ms ease-out,transform 200ms cubic-bezier(.23,1,.32,1),visibility 0s 200ms;}
    /* Room for the fixed action bar — only on the sites that have one.
       Applied to every phone it was 72px of dead space under the footer
       of every site whose CTA policy never draws a bar. */
    body.elite.e-cta-persistent main{padding-bottom:4.5rem;}
    /* Persistent strategy: the action lives in a bottom bar on a phone. */
    body.elite.e-cta-persistent .e-nav-action{display:none;}
  }
  @media (min-width:761px){
    body.elite .nav-toggle{display:none;}
  }

  /* Hover lives here and only here. On a phone a tap leaves the element
     in :hover until the next tap somewhere else, so the filled "Send"
     button turned into an empty outline at the exact moment it was
     pressed, and stayed that way — which reads as "cancelled". */
  @media (hover:hover) and (pointer:fine){
    body.elite .e-button:hover,body.elite .btn-primary:hover{background:transparent;color:var(--e-ink);}
    body.elite .e-link:hover{text-decoration-color:transparent;}
    body.elite .e-offer-link:hover{color:var(--e-accent);border-bottom-color:var(--e-accent);}
    body.elite .e-item-link:hover{border-bottom-color:currentColor;}
    body.elite .e-shelf-cell:hover .e-shelf-figure img{transform:scale(1.03);}
    body.elite .e-item .item-back:hover{color:var(--e-ink);border-bottom-color:currentColor;}
    body.elite .e-item .item-buy .btn-primary:hover{background:transparent;color:var(--e-ink);}
    body.elite .e-item .item-buy-ask .btn-primary:hover{background:var(--e-ink);color:var(--e-paper);}
  }

  /* Only sections the plan marked, only when the visitor allows it, and
     only when there is script to reveal them again.

     .e-js is set in <head> (see elite/render.py's shell) — before the
     first paint, so nothing flashes, and by the same script that will
     later run elite.js. Without that gate the hidden state was armed by
     CSS alone: a visitor whose JavaScript failed, was blocked, or was
     simply slow got a page of headings and photographs at opacity 0
     that never came back. The same gate Pro uses (html.pro-js). */
  @media (prefers-reduced-motion:no-preference){
    html.e-js body.elite:not(.e-motion-none) .e-motion{opacity:0;transform:translateY(var(--e-motion-dist));
      transition:opacity var(--e-motion-dur) var(--e-ease),transform var(--e-motion-dur) var(--e-ease);}
    html.e-js body.elite:not(.e-motion-none) .e-motion.is-visible{opacity:1;transform:none;}
    html.e-js body.elite.e-motion-reveal .e-motion .e-photo img{clip-path:inset(0 0 12% 0);transition:clip-path calc(var(--e-motion-dur) * 1.2) var(--e-ease);}
    html.e-js body.elite.e-motion-reveal .e-motion.is-visible .e-photo img{clip-path:inset(0);}
  }
  /* ── The opening arrives, once ────────────────────────────────────
     The gap: every other section had a reveal and the first screen —
     the one moment worth orchestrating — simply appeared. The order is
     taken from the Figma Make "Plan That Trip" example
     (R9HRPK1gxID5S5mYZCJofc, MacBookPro1668): the picture first, the
     words after it, the action last, each step about 300ms and 100ms
     apart. Its floating shapes, glitter sweep and glow are not taken.

     Constraints of our own: CSS only; nothing without script, under
     reduced motion, or in the editor preview (an owner sees that page
     dozens of times a session — anything seen that often must not
     move). The headline never starts transparent: it is usually the
     largest thing on the screen, and a transparent largest element is
     a later Largest Contentful Paint. */
  @media (prefers-reduced-motion:no-preference){
    @keyframes e-open-settle{from{transform:scale(1.035);}to{transform:none;}}
    @keyframes e-open-rise{from{transform:translateY(0.3em);}to{transform:none;}}
    @keyframes e-open-in{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}
    html.e-js body.elite:not(.is-editor-preview) main > .e-role-open:first-child :is(.e-bleed-img,.e-split-figure img,.e-stack-cell:first-child img){
      animation:e-open-settle 900ms cubic-bezier(.16,1,.3,1) both;}
    html.e-js body.elite:not(.is-editor-preview) main > .e-role-open:first-child :is(.e-display,.e-statement-text){
      animation:e-open-rise 480ms cubic-bezier(.16,1,.3,1) 60ms both;}
    html.e-js body.elite:not(.is-editor-preview) main > .e-role-open:first-child .e-lead{
      animation:e-open-in 320ms cubic-bezier(.16,1,.3,1) 160ms both;}
    html.e-js body.elite:not(.is-editor-preview) main > .e-role-open:first-child .e-actions{
      animation:e-open-in 320ms cubic-bezier(.16,1,.3,1) 260ms both;}

    /* Inside a revealed section, the parts arrive one after another
       instead of as one slab — the portfolio example staggers its cards
       by index × 100ms; 70ms here, and only the first six, so a long
       list never makes someone wait for its end. */
    html.e-js body.elite:not(.e-motion-none) .e-motion :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > *{
      opacity:0;transform:translateY(12px);
      transition:opacity 420ms cubic-bezier(.16,1,.3,1),transform 420ms cubic-bezier(.16,1,.3,1);}
    html.e-js body.elite:not(.e-motion-none) .e-motion.is-visible :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > *{
      opacity:1;transform:none;}
    html.e-js body.elite .e-motion.is-visible :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > :nth-child(2){transition-delay:70ms;}
    html.e-js body.elite .e-motion.is-visible :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > :nth-child(3){transition-delay:140ms;}
    html.e-js body.elite .e-motion.is-visible :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > :nth-child(4){transition-delay:210ms;}
    html.e-js body.elite .e-motion.is-visible :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > :nth-child(5){transition-delay:280ms;}
    html.e-js body.elite .e-motion.is-visible :is(.e-shelf,.e-stagger,.e-ledger-rows,.e-mosaic) > :nth-child(n+6){transition-delay:350ms;}
  }

  @media (prefers-reduced-motion:reduce){
    body.elite .e-motion{opacity:1;transform:none;}
    /* No travel, no clip — but a section still arrives rather than
       appearing, which helps the eye find what just came into view. */
    html.e-js body.elite:not(.e-motion-none) .e-motion:not(.is-visible){opacity:0;}
    html.e-js body.elite:not(.e-motion-none) .e-motion{transition:opacity 240ms ease;}
    body.elite .e-button:active,body.elite .btn-primary:active{transform:none;}
  }

/* Selling, in the Elite grammar. The ledger already sets an offer as
   "name … price"; a shop is one, so the only additions are the link on
   the name and the one item page. */
.e-item-link{color:inherit;text-decoration:none;border-bottom:1px solid transparent;position:relative;}
.e-item{display:grid;gap:2rem;align-items:start;padding-bottom:6rem;}
@media(min-width:820px){.e-item{grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:3.5rem;}}
/* No photograph: one measured column of type, not half a page beside
   an absence. */
@media(min-width:820px){.e-item-solo{grid-template-columns:minmax(0,58ch);}}
.e-item-figure{margin:0;}
/* A fixed ratio so the two columns agree whatever shape the owner
   uploaded — the same rule the shared renderer keeps (see
   site-render.css's .item-photo). */
.e-item-figure img{width:100%;height:auto;display:block;}
@media(min-width:820px){
  .e-item-figure img{aspect-ratio:4/5;object-fit:cover;max-height:min(calc(72 * var(--e-vh)),38rem);}
  .e-item-body{position:sticky;top:5rem;}
}
/* Back to the section this was found in, set as a caption. */
/* min-height: the way back from an item page measured 23px, under WCAG 2.5.8's 24. */
.e-item .item-back{display:inline-flex;align-items:center;min-height:1.75rem;margin:0 0 1.25rem;font-family:var(--e-font-body);
  font-size:var(--e-caption);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--e-muted);text-decoration:none;border-bottom:1px solid transparent;}
.e-item .item-back::before{content:"\2190\00a0";}
/* A phone shows the photograph and the price together, or the price is
   below the fold on the one page that exists to state it. */
@media(max-width:819px){.e-item-figure img{max-height:calc(34 * var(--e-vh));object-fit:cover;}}
.e-item-price{display:flex;gap:0.9rem;align-items:baseline;flex-wrap:wrap;font-family:var(--e-font-display);
  font-size:var(--e-h3);font-variant-numeric:tabular-nums;margin:0 0 1rem;color:var(--e-ink);}
.e-item-duration{font-family:var(--e-font-body);font-size:var(--e-caption);color:var(--e-muted);}
/* Reading scale, not caption scale: on the page where someone decides
   to buy, this paragraph is the whole argument for the thing, and it
   was set smaller than the site's own body copy. */
.e-item-text{color:var(--e-ink);font-size:var(--e-lead);line-height:1.45;
  margin:0 0 1.9rem;max-width:46ch;white-space:pre-line;}
/* Elite states the transaction with rules, not with a filled card: the
   standard tier's panel arrived here through the shared stylesheet and
   read as a component borrowed from another site. */
.e-item .item-buy{display:flex;flex-direction:column;gap:1rem;align-items:flex-start;
  background:transparent;border:0;border-top:1px solid var(--e-ink);border-bottom:1px solid var(--e-line);
  border-radius:0;padding:1.4rem 0;max-width:26rem;width:100%;}
.e-item .item-buy button[type=submit]{font:inherit;font-weight:500;letter-spacing:0.02em;cursor:pointer;
  border:1px solid var(--e-ink);background:var(--e-ink);color:var(--e-paper);
  padding:0.9rem 2rem;border-radius:0;}
.e-item .item-buy button[aria-busy=true]{opacity:0.55;cursor:progress;}
.e-item .item-quantity{display:flex;align-items:center;gap:0.7rem;color:var(--e-muted);font-size:0.9rem;}
.e-item .item-quantity input{width:4rem;padding:0.35rem 0.5rem;border:0;border-bottom:1px solid var(--e-ink);
  background:transparent;color:var(--e-ink);font:inherit;font-variant-numeric:tabular-nums;text-align:center;}
.e-item .item-secure{font-size:var(--e-caption);color:var(--e-muted);margin:0;}
.e-item .item-buy .btn-primary{display:inline-block;font-weight:500;letter-spacing:0.02em;
  border:1px solid var(--e-ink);background:var(--e-ink);color:var(--e-paper);
  padding:0.9rem 2rem;border-radius:0;text-decoration:none;}
.e-item .item-buy-ask .btn-primary{background:transparent;color:var(--e-ink);}
@media(max-width:819px){
  .e-item .item-buy{width:100%;}
  .e-item .item-buy button[type=submit],.e-item .item-buy .btn-primary{width:100%;text-align:center;}
}

/* ── A long list needs a way in ───────────────────────────────────────
   A hundred menu items in one column is a scroll, not a menu. From the
   `catalogue` band upward (app/rendering/volume.py) the categories get
   an index above them, and from `directory` the descriptions fold so
   that every name and every price stays visible — which is what a
   person scans a list this long for. Costs no photography and no
   motion, so it is available at every tier. */
body.elite .e-ledger-index{margin:0 0 calc(var(--e-module) * 0.5);}
body.elite .e-ledger-index ul{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0 0 0.9rem;
  gap:0.4rem 1.6rem;border-bottom:var(--e-rule, 1px solid var(--e-line));}
body.elite .e-ledger-index a{font-family:var(--e-font-body);font-size:var(--e-label);
  letter-spacing:var(--e-eyebrow-tracking);text-transform:var(--e-eyebrow-transform);
  color:var(--e-muted);text-decoration:none;}
body.elite .e-ledger-index a:hover,body.elite .e-ledger-index a:focus-visible{color:var(--e-accent);}
/* Folded: the row keeps name and price and loses only the sentence. */
body.elite .e-ledger-folded .e-ledger-row{padding-top:0.45rem;padding-bottom:0.45rem;}
body.elite .e-ledger-folded .e-ledger-group{margin-bottom:calc(var(--e-module) * 0.6);}
@media(max-width:719px){
  body.elite .e-ledger-index ul{gap:0.35rem 1rem;}
}

/* ── Media normalization ──────────────────────────────────────────────
   One treatment, applied to every photograph on the site. The
   transferable intelligence from the reference corpus is not any
   particular treatment — it is that ONE treatment over a whole ordinary
   set makes it read as one art-directed set instead of as a folder of
   phone pictures. This is how Pro differs from Standard with
   JavaScript disabled, and it is chosen once per site in
   app/rendering/elite/family.py.

   Presentation only: no stored asset is touched, so media identity and
   every srcset the responsive ladder already builds are unchanged. */
body.elite img{transition:none;}

/* Tonal unify — one curve and one saturation across the set. */
body.elite.e-norm-tonal-unify .e-figure img,
body.elite.e-norm-tonal-unify figure img,
body.elite.e-norm-tonal-unify .e-split-figure img,
body.elite.e-norm-tonal-unify .e-mosaic img,
body.elite.e-norm-tonal-unify .e-strip img{
  filter:saturate(0.82) contrast(1.06) brightness(1.02);}

/* Monochrome + accent — the photographs go to grey and the one accent
   colour does the talking elsewhere on the page. */
body.elite.e-norm-monochrome-accent .e-figure img,
body.elite.e-norm-monochrome-accent figure img,
body.elite.e-norm-monochrome-accent .e-split-figure img,
body.elite.e-norm-monochrome-accent .e-mosaic img,
body.elite.e-norm-monochrome-accent .e-strip img{
  filter:grayscale(1) contrast(1.05);}

/* Warm wash — a single warm overlay at low strength, which keeps food
   and rooms recognisable where monochrome would throw them away. */
body.elite.e-norm-warm-wash .e-figure img,
body.elite.e-norm-warm-wash figure img,
body.elite.e-norm-warm-wash .e-split-figure img,
body.elite.e-norm-warm-wash .e-mosaic img,
body.elite.e-norm-warm-wash .e-strip img{
  filter:sepia(0.18) saturate(1.05) contrast(1.03);}

/* Hairline frame — no colour change at all; one rule around each image,
   which is a treatment a set of two ordinary photographs can carry. */
body.elite.e-norm-hairline-frame figure img,
body.elite.e-norm-hairline-frame .e-split-figure img,
body.elite.e-norm-hairline-frame .e-mosaic img{
  border:1px solid var(--e-line);}

/* Framed small — the weak-media answer: the picture is reduced and given
   a margin instead of being enlarged to fill a band and expose every
   fault in it. */
body.elite.e-norm-framed-small .e-split-figure img,
body.elite.e-norm-framed-small .e-figure img{
  max-height:calc(52 * var(--e-vh));object-fit:cover;}
body.elite.e-norm-framed-small .e-split-figure{padding:var(--e-gutter);}

@media(prefers-reduced-motion:reduce){body.elite img{transition:none;}}

/* ── Whitespace safety ────────────────────────────────────────────────
   Negative space is legitimate when it is DOING something: separating
   two sections of the same weight, giving one image room, pausing
   before a change of ground, or setting a scale shift. A gap that does
   none of those is unused canvas, and unused canvas is what made the
   first generation of composed pages read as empty rather than as
   considered.

   Three ceilings, applied by tier budget rather than globally, so a
   deliberate editorial pause at Elite survives while a Standard page
   with four short sections stops claiming five screens.                */

/* An opening claims a viewport because it is the first thing seen. A
   TEXT opening with three lines in it claims a viewport and then shows
   two thirds of nothing, so it is sized to its content with a floor
   instead of a fixed height. An image opening still fills the screen —
   there the screen is the picture. */
body.elite .e-role-open:not(.e-move-bleed):not(.e-move-stack):not(.e-move-overlap):not(.e-v-page-title){
  min-height:min(calc(calc(100 * var(--e-svh)) - var(--e-nav-h)), 42rem);}
/* An inner page's title names the page and gets out of the way. Given the
   opening's floor it claimed a third of a screen above a services list. */
body.elite .e-role-open.e-v-page-title{min-height:0;}

/* Standard spends less air than Elite by budget, not by stylesheet:
   the same sections, held closer. */
body.elite.e-tier-standard{--e-module:clamp(2.5rem, 5.5vw, 5.5rem);}
body.elite.e-tier-standard .e-role-open:not(.e-move-bleed):not(.e-move-stack):not(.e-v-page-title){
  min-height:min(calc(calc(100 * var(--e-svh)) - var(--e-nav-h)), 34rem);}
body.elite.e-tier-standard .e-scale-monumental.e-move-statement:not(.e-role-open){min-height:0;}
body.elite.e-tier-standard .e-scale-spacious.e-move-statement:not(.e-role-open){min-height:0;}
body.elite.e-tier-standard .e-v-monumental.e-section,
body.elite.e-tier-standard .e-role-close.e-move-statement:is(.e-scale-spacious,.e-scale-monumental){
  min-height:0;}
body.elite.e-tier-pro .e-scale-monumental.e-move-statement:not(.e-role-open){min-height:calc(42 * var(--e-svh));}
body.elite.e-tier-pro .e-v-monumental.e-section,
body.elite.e-tier-pro .e-role-close.e-move-statement:is(.e-scale-spacious,.e-scale-monumental){
  min-height:calc(38 * var(--e-svh));}

/* A closing invitation is the last thing on the page, not a second
   opening: at every tier it is sized to its words. */
body.elite .e-role-close.e-move-column,body.elite .e-role-close.e-move-ledger{min-height:0;}

@media(max-width:719px){
  body.elite .e-role-open:not(.e-move-bleed):not(.e-move-stack):not(.e-move-overlap){min-height:0;}
  body.elite.e-tier-standard{--e-module:clamp(2.25rem, 7vw, 4rem);}
}

/* A directory earns a third column where there is room: the point of the
   form is that a hundred items stay scannable, and measured, one column
   ran to 8000px against 4200 in two. */
@media(min-width:1180px){
  body.elite .e-ledger-folded.e-ledger-two{grid-template-columns:repeat(3,minmax(0,1fr));}
}

/* An ungrouped catalogue: columns are the only navigation available to
   it, because an index needs categories and only the owner declares
   those. Rows are kept whole with break-inside. */
@media(min-width:760px){
  body.elite .e-ledger-columns .e-ledger-rows{columns:2;column-gap:calc(var(--e-gutter) * 1.5);}
  body.elite .e-ledger-columns .e-ledger-row{break-inside:avoid;}
}
@media(min-width:1180px){
  body.elite .e-ledger-columns .e-ledger-rows{columns:3;}
}

/* Three columns once there are enough categories to fill them. The composed
   ledger replaced a three-column grid on the standard renderer, and measured,
   two columns made a 50-item menu 4223px against 2211 — the form was better
   and the density was worse, which is not a trade worth making. */
@media(min-width:1180px){
  body.elite .e-ledger-groups.e-ledger-two:has(> :nth-child(4)){
    grid-template-columns:repeat(3,minmax(0,1fr));}
}

/* The About section's empty photo slot in the editor (base._about_photo_control):
   the same control Standard and Pro draw, in Elite's own ink and paper. */
body.elite .about-photo-add{display:inline-flex;align-items:center;gap:.5rem;margin-top:1.25rem;padding:.7rem 1.1rem;border:1px dashed var(--e-ink);
  border-radius:999px;background:transparent;color:var(--e-ink);font-family:var(--e-font-body);font-size:.95rem;cursor:pointer;box-shadow:none;}
body.elite .about-photo-add:focus-visible{outline:2px solid var(--e-ink);outline-offset:3px;}
/* A directory's descriptions behind a disclosure (moves/text.py _desc). */
body.elite .e-ledger-more summary{cursor:pointer;list-style:none;font-size:var(--e-caption);color:var(--e-muted);text-decoration:underline;text-underline-offset:2px;}
body.elite .e-ledger-more summary::-webkit-details-marker{display:none;}
body.elite .e-ledger-more[open] summary{margin-bottom:.25rem;}
