/* codanomix section library - written at publish from admin/starterkits/_sections/; edit those files, not this */
:where(:root){--cnx-primary:#22463c;--cnx-secondary:#3f4f47;--cnx-accent:#b8743a;--cnx-neutral:#6b7a72;--cnx-ink:#1d2b24;--cnx-body:#3f4f47;--cnx-line:#dbe3de;--cnx-bg:#ffffff;--cnx-tint:#f2f5f3;--cnx-heading-font:ui-serif,Georgia,serif;--cnx-body-font:ui-sans-serif,system-ui,sans-serif;--cnx-radius:12px;--cnx-sticky-h:80px}
/* [coda]nomix WIDGET PRIMITIVES.
   ------------------------------------------------------------------
   A widget is a block a TOOL renders on a published page: a booking
   calendar, a job list, a basket. Its words come from records rather
   than from the page, and everything else about it - where it sits,
   how it is inserted and removed, how it looks - is the same as any
   section.

   THE CONTRACT. A widget owns no colour, no typeface and no corner.
   Every rule below reads the site's --cnx-* tokens, so one booking
   calendar is warm on a guesthouse and severe on a trades site. The
   only colours declared here are the three SEMANTIC ones (bad, good,
   warn), and each is mixed with the site's own background so it sits
   on any palette.

   RESPONSIVE BY CONTAINER, NOT BY DEVICE. Every widget root carries
   container-type:inline-size, so a widget in the narrow column of a
   two-column page behaves like the phone view. Two widths matter:
   520px (stack everything) and 900px (the full layout).

   Classes are cnxw-* so nothing here can collide with a site's own
   markup or with the cnx-* section library beside it. */

/* ---------------------------------------------------------------- root */
.cnxw{
  container-type:inline-size;container-name:cnxw;
  font-family:var(--cnx-body-font);color:var(--cnx-body);
  --cnxw-r:var(--cnx-radius,12px);            /* cards, buttons, panels  */
  --cnxw-ri:calc(var(--cnx-radius,12px) * .6);/* inputs, a touch tighter */
  --cnxw-gap:14px;
  --cnxw-bad:#c0392f;--cnxw-bad-bg:color-mix(in srgb,#c0392f 10%,var(--cnx-bg));
  --cnxw-ok:#1f7a3d;--cnxw-ok-bg:color-mix(in srgb,#1f7a3d 10%,var(--cnx-bg));
  --cnxw-warn:#8a5a10;--cnxw-warn-bg:color-mix(in srgb,#c98a1e 16%,var(--cnx-bg));
}
.cnxw *,.cnxw *::before,.cnxw *::after{box-sizing:border-box}
.cnxw [hidden]{display:none!important}

/* ------------------------------------------------------------ type */
.cnxw-hd{font-family:var(--cnx-heading-font);color:var(--cnx-ink);line-height:1.15;font-weight:600;margin:0 0 .35em}
.cnxw-hd-l{font-size:clamp(1.5rem,3vw,2rem)}
.cnxw-hd-m{font-size:clamp(1.2rem,2.2vw,1.5rem)}
.cnxw-hd-s{font-size:1.1rem}
.cnxw-eyebrow{font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;color:var(--cnx-accent);font-weight:700;margin:0 0 .3em}
.cnxw-mut{color:var(--cnx-neutral);font-size:.88rem}
.cnxw-price{font-weight:700;color:var(--cnx-ink)}
.cnxw-num{font-variant-numeric:tabular-nums}

/* --------------------------------------------------------- buttons */
/* A widget never draws its own button: this IS the site's button, the
   same shape .cnx-btn has, so a kit that restyles .cnx-btn restyles
   these too (see the alias at the foot of this file). */
/* 44px is the floor for anything a thumb has to hit - a button, a pill, a
   stepper. Not a phone rule: a mis-hit on a desktop trackpad is the same
   mis-hit. min-height rather than padding, so a long label still wraps
   inside the target rather than growing it past what the layout expects. */
.cnxw-btn{display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;background:var(--cnx-primary);color:var(--cnx-bg);
  border:2px solid var(--cnx-primary);border-radius:var(--cnxw-r);
  padding:10px 18px;font:inherit;font-weight:600;font-size:.95rem;
  text-decoration:none;text-align:center;cursor:pointer;white-space:nowrap;
  transition:opacity .12s ease}
.cnxw-btn:hover{opacity:.88;color:var(--cnx-bg)}
.cnxw-btn-quiet{background:transparent;color:var(--cnx-primary)}
.cnxw-btn-quiet:hover{background:var(--cnx-tint);color:var(--cnx-primary)}
.cnxw-btn-sm{padding:7px 13px;font-size:.86rem;min-height:40px}
.cnxw-btn-block{display:flex;width:100%}
.cnxw-btn[disabled],.cnxw-btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
.cnxw-actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-top:12px}

/* ---------------------------------------------------------- fields */
.cnxw-field{margin:0 0 12px;min-width:0}
.cnxw-label{display:block;font-size:.78rem;font-weight:700;letter-spacing:.02em;color:var(--cnx-ink);margin:0 0 5px}
.cnxw-input,.cnxw select.cnxw-input,.cnxw textarea.cnxw-input{
  display:block;width:100%;min-height:44px;font:inherit;font-size:.95rem;
  padding:10px 12px;color:var(--cnx-ink);background:var(--cnx-bg);
  border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri)}
.cnxw-input::placeholder{color:var(--cnx-neutral)}
.cnxw-input:focus-visible,.cnxw a:focus-visible,.cnxw button:focus-visible,.cnxw [tabindex]:focus-visible{
  outline:2px solid var(--cnx-primary);outline-offset:2px;border-color:var(--cnx-primary)}
.cnxw textarea.cnxw-input{min-height:110px;resize:vertical}
.cnxw-input[aria-invalid="true"]{border-color:var(--cnxw-bad)}
.cnxw-hint{font-size:.82rem;color:var(--cnx-neutral);margin:5px 0 0}
.cnxw-err{font-size:.85rem;font-weight:600;color:var(--cnxw-bad);margin:5px 0 0}
.cnxw-check{display:flex;gap:9px;align-items:flex-start;font-size:.92rem;margin:0 0 10px}
.cnxw-check input{margin:3px 0 0;width:18px;height:18px;accent-color:var(--cnx-primary);flex:none}

/* counters (guests, quantity) */
.cnxw-qty{display:inline-flex;align-items:stretch;border:1.5px solid var(--cnx-line);border-radius:99px;overflow:hidden}
.cnxw-qty button{min-width:44px;min-height:44px;border:0;background:var(--cnx-bg);color:var(--cnx-ink);font:inherit;font-size:1.1rem;font-weight:700;cursor:pointer}
.cnxw-qty button:hover{background:var(--cnx-tint)}
.cnxw-qty span{min-width:44px;display:grid;place-items:center;font-weight:700;color:var(--cnx-ink);
  border-left:1.5px solid var(--cnx-line);border-right:1.5px solid var(--cnx-line);font-variant-numeric:tabular-nums}

/* ----------------------------------------------------------- pills */
.cnxw-pills{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}
.cnxw-pill{display:inline-flex;align-items:center;gap:7px;padding:7px 14px;min-height:44px;
  border:1.5px solid var(--cnx-line);border-radius:99px;background:var(--cnx-bg);
  color:var(--cnx-ink);font:inherit;font-size:.85rem;font-weight:600;cursor:pointer}
.cnxw-pill:hover{border-color:var(--cnx-primary)}
.cnxw-pill[aria-pressed="true"],.cnxw-pill.is-on{background:var(--cnx-primary);border-color:var(--cnx-primary);color:var(--cnx-bg)}
/* the x on a pill is inside a 44px target already, so it may be small */
.cnxw-pill-x{border:0;background:rgba(0,0,0,.14);color:inherit;width:22px;height:22px;border-radius:50%;
  display:grid;place-items:center;font-size:.9rem;line-height:1;cursor:pointer;padding:0;flex:none}

/* ---------------------------------------------------------- badges */
.cnxw-badge{display:inline-block;padding:3px 9px;border-radius:99px;font-size:.72rem;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;background:var(--cnx-tint);color:var(--cnx-ink)}
.cnxw-badge-accent{background:var(--cnx-accent);color:var(--cnx-bg)}
.cnxw-badge-ok{background:var(--cnxw-ok-bg);color:var(--cnxw-ok)}
.cnxw-badge-warn{background:var(--cnxw-warn-bg);color:var(--cnxw-warn)}
.cnxw-badge-bad{background:var(--cnxw-bad-bg);color:var(--cnxw-bad)}

/* ----------------------------------------------------------- cards */
.cnxw-card{border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-r);background:var(--cnx-bg);overflow:hidden}
.cnxw-card-body{padding:16px 18px}
.cnxw-card-tint{background:var(--cnx-tint)}
.cnxw-card-lead{border-color:var(--cnx-primary);border-width:2px}
.cnxw-card a.cnxw-card-link,a.cnxw-card{text-decoration:none;color:inherit;display:block}
a.cnxw-card:hover,.cnxw-card:has(a.cnxw-card-link:hover){border-color:var(--cnx-primary)}

/* pictures: a 4:3 frame that never collapses, and never stretches */
.cnxw-media{background:var(--cnx-tint);aspect-ratio:4/3;overflow:hidden;display:block}
.cnxw-media img{width:100%;height:100%;object-fit:cover;display:block}
.cnxw-media img[src=""],.cnxw-media img:not([src]){display:none}
.cnxw-media-wide{aspect-ratio:21/9}.cnxw-media-square{aspect-ratio:1}.cnxw-media-tall{aspect-ratio:3/4}
.cnxw-media-free{aspect-ratio:auto}

/* --------------------------------------------------------- layouts */
.cnxw-wrap{max-width:1080px;margin:0 auto;padding:0 24px}
.cnxw-grid{display:grid;gap:var(--cnxw-gap)}
.cnxw-grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.cnxw-grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.cnxw-grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}

/* A BOUND SECTION BRINGS ITS OWN GRID. A fragment writes its cards inside
   .cnxw-grid-3; binding it to a collection replaces that repeat with the
   collection's own render, which is itself a grid inside a .cnxw wrapper -
   so five room cards published stacked in one 335px column of a
   three-column grid. When a grid holds nothing but one wrapper that is
   itself a grid, the outer one steps out of the way. */
.cnxw-grid:has(> .cnxw:only-child > .cnxw-grid){display:block}
.cnxw-split{display:grid;gap:26px;align-items:start;grid-template-columns:minmax(0,1.7fr) minmax(0,1fr)}
.cnxw-split-even{grid-template-columns:repeat(2,minmax(0,1fr))}
.cnxw-bar{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}
.cnxw-bar>.cnxw-field{flex:1 1 150px;margin:0}
.cnxw-row{display:flex;gap:12px;align-items:center;justify-content:space-between}
.cnxw-rule{border:0;border-top:1.5px solid var(--cnx-line);margin:18px 0}
/* a side panel follows the page down on a wide screen and sits still on a phone */
.cnxw-sticky{position:sticky;top:calc(var(--cnx-sticky-h,80px) + 16px)}

/* key/value lines - a summary, a spec table, an order total */
.cnxw-kv{display:flex;justify-content:space-between;gap:14px;padding:8px 0;border-top:1px solid var(--cnx-line);font-size:.93rem}
.cnxw-kv>:first-child{color:var(--cnx-neutral)}
.cnxw-kv>:last-child{color:var(--cnx-ink);font-weight:600;text-align:right;font-variant-numeric:tabular-nums}
.cnxw-kv-total{border-top-width:1.5px;border-top-color:var(--cnx-ink);font-size:1.02rem}

/* a list of records: rows with a rule between, not boxes */
.cnxw-list{list-style:none;margin:0;padding:0}
.cnxw-list>li{padding:16px 0;border-top:1px solid var(--cnx-line)}
.cnxw-list>li:first-child{border-top:1.5px solid var(--cnx-line)}

/* ------------------------------------------------------------ step rail */
.cnxw-steps{display:flex;gap:6px;list-style:none;margin:0 0 18px;padding:0;font-size:.78rem;font-weight:700;color:var(--cnx-neutral)}
.cnxw-steps li{flex:1;border-top:3px solid var(--cnx-line);padding-top:7px;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cnxw-steps li.is-done{border-top-color:var(--cnx-accent)}
.cnxw-steps li.is-now{border-top-color:var(--cnx-primary);color:var(--cnx-ink)}

/* -------------------------------------------------------------- states */
/* EMPTY. Never a blank: what is not here, and the way to put it here. */
.cnxw-empty{border:1.5px dashed var(--cnx-line);border-radius:var(--cnxw-r);padding:28px 22px;
  text-align:center;color:var(--cnx-neutral)}
.cnxw-empty b{display:block;color:var(--cnx-ink);font-size:1.05rem;margin-bottom:4px}
/* LOADING. The widget's own shape in grey - never a spinner in space. */
.cnxw-skel{background:linear-gradient(90deg,var(--cnx-tint) 25%,color-mix(in srgb,var(--cnx-neutral) 14%,var(--cnx-tint)) 37%,var(--cnx-tint) 63%);
  background-size:400% 100%;animation:cnxw-shim 1.4s ease infinite;border-radius:var(--cnxw-ri);color:transparent!important}
.cnxw-skel *{visibility:hidden}
@keyframes cnxw-shim{0%{background-position:100% 0}100%{background-position:0 0}}
@media (prefers-reduced-motion:reduce){.cnxw-skel{animation:none}}
/* MESSAGES. What went wrong and what to do; what happened and what is next. */
.cnxw-note{border-radius:var(--cnxw-ri);padding:12px 15px;font-size:.93rem;margin:0 0 14px;
  border:1.5px solid var(--cnx-line);background:var(--cnx-tint);color:var(--cnx-ink)}
.cnxw-note-bad{border-color:var(--cnxw-bad);background:var(--cnxw-bad-bg);color:var(--cnxw-bad)}
.cnxw-note-ok{border-color:var(--cnxw-ok);background:var(--cnxw-ok-bg);color:var(--cnxw-ok)}
.cnxw-note-warn{border-color:var(--cnxw-warn);background:var(--cnxw-warn-bg);color:var(--cnxw-warn)}
/* a finished thing: the confirmation card a journey ends on */
.cnxw-done{border:2px solid var(--cnx-primary);border-radius:var(--cnxw-r);padding:22px 24px;background:var(--cnx-bg)}
/* ON THE CANVAS. The editor sees the widget, never its live controls. */
.cnxw-inert{pointer-events:none;user-select:none}

/* --------------------------------------------------- container queries */
@container cnxw (max-width: 900px){
  .cnxw-grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cnxw-grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cnxw-split{grid-template-columns:minmax(0,1fr)}
  .cnxw-sticky{position:static}
}
@container cnxw (max-width: 520px){
  .cnxw-grid-2,.cnxw-grid-3,.cnxw-grid-4,.cnxw-split-even{grid-template-columns:minmax(0,1fr)}
  .cnxw-bar{flex-direction:column;align-items:stretch}
  .cnxw-bar>.cnxw-field{flex:1 1 auto}
  .cnxw-bar .cnxw-btn,.cnxw-actions .cnxw-btn{width:100%}
  .cnxw-actions{flex-direction:column;align-items:stretch}
  .cnxw-steps{gap:4px}
  .cnxw-steps li{font-size:0;padding-top:5px;border-top-width:4px}
  .cnxw-card-body{padding:14px 15px}
  .cnxw-hd-l{font-size:1.45rem}
  .cnxw-wrap{padding:0 16px}
}

/* Visually hidden, still read aloud. A required marker or a field label a
   design does not show still has to reach a screen reader - and a fetched
   fragment carries it onto pages that link nothing but this sheet. */
.cnxw-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ------------------------------------------------- the site's own button */
/* A kit styles .cnx-btn; a site imported from HTML may style .btn. Widgets
   ask for .cnxw-btn and get whichever the site has actually dressed, so a
   booking button matches the buttons already on the page. */
.cnxw .cnx-btn,.cnxw .cnx-btn-quiet{font-family:inherit}

/* ------------------------------------------------------------ galleries */
/* THE ASPECT BOX. A tile is a frame the picture covers, never a picture
   deciding the row's height: --cnxw-ar on the figure, set by a class per
   ratio (cnxw-ar-32, -43, -11, -34, -23, -169), never by an inline style.
   The frame is the link, so the whole tile is the 44px+ target the lightbox
   opens from. An empty tile (a palette insert nobody has filled) is nothing
   on the site and a dashed pick target while Canvas is editing. */
.cnxw-gal{display:grid;gap:var(--cnxw-gap)}
.cnxw-gal-tile{margin:0;min-width:0;position:relative;--cnxw-ar:4/3}
.cnxw-ar-32{--cnxw-ar:3/2}.cnxw-ar-43{--cnxw-ar:4/3}.cnxw-ar-11{--cnxw-ar:1/1}
.cnxw-ar-34{--cnxw-ar:3/4}.cnxw-ar-23{--cnxw-ar:2/3}.cnxw-ar-169{--cnxw-ar:16/9}
.cnxw-gal-tile>a{display:block;aspect-ratio:var(--cnxw-ar);overflow:hidden;border-radius:var(--cnxw-r);
  background:var(--cnx-tint);color:inherit;text-decoration:none}
.cnxw-gal-tile>a:focus-visible{outline:2px solid var(--cnx-primary);outline-offset:2px}
.cnxw-gal-tile img{width:100%;height:100%;object-fit:cover;display:block}
.cnxw-gal-tile img[src=""],.cnxw-gal-tile img:not([src]){display:none}
.cnxw-gal-tile figcaption{font-size:.84rem;color:var(--cnx-neutral);margin-top:6px}
.cnxw-gal-tile figcaption:empty{display:none}
.cnxw-gal-tile:has(>a>img[src=""]){display:none}
html.cnxe-on .cnxw-gal-tile:has(>a>img[src=""]){display:block}
html.cnxe-on .cnxw-gal-tile>a>img[src=""]{display:block;opacity:0;cursor:pointer}
html.cnxe-on .cnxw-gal-tile:has(>a>img[src=""])>a{border:2px dashed var(--cnx-line)}
/* a source-fed gallery (a record, a folder) stands in for the written one
   beside it: the words stay in the draft, the site shows the source */
.cnxw-gal-wrap~.cnx-gal-written{display:none}

/* curated + record hero: one large, four small; the sixth onward are in the
   set (the lightbox walks them) and off the page (the "+N" tile opens them) */
.cnxw-gal-curated,.cnxw-gal-hero{grid-template-columns:repeat(4,minmax(0,1fr))}
.cnxw-gal-curated>.cnxw-gal-tile,.cnxw-gal-hero>.cnxw-gal-tile{--cnxw-ar:4/3}
.cnxw-gal-curated>.cnxw-gal-tile:first-child,.cnxw-gal-hero>.cnxw-gal-tile:first-child{grid-column:1/span 2;grid-row:1/span 2}
.cnxw-gal-curated>.cnxw-gal-tile:first-child>a,.cnxw-gal-hero>.cnxw-gal-tile:first-child>a{aspect-ratio:auto;height:100%}
.cnxw-gal-curated>.cnxw-gal-tile:nth-child(n+6),.cnxw-gal-hero>.cnxw-gal-tile:nth-child(n+6){display:none}
.cnxw-gal-more{position:absolute;inset:0;width:100%;height:100%;display:grid;place-items:center;
  border:0;border-radius:var(--cnxw-r);cursor:pointer;padding:0;
  background:color-mix(in srgb,var(--cnx-ink) 55%,transparent);color:var(--cnx-bg);
  font-family:var(--cnx-heading-font);font-size:1.5rem;font-weight:600;line-height:1}
.cnxw-gal-more:hover{background:color-mix(in srgb,var(--cnx-ink) 68%,transparent)}
.cnxw-gal-more:focus-visible{outline:2px solid var(--cnx-bg);outline-offset:-4px}
.cnxw-gal-all{margin-top:14px}

/* full: three across, grouped by set with a heading per group */
.cnxw-gal-group{margin:0 0 30px}
.cnxw-gal-group:last-child{margin-bottom:0}
.cnxw-gal-group>.cnxw-hd{margin:0 0 12px}
.cnxw-gal-full{grid-template-columns:repeat(3,minmax(0,1fr))}
.cnxw-gal-full>.cnxw-gal-tile{--cnxw-ar:4/3}

/* strip: one row that scrolls and snaps, tiles at their own proportions */
.cnxw-gal-strip{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:6px;
  scrollbar-width:thin;-webkit-overflow-scrolling:touch}
.cnxw-gal-strip>.cnxw-gal-tile{flex:0 0 auto;scroll-snap-align:start;max-width:80%}
.cnxw-gal-strip>.cnxw-gal-tile>a{height:clamp(200px,28vw,320px);width:auto;aspect-ratio:var(--cnxw-ar)}

@container cnxw (max-width: 900px){
  .cnxw-gal-full{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cnxw-gal-curated,.cnxw-gal-hero{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cnxw-gal-curated>.cnxw-gal-tile:first-child,.cnxw-gal-hero>.cnxw-gal-tile:first-child{grid-column:1/span 2;grid-row:auto;--cnxw-ar:16/9}
  .cnxw-gal-curated>.cnxw-gal-tile:first-child>a,.cnxw-gal-hero>.cnxw-gal-tile:first-child>a{aspect-ratio:var(--cnxw-ar);height:auto}
}
@container cnxw (max-width: 520px){
  /* "1.5 columns": a snap scroller showing one tile and half the next */
  .cnxw-gal-full{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:6px;scrollbar-width:thin}
  .cnxw-gal-full>.cnxw-gal-tile{flex:0 0 66%;scroll-snap-align:start}
  .cnxw-gal-curated>.cnxw-gal-tile,.cnxw-gal-hero>.cnxw-gal-tile{--cnxw-ar:1/1}
  .cnxw-gal-curated>.cnxw-gal-tile:first-child,.cnxw-gal-hero>.cnxw-gal-tile:first-child{--cnxw-ar:4/3}
  .cnxw-gal-strip>.cnxw-gal-tile>a{height:clamp(180px,52vw,240px)}
  .cnxw-gal-more{font-size:1.25rem}
}

/* ------------------------------------------------------------ the lightbox
   One <dialog class="cnxw cnxw-lb"> per page (apps/lightbox.js). It is a
   cnxw container of its own, so the same two widths govern it. The ground is
   the site's ink; every control is 44px; the picture is never cropped. Zoom
   is a class - the pan box scrolls the picture at its natural size. Motion
   only when the visitor has not asked for less. */
.cnxw-lb{position:fixed;inset:0;width:100vw;height:100vh;max-width:none;max-height:none;margin:0;padding:0;border:0;
  background:color-mix(in srgb,var(--cnx-ink) 94%,transparent);color:var(--cnx-bg);
  display:none;flex-direction:column;overflow:hidden;overscroll-behavior:contain}
.cnxw-lb[open]{display:flex}
.cnxw-lb::backdrop{background:transparent}
.cnxw-lb [hidden]{display:none!important}
.cnxw-lb-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 8px 8px 16px;flex:none}
.cnxw-lb-n{margin:0;font-size:.9rem;font-variant-numeric:tabular-nums;opacity:.85}
.cnxw-lb-btn{min-width:44px;min-height:44px;border:0;border-radius:var(--cnxw-r);padding:0;
  background:color-mix(in srgb,var(--cnx-bg) 12%,transparent);color:var(--cnx-bg);
  font:inherit;font-size:1.6rem;line-height:1;cursor:pointer;display:grid;place-items:center}
.cnxw-lb-btn:hover{background:color-mix(in srgb,var(--cnx-bg) 24%,transparent)}
.cnxw-lb-btn:focus-visible{outline:2px solid var(--cnx-bg);outline-offset:2px}
.cnxw-lb-btn[disabled]{opacity:.35;cursor:default}
.cnxw-lb-stage{position:relative;flex:1 1 auto;min-height:0;display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;gap:8px;padding:0 8px 8px}
.cnxw-lb-fig{margin:0;min-width:0;height:100%;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px}
.cnxw-lb-pan{flex:1 1 auto;min-height:0;width:100%;display:flex;align-items:center;justify-content:center;
  overflow:hidden;touch-action:none;user-select:none;-webkit-user-select:none}
.cnxw-lb-img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;display:block;
  border-radius:calc(var(--cnxw-r) * .5);-webkit-user-drag:none}
.cnxw-lb-fig.is-loading .cnxw-lb-img{opacity:0}
.cnxw-lb.is-zoomed .cnxw-lb-pan{overflow:auto;display:block;cursor:grab}
.cnxw-lb.is-zoomed .cnxw-lb-img{max-width:none;max-height:none;border-radius:0}
.cnxw-lb-cap{margin:0;flex:none;padding:0 12px;font-size:.9rem;text-align:center;max-width:70ch;opacity:.9}
body.cnxw-lb-open{overflow:hidden}
@media (prefers-reduced-motion:no-preference){.cnxw-lb-img{transition:opacity .18s ease}}
@container cnxw (max-width: 520px){
  .cnxw-lb-stage{grid-template-columns:minmax(0,1fr);padding:0 0 8px}
  .cnxw-lb-prev,.cnxw-lb-next{position:absolute;bottom:14px;z-index:1}
  .cnxw-lb-prev{left:12px}.cnxw-lb-next{right:12px}
  .cnxw-lb-cap{padding:0 64px 44px}
  .cnxw-lb-img{border-radius:0}
}


/* --- widgets.events.css --- */
/* [coda]nomix EVENTS WIDGETS.
   ------------------------------------------------------------------
   What the Events tool renders on a published page: the what's-on
   list, one event's panel, the registration form and its confirmation.

   Everything a card, a button, a field, a pill, a badge or a grid
   needs is already in widgets.css - this file adds only the shapes
   that are the EVENTS' own and nothing else has:

     .cnxw-ev-d      the date block (big day number, month beneath)
     .cnxw-ev-row    the date block beside the words
     .cnxw-ev-box    the bordered date box at the head of a panel
     .cnxw-ev-map    the map frame
     .cnxw-ev-rows   the compact "calendar list" layout

   No colour, face or corner is declared here: every one reads a
   --cnx-* token, so what's on is warm on a guesthouse and severe on a
   trades site without a line of this file changing. */

/* ---------------------------------------------------- the tool's sections
   A widget reads --cnx-ink and --cnx-body, which are legible against
   --cnx-bg by definition and against nothing else. So the sections these
   widgets live in take that ground rather than whatever the page happens
   to be. Declared here, which the library sheet loads BEFORE sections.css,
   so .cnx-look-tinted still wins when a client asks for the tint. */
.cnx-event,.cnx-eventreg,.cnx-eventdone,.cnx-eventnext{background:var(--cnx-bg)}

/* ------------------------------------------------------- the date block */
/* The wireframe's .dnum: a day number in the heading face with the month
   under it. It is never the ONLY cue - the <time datetime> beside it and
   the "6:30pm · The Long Room" line beneath both say the same thing in
   words, so a reader who cannot see the block still has the date. */
.cnxw-ev-d{
  font-family:var(--cnx-heading-font);font-size:1.5rem;line-height:1;
  color:var(--cnx-primary);text-align:center;min-width:44px;display:block}
.cnxw-ev-d small{
  display:block;font-family:var(--cnx-body-font);font-size:.68rem;
  letter-spacing:.06em;text-transform:uppercase;color:var(--cnx-neutral);margin-top:3px}

/* the card's body: date block, then the words */
.cnxw-ev-row{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:start}
.cnxw-ev-name{display:block;color:var(--cnx-ink);font-weight:700;margin:0 0 2px}
.cnxw-ev-name a{color:inherit;text-decoration:none}
.cnxw-ev-name a:hover{text-decoration:underline}
.cnxw-ev-meta{margin:0}
.cnxw-ev-meta+.cnxw-ev-meta{margin-top:2px}

/* a past or cancelled date keeps its place and says so - it is never hidden */
.cnxw-ev[data-when="past"] .cnxw-ev-d{color:var(--cnx-neutral)}

/* ------------------------------------------------------------ the panel */
/* One event at the head of its own page: the date box, then the words. */
.cnxw-ev-box{
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;align-items:center;
  padding:10px 12px;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-r);margin:0 0 10px}
.cnxw-ev-tx{margin:0 0 10px;color:var(--cnx-body)}
.cnxw-ev-map{margin:0}
.cnxw-ev-map iframe,.cnxw-ev-map img{width:100%;height:100%;border:0;display:block}
.cnxw-ev-map-ph{display:grid;place-items:center;color:var(--cnx-neutral);
  font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;height:100%}

/* ---------------------------------------------------- the list layout */
/* "Calendar list": the same cards, stacked and ruled instead of boxed. */
.cnxw-ev-rows{display:grid;gap:0}
.cnxw-ev-rows .cnxw-ev{border-width:0;border-top:1px solid var(--cnx-line);border-radius:0}
.cnxw-ev-rows .cnxw-ev:first-child{border-top-width:1.5px}
.cnxw-ev-rows .cnxw-card-body{padding-left:0;padding-right:0}

/* ------------------------------------------------------- the filter bar */
.cnxw-ev-filters{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 14px}
.cnxw-ev-filters .cnxw-pills{margin:0}
.cnxw-ev-filters .cnxw-mut{margin-right:2px}

/* --------------------------------------------------------- the booking */
/* The ticket rows are cnxw-kv lines; the stepper is the cnxw-qty primitive.
   Only the pairing of the two needs saying here: the name takes the room
   that is going spare and the price and stepper take exactly what they
   need, or "The whole course" breaks over two lines beside a stepper. */
.cnxw-ev-tk{align-items:center;flex-wrap:wrap}
.cnxw-ev-tk>:first-child{flex:1 1 9em;min-width:0}
.cnxw-ev-tk>:last-child{flex:0 0 auto;display:flex;align-items:center;gap:8px;justify-content:flex-end}
.cnxw-ev-blurb{display:block;font-weight:400;color:var(--cnx-neutral);font-size:.85rem;text-align:left}

/* the .ics link sits under the confirmation's own lines */
.cnxw-ev-ics{margin-top:14px}

/* ------------------------------------------------------ the card fields */
/* Stripe's Payment Element mounts here. It draws its own inputs inside an
   iframe, so there is nothing here to style but the box around them - the
   same box the Shop's card fields sit in, because a visitor who has bought
   a book and booked a class should be looking at the same thing twice.
   Hidden until there is a payment to take, so a free booking never shows
   an empty panel. */
.cnxw-pay{margin:14px 0 0}
.cnxw-pay:not([hidden]){padding:14px;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);background:var(--cnx-bg)}

/* -------------------------------------------------- container queries */
@container cnxw (max-width: 520px){
  .cnxw-ev-d{font-size:1.3rem;min-width:38px}
  .cnxw-ev-row{gap:10px}
  .cnxw-ev-filters{align-items:stretch;flex-direction:column}
}

/* --- widgets.hiring.css --- */
/* [coda]nomix HIRING widgets.
   ------------------------------------------------------------------
   Everything generic - buttons, fields, pills, cards, grids, the step
   rail, the empty/loading/error states - is in widgets.css and is NOT
   repeated here. What follows is only the shapes Hiring has that no
   other tool does: a vacancy row, the filter bar over it, the job
   page's fact panel, the CV drop zone, the status card and the alerts
   sign-up.

   THE CONTRACT. No colour, no typeface and no corner of its own: every
   value below is a --cnx-* token, or one of widgets.css's three
   semantic vars (--cnxw-bad / --cnxw-ok / --cnxw-warn). A literal here
   fails tests/Unit/HiringWidgetsTest.php, which is the point.

   Layout is by CONTAINER, never by viewport: the job list in a narrow
   column behaves like the phone view. The two widths are the library's
   own, 520 and 900, and there is no @media rule in this file at all.

   The careers RUNTIME's page shell - skip link, header, footer, the
   site's own nav strip - is NOT here. It is a whole document rather than
   a widget, its selectors are cr-* rather than cnxw-*, and this sheet is
   linked by every published site: apps/careers-shell.css carries it, and
   apps/careers.php links that beside this. */

/* ------------------------------------------------------------ list */
.cnxw-jobs-count{color:var(--cnx-neutral);font-size:.9rem;margin:0 0 8px}
.cnxw-jobs-note{color:var(--cnx-neutral);font-size:.92rem;margin:14px 0 0}

/* the filter bar: a search box, two selects, then the category pills.
   Hidden until script has filled it from the rows actually rendered -
   a select with nothing in it is worse than no select. */
.cnxw-filters{margin:0 0 16px}
.cnxw-filters .cnxw-bar{margin:0 0 10px}
.cnxw-filters .cnxw-pills{margin:0}
/* Only while the bar IS a row. Both of these are cross-axis instructions,
   and .cnxw-bar turns into a column under 520: "align-items:flex-end" then
   right-aligned every field, and a flex-basis of 220px became 220px of
   HEIGHT under the search box. Guarded rather than fought with weight. */
@container cnxw (min-width: 521px){
  .cnxw-filters .cnxw-bar{align-items:flex-end}
  .cnxw-filters .cnxw-field-grow{flex:2 1 220px}
}

/* a vacancy row: .cnxw-list gives the rules between, .cnxw-split gives
   the two columns; this narrows the right one to the Apply button. */
.cnxw-job{grid-template-columns:minmax(0,1fr) auto;gap:12px}
.cnxw-job-title{margin:0;font-family:var(--cnx-heading-font);font-size:1.05rem;line-height:1.25;
  color:var(--cnx-ink);font-weight:600}
.cnxw-job-title a{color:inherit;text-decoration:none}
.cnxw-job-title a:hover{color:var(--cnx-primary)}
.cnxw-job-meta{margin:2px 0 0}
.cnxw-job-meta span+span::before{content:"\00b7";margin:0 7px}
.cnxw-job-summary{margin:6px 0 0;max-width:62ch}
/* "show pay" and "show closing date" are toggles: the markup always
   carries the fact and the setting decides whether it is shown, so one
   published row answers either way with no second template. */
[data-pay="0"] .cnxw-job-pay,[data-pay="0"] .cnxw-fact-pay{display:none}
[data-pay="0"] .cnxw-job-pay+span::before{content:none;margin:0}
[data-closing="0"] .cnxw-job-closing,[data-closing="0"] .cnxw-fact-closing{display:none}
[data-closing="0"] .cnxw-job-closing+span::before{content:none;margin:0}
/* a row the client-side filter has put away: the rows are already on
   the page, so filtering is an attribute, not a request per keystroke */
.cnxw-job-row[hidden]{display:none}

/* ------------------------------------------------------ now hiring */
.cnxw-strip{display:flex;gap:14px;align-items:center;justify-content:space-between}
.cnxw-strip-n{font-family:var(--cnx-heading-font);font-size:1.2rem;color:var(--cnx-ink);margin:0;font-weight:600}
.cnxw-strip-n b{font-weight:inherit;color:var(--cnx-primary)}

/* --------------------------------------------------------- job page */
.cnxw-crumb{font-size:.85rem;color:var(--cnx-neutral);margin:0 0 12px}
.cnxw-crumb a{color:inherit}
.cnxw-crumb a+a::before,.cnxw-crumb span::before{content:"\203a";margin:0 8px;color:var(--cnx-neutral)}
.cnxw-facts .cnxw-kv:first-child{border-top:0;padding-top:0}
.cnxw-panel-note{margin:8px 0 0}
/* the advert body: the job's own sections, in the site's own prose */
.cnxw-advert>:first-child{margin-top:0}
.cnxw-advert h2,.cnxw-advert h3,.cnxw-advert h4{font-family:var(--cnx-heading-font);color:var(--cnx-ink);
  font-size:1.1rem;font-weight:600;margin:22px 0 .35em;line-height:1.2}
.cnxw-advert p,.cnxw-advert li{max-width:66ch}
.cnxw-advert ul,.cnxw-advert ol{padding-left:20px}

/* ------------------------------------------------------------ apply */
.cnxw-step[hidden]{display:none}
.cnxw-stepnav{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin:20px 0 0;
  padding-top:16px;border-top:1.5px solid var(--cnx-line)}
.cnxw-stepnav .cnxw-mut{margin:0}

/* an answer as pills: a bigger target than a bare radio, and the same
   shape as the filter pills the candidate has just used. The input
   stays in the DOM and stays operable by keyboard - the pill is its
   label, so nothing here invents a control that assistive tech cannot
   see. :has() gives the checked and focused states; a browser without
   it still shows the native control, which is why the input is only
   made small, never hidden. */
.cnxw-choices{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;border:0}
.cnxw-choices-col{flex-direction:column;flex-wrap:nowrap}
.cnxw-choice{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:9px 16px;
  border:1.5px solid var(--cnx-line);border-radius:99px;background:var(--cnx-bg);
  color:var(--cnx-ink);font-size:.9rem;font-weight:600;line-height:1.3;cursor:pointer}
.cnxw-choice:hover{border-color:var(--cnx-primary)}
.cnxw-choice input{width:16px;height:16px;flex:none;margin:0;accent-color:var(--cnx-primary)}
.cnxw-choice:has(input:checked){background:var(--cnx-primary);border-color:var(--cnx-primary);color:var(--cnx-bg)}
.cnxw-choice:has(input:focus-visible){outline:2px solid var(--cnx-primary);outline-offset:2px}
.cnxw-choices-col .cnxw-choice{border-radius:var(--cnxw-r);justify-content:flex-start;align-items:flex-start;font-weight:400}
.cnxw-fs{border:0;padding:0;margin:0 0 16px;min-width:0}
.cnxw-fs legend{display:block;font-size:.78rem;font-weight:700;letter-spacing:.02em;color:var(--cnx-ink);
  margin:0 0 6px;padding:0}
.cnxw-fs[data-invalid="1"] legend{color:var(--cnxw-bad)}
.cnxw-req{color:var(--cnxw-bad)}
/* Said to a screen reader, not shown. It belongs with the WIDGET rather
   than with the careers shell: a form fetched into a site page carries
   "(required)" after every asterisk, and on a page that does not link the
   careers shell it was simply visible. A candidate to promote into
   widgets.css when another tool needs it. */
/* .cnxw-sr moved to widgets.css - a second tool wanted it */
.cnxw-opt{color:var(--cnx-neutral);font-weight:400;text-transform:none;letter-spacing:0}
.cnxw-essential{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:99px;font-size:.68rem;
  font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  background:var(--cnxw-warn-bg);color:var(--cnxw-warn);vertical-align:middle}

/* the CV drop zone. It is a LABEL around a real <input type=file>, so a
   click, the keyboard and a drop all reach the same control; the size
   limit is written on it because a rejected upload after a slow phone
   connection is the worst way to learn it. Without script the input is
   shown plainly - .cnxw-drop-live is added by careers-widgets.js only
   once the drop handlers are attached. */
.cnxw-drop{display:block;cursor:pointer;position:relative}
.cnxw-drop:hover,.cnxw-drop.is-over{border-color:var(--cnx-primary);color:var(--cnx-ink)}
.cnxw-drop:has(input:focus-visible){outline:2px solid var(--cnx-primary);outline-offset:2px}
.cnxw-drop-live input[type="file"]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.cnxw-drop input[type="file"]{display:block;margin:12px auto 0;max-width:100%;font:inherit;font-size:.9rem}
.cnxw-drop-name{display:block;margin:10px 0 0;color:var(--cnx-ink);font-weight:600;word-break:break-word}

.cnxw-privacy{border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);background:var(--cnx-tint);
  padding:12px 15px;font-size:.86rem;color:var(--cnx-body);max-height:220px;overflow:auto;margin:0 0 12px}
.cnxw-privacy p:last-child{margin-bottom:0}
.cnxw-hp{position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;overflow:hidden}
.cnxw-count-chars{text-align:right}

/* the review step: what was typed, before it is sent */
.cnxw-review{margin:0}
.cnxw-review dt{color:var(--cnx-neutral);font-size:.74rem;text-transform:uppercase;letter-spacing:.05em;
  font-weight:700;margin:12px 0 2px}
.cnxw-review>dt:first-child{margin-top:0}
.cnxw-review dd{margin:0;color:var(--cnx-ink);word-break:break-word}

/* ----------------------------------------------------------- status */
.cnxw-status-top{display:flex;gap:12px;justify-content:space-between;align-items:center;
  margin:0 0 6px;flex-wrap:wrap}
.cnxw-status-top b{font-family:var(--cnx-heading-font);font-size:1.1rem;color:var(--cnx-ink);font-weight:600}
.cnxw-events{list-style:none;margin:0;padding:0}
.cnxw-events li{display:flex;gap:14px;justify-content:space-between;align-items:center;flex-wrap:wrap;
  padding:12px 0;border-top:1px solid var(--cnx-line)}
.cnxw-events li:first-child{border-top:0}
.cnxw-status-form{margin:0;display:contents}

/* ----------------------------------------------------------- alerts */
.cnxw-alerts-note{margin:8px 0 0}

/* ------------------------------------------------- shared small parts */
/* A standfirst under a heading, the editor's introduction above a widget,
   and the two wrappers the hiring markup needs. Small enough to live with
   Hiring rather than to earn a place in the primitives. */
.cnxw-lead{font-size:1.05rem;color:var(--cnx-ink);margin:0 0 16px;max-width:66ch}
.cnxw-intro{margin:0 0 18px;color:var(--cnx-body)}
.cnxw-intro>:last-child{margin-bottom:0}
.cnxw-form{margin:0}
.cnxw-featured{margin:0}
.cnxw-step-h{margin:0 0 6px}

/* --------------------------------------------------- container queries */
@container cnxw (max-width: 520px){
  .cnxw-job{grid-template-columns:minmax(0,1fr)}
  .cnxw-job-go .cnxw-btn{width:100%}
  .cnxw-strip{flex-direction:column;align-items:stretch}
  .cnxw-strip .cnxw-btn{width:100%}
  .cnxw-choices-2 .cnxw-choice{flex:1 1 100%}
  .cnxw-stepnav{flex-direction:column;align-items:stretch}
  .cnxw-stepnav .cnxw-actions{width:100%}
}

/* --- widgets.listings.css --- */
/* [coda]nomix LISTINGS WIDGETS.
   ------------------------------------------------------------------
   Listings is the generic engine every vertical sits on: projects,
   team, properties, stockists, anything with records. Its widgets are
   the collection grid, one item's page and a featured strip.

   The cards, grids, kv lines, pills and buttons are all the widget
   primitives in widgets.css. This file adds only what a RECORD needs
   that a card does not:

     .cnxw-li-filter   the "Filter  All Design Build" row
     .cnxw-li-gal      the hero-plus-thumbs gallery
     .cnxw-li-crumb    the "Our work > Harbour Cafe" line
     .cnxw-li-sec      a named section of a detail page

   No colour, face or corner is declared here - every one is a --cnx-*
   token, so a collection grid takes the site's palette untouched. */

/* ---------------------------------------------------- the tool's sections
   The same rule the events widgets keep: a widget reads --cnx-ink and
   --cnx-body, so its section takes --cnx-bg rather than whatever ground the
   page happens to have. Before sections.css, so a tinted look still wins. */
.cnx-collection,.cnx-listing,.cnx-featured{background:var(--cnx-bg)}

/* --------------------------------------------------------- the filter */
.cnxw-li-filter{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 12px}
.cnxw-li-filter .cnxw-pills{margin:0}
.cnxw-li-filter .cnxw-mut{margin-right:2px}
/* a card the filter has put away - the attribute, never an inline style */
.cnxw-li-card[hidden]{display:none!important}

/* ----------------------------------------------------------- the card */
.cnxw-li-name{display:block;color:var(--cnx-ink);font-weight:700;margin:0 0 2px}
.cnxw-li-name a{color:inherit;text-decoration:none}
.cnxw-li-name a:hover{text-decoration:underline}
.cnxw-li-meta{margin:0}
.cnxw-li-sum{margin:6px 0 0;color:var(--cnx-body);font-size:.93rem}
.cnxw-li-more{display:inline-block;margin-top:10px;color:var(--cnx-primary);font-weight:600;
  font-size:.9rem;text-decoration:none}
.cnxw-li-more:hover{text-decoration:underline}

/* -------------------------------------------------------- the item page */
.cnxw-li-crumb{font-size:.84rem;color:var(--cnx-neutral);margin:0 0 10px}
.cnxw-li-crumb a{color:inherit;text-decoration:none}
.cnxw-li-crumb a:hover{text-decoration:underline}

/* the wireframe's .gal: a tall hero with two stacked thumbs beside it */
.cnxw-li-gal{display:grid;grid-template-columns:2fr 1fr;grid-template-rows:1fr 1fr;gap:8px}
.cnxw-li-gal figure{margin:0;min-width:0}
.cnxw-li-gal figure:first-child{grid-row:1/span 2}
.cnxw-li-gal figure:first-child .cnxw-media{aspect-ratio:auto;min-height:220px;height:100%}
.cnxw-li-gal figcaption{font-size:.8rem;color:var(--cnx-neutral);margin-top:4px}
/* one row of equal frames, for a collection that would rather not lead */
.cnxw-li-gal-row{grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:auto}
.cnxw-li-gal-row figure:first-child{grid-row:auto}
.cnxw-li-gal-row figure:first-child .cnxw-media{aspect-ratio:4/3;min-height:0;height:auto}
/* a single frame, for a record whose one picture is the point */
.cnxw-li-gal-one{grid-template-columns:minmax(0,1fr);grid-template-rows:auto}
.cnxw-li-gal-one figure:first-child{grid-row:auto}

.cnxw-li-body{color:var(--cnx-body)}
.cnxw-li-body img{max-width:100%;height:auto}
.cnxw-li-sec{margin-top:22px}
.cnxw-li-sec>h2{font-family:var(--cnx-heading-font);color:var(--cnx-ink);font-size:1.2rem;margin:0 0 8px}
.cnxw-li-sec>h3,.cnxw-li-sec>h4{color:var(--cnx-ink);font-size:1rem;margin:12px 0 4px}
.cnxw-li-links{display:flex;flex-wrap:wrap;gap:8px}

/* -------------------------------------------------- container queries */
@container cnxw (max-width: 520px){
  .cnxw-li-gal{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto}
  .cnxw-li-gal figure:first-child{grid-column:1/span 2;grid-row:auto}
  .cnxw-li-gal figure:first-child .cnxw-media{min-height:170px}
  .cnxw-li-filter{align-items:stretch;flex-direction:column}
}

/* --- widgets.misc.css --- */
/* [coda]nomix WIDGETS - forms, mailer, search, navigation, menu extras.
   ------------------------------------------------------------------
   The five widgets in this file are the ones a visitor meets before
   they meet anything else: the enquiry form, the signup, the search
   box, the navigation and the two small Food Menus additions. Three of
   them are RUNTIMES - apps/form-embed.js, apps/m.php and apps/search.js
   build their markup in the browser - so the rules below are the other
   half of a contract those files keep: they emit cnxw-* primitives and
   the classes declared here, and nothing else.

   THE CONTRACT. Not one colour, face or corner is declared here. Every
   value reads a --cnx-* token or one of widgets.css's three semantic
   --cnxw-* vars, so a form is warm on a guesthouse and severe on a
   trades site without a line of this file changing. Nothing below
   re-declares a button, an input, a field, a card or a badge either:
   widgets.css owns those, and a widget that wants one asks for it.

   RESPONSIVE BY CONTAINER. Every root carries .cnxw, so the two widths
   that matter are the widget's own: 520px (stack; the navigation
   becomes a burger and a drawer) and 900px (the full layout). */

/* A TAP TARGET IS 44px. .cnxw-btn's own padding lands at 42, and every
   button in this file is somebody finishing something on a phone - sending
   an enquiry, subscribing, opening the menu - so these widgets ask for the
   extra two rather than editing the shared button for every widget in the
   system. Vertical padding, not min-height: min-height on an inline-block
   pads the bottom and leaves the words sitting high. */
.cnxw-formw .cnxw-btn,.cnxw-signupw .cnxw-btn,.cnxw-navw .cnxw-btn,
.cnxw-hlw .cnxw-btn,.cnxw-confirmw .cnxw-btn,.cnxw-drawer .cnxw-btn{padding-block:12px}

/* ------------------------------------------------------------ shell */
/* A widget dropped on a page is a band on that page, so it owns the
   air above and below it the way every section in sections.css does. */
.cnxw-sec{padding:clamp(32px,5vw,60px) 0}
.cnxw-sec-tight{padding:clamp(14px,2.2vw,24px) 0}

/* =================================================================
   FORM (contact-form) - apps/form.php?embed + apps/form-embed.js
   ================================================================= */
.cnxw-form{max-width:44rem}
/* The field grid IS the layout setting: stacked is one column,
   two-column pairs the short fields and lets a message span both. */
.cnxw-form-fields{display:grid;gap:0 var(--cnxw-gap);grid-template-columns:minmax(0,1fr)}
.cnxw-form-two-column .cnxw-form-fields{grid-template-columns:repeat(2,minmax(0,1fr))}
.cnxw-form-two-column .cnxw-f-wide{grid-column:1/-1}
/* two columns is a WIDE-CONTAINER choice, not a permanent one: in a narrow
   column, or on a phone, every field takes the width */
@container cnxw (max-width: 520px){
  .cnxw-form-two-column .cnxw-form-fields{grid-template-columns:minmax(0,1fr)}
}
/* the honeypot: off-screen, never display:none - a bot reads the CSS */
.cnxw-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.cnxw-opt{font-weight:400;color:var(--cnx-neutral)}
.cnxw-form .cnxw-actions{margin-top:4px}
.cnxw-form-foot{margin:10px 0 0}
/* the success card the form becomes: widgets.css's .cnxw-done, with the
   words the tool's own successMsg puts inside it reading as prose */
.cnxw-done>:first-child{margin-top:0}
.cnxw-done>:last-child{margin-bottom:0}

/* =================================================================
   NEWSLETTER SIGNUP (newsletter-signup) - apps/m.php?form=N
   ================================================================= */
/* Band is the tinted card the fragment already draws. Inline takes its
   ground away and lays the same content along one line, which is why
   the layout setting only ever removes rules here. */
.cnxw-signup-inline{border:0;background:none;border-radius:0}
.cnxw-signup-inline>.cnxw-card-body{padding:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px 22px}
.cnxw-signup-inline .cnxw-signup-say{flex:1 1 15rem;min-width:0}
.cnxw-signup-inline .cnxw-signup{flex:2 1 20rem;min-width:0}
.cnxw-signup-inline .cnxw-signup-note{flex:1 1 100%;margin:0}
.cnxw-signup-lead{font-weight:700;color:var(--cnx-ink);margin:0}
.cnxw-signup-say>.cnxw-eyebrow{margin-bottom:.2em}
.cnxw-signup-form{margin:8px 0 0}
.cnxw-signup-inline .cnxw-signup-form{margin:0}
.cnxw-signup-note{margin:8px 0 0}
@container cnxw (max-width: 520px){
  .cnxw-signup-inline>.cnxw-card-body{display:block}
  .cnxw-signup-inline .cnxw-signup-form{margin:10px 0 0}
}

/* =================================================================
   SITE SEARCH (misc-search) - apps/search.js
   ================================================================= */
.cnxw-search{position:relative;max-width:34rem}
/* a results PAGE is a page: the list wants the measure, the box does not */
.cnxw-search-page{max-width:52rem}
.cnxw-search-page .cnxw-search-in{max-width:34rem}
.cnxw-search-in{position:relative}
.cnxw-search-icon{position:absolute;left:15px;top:50%;transform:translateY(-50%);
  width:18px;height:18px;color:var(--cnx-neutral);pointer-events:none}
.cnxw-search-input{border-radius:99px;padding-left:44px}
.cnxw-search-input::-webkit-search-cancel-button{cursor:pointer}
/* A DROPDOWN floats over the page; a PAGE list sits in the flow under
   the box. One markup, one rule apart - which is the whole difference
   between "search from the header" and "the search results page". */
.cnxw-search-res{margin-top:8px;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-r);
  background:var(--cnx-bg);overflow:hidden auto;max-height:26rem}
.cnxw-search-drop .cnxw-search-res{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:60;
  box-shadow:0 24px 60px color-mix(in srgb,var(--cnx-ink) 18%,transparent)}
.cnxw-search-page .cnxw-search-res{position:static;max-height:none;border:0;border-radius:0;margin-top:18px}
.cnxw-search-hit{display:block;padding:13px 17px;text-decoration:none;color:inherit;
  border-top:1px solid var(--cnx-line)}
.cnxw-search-hit:first-child{border-top:0}
.cnxw-search-page .cnxw-search-hit{padding:16px 0}
.cnxw-search-page .cnxw-search-hit:first-child{border-top:1.5px solid var(--cnx-line)}
.cnxw-search-hit:hover,.cnxw-search-hit.is-on{background:var(--cnx-tint)}
/* Direct children only. The matched words inside a title and a snippet are
   marked with <b> too, and a descendant rule turned every highlighted word
   into its own line - a result that read as a column of fragments. */
.cnxw-search-hit>b{display:block;font-weight:600;color:var(--cnx-ink);font-size:.98rem}
.cnxw-search-hit>b b{color:var(--cnx-primary)}
.cnxw-search-hit>span{display:block;color:var(--cnx-neutral);font-size:.86rem;line-height:1.45;margin-top:2px}
.cnxw-search-hit>span b{color:var(--cnx-ink);font-weight:600}
.cnxw-search-res .cnxw-empty,.cnxw-search-res .cnxw-note{border-radius:0;border:0;margin:0}
.cnxw-search-skel{padding:13px 17px;border-top:1px solid var(--cnx-line)}
.cnxw-search-skel:first-child{border-top:0}
.cnxw-search-skel i{display:block;height:12px;margin-bottom:7px;width:45%}
.cnxw-search-skel u{display:block;height:10px;width:85%}

/* =================================================================
   NAVIGATION (misc-nav) - apps/nav.js
   ================================================================= */
.cnxw-navw{position:relative;z-index:40}
.cnxw-navw[data-sticky="1"]{position:sticky;top:0;background:var(--cnx-bg)}
.cnxw-navbar{display:flex;align-items:center;gap:22px;padding:14px 0;min-height:60px}
.cnxw-nav-brand{font-family:var(--cnx-heading-font);font-weight:700;font-size:1.15rem;
  color:var(--cnx-ink);text-decoration:none;white-space:nowrap}
.cnxw-nav-brand:hover{color:var(--cnx-primary)}
/* The menu markup inside is the SITE's - cdnmxUF_Navigation renders whatever
   the navMenus record says, and a site's own .cnx-nav rules live in
   sections.css, which is concatenated after this file. Equal specificity
   would hand every one of these to that sheet (it did: the drawer's list
   came out as a wrapped row), so each rule here carries the widget's own
   class as well and wins on merit rather than on file order. */
.cnxw-nav-menu{min-width:0}
.cnxw-navw .cnxw-nav-menu ul{display:flex;flex-wrap:wrap;align-items:center;gap:4px 22px;list-style:none;margin:0;padding:0}
.cnxw-navw .cnxw-nav-menu li{position:relative}
.cnxw-navw .cnxw-nav-menu a{text-decoration:none;color:var(--cnx-body);font-weight:600;font-size:.95rem;
  display:inline-block;padding:8px 0;min-height:34px}
.cnxw-navw .cnxw-nav-menu a:hover,.cnxw-navw .cnxw-nav-menu a[aria-current="page"],
.cnxw-navw .cnxw-nav-menu a.active{color:var(--cnx-primary)}
.cnxw-nav-end{margin-left:auto}
/* the three styles: where the brand, the menu and the action sit */
.cnxw-nav-bar .cnxw-nav-menu{margin-left:auto}
.cnxw-nav-bar .cnxw-nav-end{margin-left:0}
.cnxw-nav-split .cnxw-nav-menu{flex:1;display:flex;justify-content:center}
.cnxw-nav-centred .cnxw-navbar{flex-direction:column;gap:10px;text-align:center}
.cnxw-nav-centred .cnxw-nav-menu ul{justify-content:center}
.cnxw-nav-centred .cnxw-nav-end{margin-left:0}
/* the burger: never shown while the menu fits, always a real button */
.cnxw-nav-toggle{display:none;margin-left:auto;align-items:center;justify-content:center;
  width:46px;height:46px;padding:0;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);
  background:var(--cnx-bg);color:var(--cnx-ink);cursor:pointer}
.cnxw-nav-toggle i{display:block;position:relative;width:20px;height:2px;background:currentColor}
.cnxw-nav-toggle i::before,.cnxw-nav-toggle i::after{content:"";position:absolute;left:0;
  width:20px;height:2px;background:currentColor}
.cnxw-nav-toggle i::before{top:-6px}
.cnxw-nav-toggle i::after{top:6px}
/* the drawer: a real panel over the page, not the menu squashed */
.cnxw-drawer{position:fixed;inset:0;z-index:900;display:flex;justify-content:flex-end}
/* display:flex outranks the browser's own [hidden] rule, so a closed drawer
   stood wide open on every page until this line existed */
.cnxw-drawer[hidden]{display:none}
.cnxw-drawer-scrim{position:absolute;inset:0;background:color-mix(in srgb,var(--cnx-ink) 55%,transparent);border:0;padding:0}
.cnxw-drawer-panel{position:relative;width:min(88vw,340px);background:var(--cnx-bg);
  border-left:1.5px solid var(--cnx-line);padding:18px 22px 28px;overflow-y:auto;display:flex;flex-direction:column;gap:14px}
.cnxw-drawer-top{display:flex;align-items:center;justify-content:space-between;gap:14px}
.cnxw-drawer-close{width:44px;height:44px;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);
  background:var(--cnx-bg);color:var(--cnx-ink);font:inherit;font-size:1.3rem;line-height:1;cursor:pointer}
.cnxw-drawer .cnxw-drawer-menu ul{list-style:none;margin:0;padding:0;display:block}
.cnxw-drawer .cnxw-drawer-menu li{border-top:1px solid var(--cnx-line);position:static}
.cnxw-drawer .cnxw-drawer-menu li:first-child{border-top:0}
.cnxw-drawer .cnxw-drawer-menu a{display:block;padding:13px 0;min-height:44px;text-decoration:none;
  color:var(--cnx-ink);font-weight:600;font-size:1rem}
.cnxw-drawer .cnxw-drawer-menu a:hover{color:var(--cnx-primary)}
/* a submenu the site's own markup nests: indented, always open, never a
   panel floating over a drawer that is already a panel */
.cnxw-drawer .cnxw-drawer-menu .cnx-panel{position:static;display:block;padding-left:16px;
  opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;background:none;min-width:0}
body.cnxw-locked{overflow:hidden}
@container cnxw (max-width: 520px){
  .cnxw-nav-toggle{display:inline-flex}
  .cnxw-navbar>.cnxw-nav-menu,.cnxw-navbar>.cnxw-nav-end{display:none}
  .cnxw-nav-centred .cnxw-navbar{flex-direction:row;text-align:left}
}

/* =================================================================
   BREADCRUMB (misc-breadcrumb) and LANGUAGE SWITCHER (misc-lang)
   ================================================================= */
.cnxw-crumb{font-size:.86rem;color:var(--cnx-neutral)}
.cnxw-crumb ol,.cnxw-crumb ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center}
.cnxw-crumb a{color:var(--cnx-neutral);text-decoration:none}
.cnxw-crumb a:hover{color:var(--cnx-primary);text-decoration:underline}
.cnxw-crumb [aria-current="page"],.cnxw-crumb li:last-child{color:var(--cnx-ink)}
/* the separator the page tree does not supply: the trail reads as a
   trail whether the stored menu markup joins its items or not */
.cnxw-crumb li+li::before{content:"\203A";margin-right:10px;color:var(--cnx-neutral)}

.cnxw-lang{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.cnxw-lang .cnx-lang{text-decoration:none;color:var(--cnx-neutral);font-size:.82rem;
  font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.cnxw-lang .cnx-lang:hover{color:var(--cnx-primary)}
.cnxw-lang .cnx-lang-on{color:var(--cnx-ink)}
.cnxw-lang-pills .cnx-lang{border:1.5px solid var(--cnx-line);border-radius:99px;padding:6px 13px;min-height:34px;display:inline-flex;align-items:center}
.cnxw-lang-pills .cnx-lang-on{background:var(--cnx-primary);border-color:var(--cnx-primary);color:var(--cnx-bg)}

/* =================================================================
   CONFIRM AND UNSUBSCRIBE (misc-mail-confirm) - apps/m.php
   ================================================================= */
/* The same fragment twice over: a section on a page, and the document
   apps/m.php serves for the outcomes it decides itself. The body class is
   only ever on the second, and all it does is centre one card in a window
   with nothing else in it. */
.cnxw-confirmpage{display:grid;align-content:center;min-height:100vh;background:var(--cnx-tint)}
.cnxw-confirmpage .cnxw-wrap{max-width:38rem}

/* =================================================================
   FOOD MENUS EXTRAS (misc-menu-highlights, misc-dietary-key)
   ================================================================= */
.cnxw-hl-name{display:block;font-weight:700;color:var(--cnx-ink);margin:0 0 2px}
/* the strip sits on a tinted card, and .cnxw-badge's own ground IS the tint -
   so a dietary mark on it was invisible until it took the page's ground */
.cnxw-hl-name .cnxw-badge{margin-left:7px;vertical-align:2px;background:var(--cnx-bg)}
.cnxw-hl-what{display:block;color:var(--cnx-neutral);font-size:.88rem;line-height:1.45}
.cnxw-hl .cnxw-grid{--cnxw-gap:22px}

.cnxw-diet{display:flex;flex-wrap:wrap;gap:10px 26px;margin:0;align-items:baseline}
.cnxw-diet div{display:flex;gap:9px;align-items:baseline;margin:0}
.cnxw-diet dt{margin:0}
.cnxw-diet dd{margin:0;color:var(--cnx-neutral);font-size:.9rem}

/* --- widgets.nav.css --- */
/* =================================================================
   NAVIGATION - the fit rule and the menu recipe (misc-nav, apps/nav.js)

   Bundled after widgets.misc.css by name (cdnmxSectionLibraryToolCss globs
   widgets.*.css in order), so an equal-specificity rule here wins over the
   widget's base rules there. Tokens only: no colour of its own, like every
   widget sheet - one hex here and the bar stops belonging to its site.

   The bar is ONE LINE or it is not a bar. apps/nav.js measures brand, items
   and button; what would wrap folds into a "More" disclosure before the
   button. Below 520px of the container the burger and the drawer take over
   (widgets.misc.css) and the fold stands down.
   ================================================================= */
/* an item never breaks inside its own label - the fold is the only wrap */
.cnxw-navw .cnxw-nav-menu a{white-space:nowrap}
.cnxw-navw .cnxw-nav-menu li.cnxw-nav-morei{position:relative}
/* the disclosure: a real <details>, keyboard-reachable for free, 44px tall */
.cnxw-nav-more{position:relative}
.cnxw-nav-more>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
  min-height:44px;padding:5px 0;font-weight:600;font-size:.95rem;color:var(--cnx-body);white-space:nowrap;user-select:none}
.cnxw-nav-more>summary::-webkit-details-marker{display:none}
.cnxw-nav-more>summary::after{content:"";width:7px;height:7px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg);margin-top:-4px;transition:transform .15s}
.cnxw-nav-more>summary:hover,.cnxw-nav-more[open]>summary{color:var(--cnx-primary)}
.cnxw-nav-more[open]>summary::after{transform:rotate(-135deg);margin-top:3px}
.cnxw-nav-more>summary:focus-visible{outline:2px solid var(--cnx-primary);outline-offset:3px;border-radius:4px}
/* the folded items: a panel under the summary, never a second line. The
   selectors carry .cnxw-nav-menu because the base sheet's rules for "any ul,
   li, a in the menu" would otherwise outrank these and lay the panel out as
   a flex row. */
.cnxw-navw .cnxw-nav-menu ul.cnxw-nav-more-list{position:absolute;top:100%;right:0;z-index:60;min-width:220px;max-width:min(88vw,360px);
  margin:6px 0 0;padding:8px 0;list-style:none;display:block;flex-wrap:nowrap;
  background:var(--cnx-bg);border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);
  box-shadow:0 14px 34px color-mix(in srgb,var(--cnx-ink) 16%,transparent)}
.cnxw-navw .cnxw-nav-menu .cnxw-nav-more-list li{position:static;display:block}
.cnxw-navw .cnxw-nav-menu .cnxw-nav-more-list a{display:block;padding:10px 18px;min-height:44px;white-space:normal}
/* a submenu the site's own markup nests inside a folded item: indented and
   open, never a panel floating over a panel */
.cnxw-navw .cnxw-nav-menu .cnxw-nav-more-list .cnx-panel{position:static;display:block;padding-left:16px;
  opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;background:none;min-width:0}
.cnxw-nav-centred .cnxw-nav-menu ul.cnxw-nav-more-list{right:auto;left:50%;transform:translateX(-50%)}
/* the utility links live in the drawer and the footer, never in the bar */
.cnxw-nav-utility{display:none}
/* the drawer: menu, then the utility links after a rule, then the button
   full-width at the bottom */
.cnxw-drawer-utility{border-top:1px solid var(--cnx-line);padding-top:10px}
.cnxw-drawer-utility ul{list-style:none;margin:0;padding:0}
.cnxw-drawer-utility a{display:block;padding:11px 0;min-height:44px;text-decoration:none;color:var(--cnx-neutral);font-weight:500;font-size:.95rem}
.cnxw-drawer-utility a:hover{color:var(--cnx-primary)}
.cnxw-drawer-end{margin-top:auto;padding-top:8px}
.cnxw-drawer-end .cnxw-btn-block{justify-content:center;min-height:48px}

/* ---- the recipe on the kit shell (starterKits.php cdnmxKitPageHtml):
   the one button in the header, the link groups and utility links in the
   footer - the same links the drawer carries on a phone ---- */
.cnx-header .cnx-header-cta{white-space:nowrap}
.cnx-footer .cnx-footer-groups{display:flex;flex-wrap:wrap;gap:24px 48px;justify-content:center;text-align:left;margin:0 0 22px}
.cnx-footer .cnx-footer-group b{display:block;font-family:var(--cnx-heading-font);font-size:1rem;color:var(--cnx-ink);margin:0 0 8px}
.cnx-footer .cnx-footer-group ul,.cnx-footer .cnx-footer-utility{list-style:none;margin:0;padding:0}
.cnx-footer .cnx-footer-group li{margin:0 0 6px}
.cnx-footer .cnx-footer-groups a{color:var(--cnx-neutral);text-decoration:none}
.cnx-footer .cnx-footer-groups a:hover{color:var(--cnx-primary);text-decoration:underline}
.cnx-footer .cnx-footer-utility{flex-basis:100%;display:flex;flex-wrap:wrap;gap:8px 22px;justify-content:center;font-size:.85rem}

/* --- widgets.pms.css --- */
/* Hotel widgets: the calendar, the stay panel, and the room card's price.
   Everything else the booking wizard needs is a cnxw-* primitive. Not a
   colour, a face or a corner is declared here - a booking calendar on a
   guesthouse and one on a city hotel differ only in the site's tokens. */

/* the two-month calendar */
.cnxw-cal-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 12px}
.cnxw-cal-span{font-family:var(--cnx-heading-font);color:var(--cnx-ink);font-weight:600;font-size:1.05rem}
.cnxw-cal-months{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px}
.cnxw-cal-title{font-family:var(--cnx-heading-font);color:var(--cnx-ink);font-weight:600;text-align:center;margin:0 0 8px}
.cnxw-cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:3px}
.cnxw-cal-dow{text-align:center;font-size:.7rem;font-weight:700;letter-spacing:.04em;color:var(--cnx-neutral);padding:4px 0}
.cnxw-cal-pad{visibility:hidden}
/* A NIGHT IS A BUTTON. Its price is the second line, so a guest reads the
   month and the money in one pass instead of clicking to find out. */
.cnxw-cal-day{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
  min-height:44px;padding:5px 2px;border:1.5px solid transparent;border-radius:calc(var(--cnxw-ri) * .8);
  background:transparent;color:var(--cnx-ink);font:inherit;font-size:.9rem;font-weight:600;cursor:pointer;
  font-variant-numeric:tabular-nums}
/* the day number leads; the price is a second line that must never be the
   reason the number is squeezed out of its own cell */
.cnxw-cal-day{overflow:hidden;min-width:0}
.cnxw-cal-day>small{font-size:.62rem;font-weight:600;color:var(--cnx-neutral);letter-spacing:-.03em;
  max-width:100%;overflow:hidden;white-space:nowrap}
.cnxw-cal-day:hover:not([disabled]){border-color:var(--cnx-primary)}
/* taken, closed or past: shown and struck through, never hidden - a gap in
   a calendar is a question, a struck night is an answer */
.cnxw-cal-day.is-out{color:var(--cnx-neutral);opacity:.5;text-decoration:line-through;cursor:not-allowed}
.cnxw-cal-day.is-out small{display:none}
.cnxw-cal-day.is-span{background:var(--cnx-tint)}
.cnxw-cal-day.is-edge{background:var(--cnx-primary);color:var(--cnx-bg);border-color:var(--cnx-primary)}
.cnxw-cal-day.is-edge small{color:var(--cnx-bg);opacity:.8}

/* the stay panel's date boxes */
.cnxw-stay{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:center;
  padding:10px 12px;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-r);margin:0 0 10px}
.cnxw-stay-d{font-family:var(--cnx-heading-font);font-size:1.6rem;line-height:1;color:var(--cnx-primary);
  text-align:center;min-width:46px;font-variant-numeric:tabular-nums}
.cnxw-stay-d small{display:block;font-family:var(--cnx-body-font);font-size:.62rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--cnx-neutral);margin-top:2px}
.cnxw-stay b{display:block;color:var(--cnx-ink);font-size:.95rem}
.cnxw-stay .cnxw-mut{display:block}

/* a room card's price line, and the room page's spec grid */
.cnxw-room-price{font-family:var(--cnx-heading-font);font-size:1.25rem;color:var(--cnx-ink);font-weight:600}
.cnxw-room-price small{font-family:var(--cnx-body-font);font-size:.82rem;font-weight:400;color:var(--cnx-neutral)}
.cnxw-room-gal{display:grid;grid-template-columns:2fr 1fr;grid-template-rows:1fr 1fr;gap:8px}
.cnxw-room-gal>*:first-child{grid-row:1/span 2}
.cnxw-room-gal .cnxw-media{aspect-ratio:auto;height:100%;min-height:150px}

@container cnxw (max-width: 760px){
  .cnxw-cal-months{grid-template-columns:minmax(0,1fr);gap:16px}
}
@container cnxw (max-width: 520px){
  .cnxw-cal-day{min-height:46px;font-size:.95rem}
  .cnxw-cal-day small{display:none}
  .cnxw-room-gal{grid-template-columns:1fr 1fr;grid-template-rows:auto}
  .cnxw-room-gal>*:first-child{grid-column:1/span 2;grid-row:auto;min-height:180px}
}

/* ---- the wizard's summary: a sticky panel beside the calendar on a wide
   page, a bar along the bottom of the screen under 900px of the widget's
   own width. The bar (.cnxw-dock) is appended to <body> by booking.js: the
   widget root is a size container, and containment makes it the containing
   block for position:fixed, so a bar inside it would pin to the widget. */
.cnxw-quote-place{font-family:var(--cnx-heading-font);color:var(--cnx-ink);font-weight:600;margin:0 0 10px}
.cnxw-rule-words{font-size:.85rem;font-weight:600;color:var(--cnx-ink);margin:0 0 12px;padding:8px 10px;
  border-left:3px solid var(--cnx-accent);background:var(--cnx-tint);border-radius:0 var(--cnxw-ri) var(--cnxw-ri) 0}
.cnxw-counter .cnxw-label .cnxw-mut{font-weight:400;font-size:.75rem}
.cnxw-counters{margin:0 0 18px}
.cnxw.is-narrow .cnxw-quote{display:none}
.cnxw.is-docked{padding-bottom:84px}
.cnxw-dock{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--cnx-bg);color:var(--cnx-body);
  border-top:1.5px solid var(--cnx-line);box-shadow:0 -8px 24px rgba(0,0,0,.08)}
.cnxw-dock-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;
  padding-bottom:calc(10px + env(safe-area-inset-bottom,0px))}
.cnxw-dock-sum{display:flex;flex-direction:column;min-width:0}
.cnxw-dock-sum b{font-family:var(--cnx-heading-font);color:var(--cnx-ink);font-size:1.15rem;line-height:1.2}
.cnxw-dock-sum .cnxw-mut{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cnxw-dock-sheet{max-height:70vh;overflow:auto;border-top:1px solid var(--cnx-line)}
.cnxw-dock-sheet .cnxw-sticky{position:static}

/* extras: a list of rows with a stepper each */
.cnxw-extras-hd{margin-top:18px}
.cnxw-extras{margin:0 0 14px}
.cnxw-extra{display:flex;align-items:center;justify-content:space-between;gap:14px}
.cnxw-extra b{display:block;color:var(--cnx-ink)}
.cnxw-extra .cnxw-mut{display:block}

/* a room row's price and button, right-aligned */
.cnxw-room-buy{text-align:right;flex:none}
.cnxw-room-buy .cnxw-btn{margin-top:6px}

/* loading shapes, sized by class rather than by an attribute */
.cnxw-skel-tall{height:280px}
.cnxw-skel-mid{height:180px}

/* the rates table */
.cnxw-rates-wrap{overflow-x:auto}
.cnxw-rates{width:100%;border-collapse:collapse;font-size:.93rem}
.cnxw-rates th{text-align:left;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;color:var(--cnx-neutral);
  padding:0 12px 8px 0;border-bottom:1.5px solid var(--cnx-ink)}
.cnxw-rates td{padding:12px 12px 12px 0;border-bottom:1px solid var(--cnx-line);vertical-align:top;color:var(--cnx-ink)}
.cnxw-rates td b{display:block;font-family:var(--cnx-heading-font)}
.cnxw-rates td .cnxw-mut{display:block}
.cnxw-rates-closed td{color:var(--cnx-neutral)}

/* the confirmation */
.cnxw-done .cnxw-grid{margin:14px 0}
.cnxw-done-actions{margin-top:16px}
.cnxw-done-address{margin:12px 0 0;white-space:pre-line}

@container cnxw (max-width: 520px){
  .cnxw-counters{grid-template-columns:minmax(0,1fr)}
  .cnxw-extra{flex-wrap:wrap}
  .cnxw-room-buy{text-align:left;width:100%}
}

/* --- widgets.shop.css --- */
/* [coda]nomix SHOP WIDGETS - the shapes only a shop has.
   ------------------------------------------------------------------
   Everything a card, a button, an input, a badge, a grid or an empty
   state looks like is already decided in widgets.css. What is left is
   Shop-shaped: a work card's price line, a work page's gallery beside
   its buying column, a basket line, a checkout with its summary, an
   order's status card. Nothing here names a colour or a typeface -
   every value is one of the site's --cnx-* tokens or one of the three
   semantic vars the primitives declare.

   Responsive is by CONTAINER (@container cnxw), never by device, so a
   shop widget in a narrow column behaves like the phone view. */

/* ------------------------------------------------------- work cards */
/* The card is .cnxw-card; these are the parts inside it a work has and
   a generic card does not. Titles and captions are spans inside an <a>,
   so each has to be told it is a line of its own. */
.cdnmx-shop-work{display:block}
.cdnmx-shop-work-title{display:block}
.cdnmx-shop-work-medium{display:block;margin:2px 0 0}
.cdnmx-shop-work-price{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px}
.cdnmx-shop-work-price:empty{display:none}
/* a sold piece stays on the wall, quietly */
.cdnmx-shop-sold .cnxw-media img{opacity:.72}
.cdnmx-shop-collection+.cdnmx-shop-collection{margin-top:38px}
.cdnmx-shop-collection-head{margin:0 0 14px}
.cdnmx-shop-series{margin-top:26px}
/* "3 left" sits beside the price, never instead of it */
.cdnmx-shop-left{white-space:nowrap}

/* ------------------------------------------- the work grid's filters */
/* One row of groups above the grid, each a label and its pills, and the
   line that counts what they leave. The pills themselves are .cnxw-pill -
   44px targets, the site's own colours - so nothing here dresses them. */
.cnxw-shop-filters{display:flex;flex-wrap:wrap;gap:10px 26px;align-items:flex-start;margin:0 0 10px}
.cnxw-shop-filter{display:flex;gap:10px;align-items:center;flex-wrap:wrap;min-width:0}
.cnxw-shop-filter .cnxw-pills{margin:0}
.cnxw-shop-filter-lab{flex:none}
.cnxw-shop-count{margin:0 0 18px}
.cnxw-shop-none{margin-top:18px}
/* a filtered-away collection takes its heading with it */
.cdnmx-shop-filtered [hidden]{display:none!important}

/* --------------------------------- more from this collection */
.cnxw-shop-more{margin-top:44px;padding-top:26px;border-top:1.5px solid var(--cnx-line)}
.cnxw-shop-more .cnxw-eyebrow{margin-bottom:14px}
.cnxw-shop-more .cdnmx-shop-work-title{display:block}

/* --------------------------------------------- the collection index */
.cdnmx-shop-collection-tile{display:block}
.cdnmx-shop-collection-tile .cdnmx-shop-collection-name{display:block}
.cdnmx-shop-collection-tile .cdnmx-shop-collection-blurb{display:block;margin:2px 0 0}
.cdnmx-shop-collection-count{display:block;margin-top:8px}

/* ------------------------------------------------------- work page */
/* Picture left, the decision right; the buying column follows the page
   down on a wide screen (.cnxw-sticky already says how). */
.cnxw-shop-work-main{min-width:0}
.cnxw-shop-thumbs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-top:8px}
.cnxw-shop-thumb{padding:0;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);
  background:var(--cnx-bg);cursor:pointer;overflow:hidden;min-height:44px}
.cnxw-shop-thumb[aria-pressed="true"]{border-color:var(--cnx-primary)}
.cnxw-shop-gallery-stack>*+*{margin-top:10px}
.cnxw-shop-crumb{margin:0 0 6px}
/* the price the buyer is deciding on, bigger than a card's */
.cnxw-shop-bigprice{font-size:1.4rem}

/* --------------------------------------------------------- basket */
/* thumb, what it is, and what it costs - three columns that become two
   rows on a phone, with the picture holding its place. */
.cnxw-shop-line{display:grid;grid-template-columns:64px minmax(0,1fr) auto;gap:14px;align-items:center}
.cnxw-shop-line-pic{width:64px}
/* the piece's name owns its line, whether or not an edition follows it */
.cnxw-shop-line b{display:block}
.cnxw-shop-line-end{text-align:right;display:grid;gap:6px;justify-items:end}
.cnxw-shop-line-rm{border:0;background:transparent;color:var(--cnx-neutral);font:inherit;
  font-size:.85rem;text-decoration:underline;cursor:pointer;padding:6px 2px;min-height:44px}
.cnxw-shop-line-rm:hover{color:var(--cnxw-bad)}

/* ------------------------------------------------------- checkout */
.cnxw-shop-pay{margin:14px 0 0}
.cnxw-shop-pay-on{padding:14px;border:1.5px solid var(--cnx-line);border-radius:var(--cnxw-ri);background:var(--cnx-bg)}

/* --------------------------------------------------------- states */
/* the storefront's own page ground when it is NOT wearing a site shell */
.cnxw-shop-standalone{background:var(--cnx-bg);margin:0;padding:0}
.cnxw-shop-standalone .cnxw-wrap{padding-top:34px;padding-bottom:60px}
.cnxw-shop-top{display:flex;justify-content:space-between;align-items:center;gap:14px;margin:0 0 20px}
/* the loading shape a widget shows before its records arrive */
.cnxw-shop-skelcard{height:250px}
.cnxw-shop-skelline{height:14px;margin:12px 0}
.cnxw-shop-checkout-main{min-width:0}

/* ----------------------------------------------- container queries */
@container cnxw (max-width: 520px){
  /* the filter groups stack, and each label sits over its own pills rather
     than pushing them off the side of a phone */
  .cnxw-shop-filters{gap:12px}
  .cnxw-shop-filter{align-items:flex-start;flex-direction:column;gap:6px;width:100%}
  .cnxw-shop-line{grid-template-columns:56px minmax(0,1fr)}
  .cnxw-shop-line-pic{width:56px}
  .cnxw-shop-line-end{grid-column:1 / -1;justify-items:start;text-align:left}
  .cnxw-shop-thumbs{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* ------------------------------------- the 1.0 Shop section, intact */
/* sections.css dresses the ORIGINAL "Shop" section (.cnx-shop) against
   the same rendered markup these templates emit. Those rules are two
   classes deep and load after this file, so inside that one section
   they win - which is right, an existing page must not change shape.
   These three put back what the primitives now supply instead, so the
   old section does not end up with a card's padding twice over. */
.cnx-shop .cnxw-card .cdnmx-shop-work-title,
.cnx-shop .cnxw-card .cdnmx-shop-work-medium,
.cnx-shop .cnxw-card .cdnmx-shop-work-price{padding-left:0;padding-right:0}
.cnx-shop .cnxw-card .cnxw-media .cdnmx-shop-img{aspect-ratio:auto;height:100%}

/* [coda]nomix starter-kit section library.
   Every rule reads its colour and type from --cnx-* custom properties, which
   the kit's theme block sets. That is what makes "choose your colours" a
   token swap rather than a fork of the stylesheet, and what lets a preview
   restyle itself live. Nothing here hard-codes a brand colour. */
/* This sheet is linked from every page of every site, kit or not. The
   element rules below therefore only fire on a KIT page (body.cnx-s-*);
   everything else in the file is class-based and touches nothing it does
   not own. :where() keeps each rule at the specificity it had as a bare
   element selector, so every class rule that used to beat it still does -
   a plain body[class*=] prefix would have outranked .cnx-s-warm h2 and the
   white headings on the dark heroes. box-sizing also covers the sections'
   own boxes on a non-kit page: an input at width:100% with padding breaks
   without it, and nothing outside our sections is touched. */
:where(body[class*="cnx-s-"]) *,:where(body[class*="cnx-s-"]) *::before,:where(body[class*="cnx-s-"]) *::after,
:where(section[class*="cnx-"]) *,:where(section[class*="cnx-"]) *::before,:where(section[class*="cnx-"]) *::after{box-sizing:border-box}
:where(body[class*="cnx-s-"]){margin:0;font-family:var(--cnx-body-font);color:var(--cnx-body);background:var(--cnx-bg);line-height:1.6}
:where(body[class*="cnx-s-"]) h1,:where(body[class*="cnx-s-"]) h2,:where(body[class*="cnx-s-"]) h3{font-family:var(--cnx-heading-font);color:var(--cnx-ink);line-height:1.2;margin:0 0 .5em}
:where(body[class*="cnx-s-"]) h1{font-size:clamp(2rem,5vw,3.2rem)}
:where(body[class*="cnx-s-"]) h2{font-size:clamp(1.4rem,3vw,2rem)}
:where(body[class*="cnx-s-"]) h3{font-size:1.1rem}
:where(body[class*="cnx-s-"]) p{margin:0 0 1em}
:where(body[class*="cnx-s-"]) a{color:var(--cnx-primary)}
.cnx-wrap{max-width:1080px;margin:0 auto;padding:0 24px}

/* The LOOK setting every section carries (cnx-look-%opt_look%): three
   choices, closed. Declared this early on purpose - a section that owns its
   ground (the heroes, the closing band, the call to action, the marquee)
   declares its background later in the file and wins; the look only
   decides for sections that have no ground of their own. Plain is nothing. */
.cnx-look-tinted{background:var(--cnx-tint)}
.cnx-look-bordered{border-top:1px solid var(--cnx-line);border-bottom:1px solid var(--cnx-line)}

/* chrome */
.cnx-header{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:18px 24px;border-bottom:1px solid var(--cnx-line);flex-wrap:wrap}
.cnx-brand{text-decoration:none;font-family:var(--cnx-heading-font);font-weight:700;font-size:1.15rem;color:var(--cnx-ink)}
.cnx-logo{max-height:44px;width:auto;display:block}
.cnx-nav ul{display:flex;gap:20px;list-style:none;margin:0;padding:0;flex-wrap:wrap}
.cnx-nav a{text-decoration:none;color:var(--cnx-body);font-weight:600;font-size:.95rem}
.cnx-nav a:hover,.cnx-nav a[aria-current="page"]{color:var(--cnx-primary)}
.cnx-footer{border-top:1px solid var(--cnx-line);padding:28px 24px;text-align:center;color:var(--cnx-neutral);font-size:.9rem}

/* sections */
/* zero specificity, our sections only: .cnx-facts and friends set their own */
:where(section[class*="cnx-"]){padding:calc(64px * var(--cnx-sp,1)) 0}
.cnx-hero{background:var(--cnx-tint);text-align:center}
.cnx-eyebrow{text-transform:uppercase;letter-spacing:.08em;font-size:.78rem;font-weight:700;color:var(--cnx-primary);margin:0 0 .6em}
.cnx-lede{font-size:1.15rem;max-width:56ch;margin:0 auto 1.4em}
.cnx-btn{display:inline-block;background:var(--cnx-primary);color:#fff;text-decoration:none;font-weight:600;padding:13px 26px;border-radius:8px}
.cnx-btn:hover{background:var(--cnx-secondary)}
.cnx-btn-invert{background:#fff;color:var(--cnx-primary)}
.cnx-grid-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:24px}
.cnx-card,.cnx-person{border:1px solid var(--cnx-line);border-radius:12px;padding:24px;background:var(--cnx-bg)}
.cnx-role{color:var(--cnx-primary);font-weight:600;margin:0 0 .5em}
.cnx-features-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:28px}
.cnx-features-list li{border-left:3px solid var(--cnx-accent);padding-left:16px}
.cnx-stats{background:var(--cnx-tint)}
.cnx-stat{text-align:center}
.cnx-stat-n{display:block;font-family:var(--cnx-heading-font);font-size:2.6rem;font-weight:700;color:var(--cnx-primary);line-height:1}
.cnx-stat-l{display:block;font-size:.9rem;color:var(--cnx-neutral)}
.cnx-testimonial-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:24px}
.cnx-testimonial{margin:0;border:1px solid var(--cnx-line);border-radius:12px;padding:24px;background:var(--cnx-bg)}
.cnx-testimonial cite{font-style:normal;font-weight:600;color:var(--cnx-neutral);font-size:.9rem}
.cnx-logos-title{text-align:center;font-size:.85rem;text-transform:uppercase;letter-spacing:.08em;color:var(--cnx-neutral)}
.cnx-logo-grid{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:36px;justify-content:center;align-items:center;color:var(--cnx-neutral);font-weight:700}
.cnx-cta{background:var(--cnx-primary);color:#fff;text-align:center}
.cnx-cta h2{color:#fff}
.cnx-map-embed{border:1px dashed var(--cnx-line);border-radius:12px;padding:48px;text-align:center;color:var(--cnx-neutral)}
.cnx-address{font-weight:600;color:var(--cnx-ink)}
.cnx-hours-list{display:grid;grid-template-columns:1fr auto;gap:8px 24px;max-width:420px;margin:0}
.cnx-hours-list dt{font-weight:600;color:var(--cnx-ink)}
.cnx-hours-list dd{margin:0;text-align:right}
.cnx-prose p{max-width:66ch}
.cnx-signup{background:var(--cnx-tint);text-align:center}
.cnx-signup-form{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:520px;margin:0 auto}
.cnx-signup-form label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.cnx-signup-form input,.cnx-signup-input{flex:1 1 240px;padding:12px 14px;border:1px solid var(--cnx-line);border-radius:8px;font:inherit}
.cnx-signup-msg{flex:1 1 100%;margin:0;font-size:.9rem}
.cnx-signup-msg:empty{display:none}
.cnx-signup-form button,.cnx-form button,.cnx-contact .cdnmx-form form button{background:var(--cnx-primary);color:#fff;border:0;border-radius:8px;padding:12px 24px;font:inherit;font-weight:600;cursor:pointer}
.cnx-form,.cnx-contact .cdnmx-form form{display:grid;gap:6px;max-width:560px}
.cnx-form label,.cnx-contact .cdnmx-form form label{font-weight:600;color:var(--cnx-ink);font-size:.9rem;margin-top:8px}
.cnx-form input,.cnx-form textarea,.cnx-contact .cdnmx-form form input,.cnx-contact .cdnmx-form form textarea,.cnx-contact .cdnmx-form form select{padding:12px 14px;border:1px solid var(--cnx-line);border-radius:8px;font:inherit;width:100%;background:var(--cnx-bg);color:var(--cnx-ink)}
.cnx-contact .cdnmx-form form label.cf-check input{width:auto}
.cnx-form button,.cnx-contact .cdnmx-form form button{margin-top:14px;justify-self:start}
.cnx-contact .cdnmx-form form input:focus,.cnx-contact .cdnmx-form form textarea:focus,.cnx-contact .cdnmx-form form select:focus{outline:none;border-color:var(--cnx-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--cnx-primary) 15%,transparent)}
@media(max-width:640px){:where(section[class*="cnx-"]){padding:calc(44px * var(--cnx-sp,1)) 0}.cnx-header{justify-content:center}}

/* ---- vertical-specific sections ------------------------------------ */
.cnx-tier{border:1px solid var(--cnx-line);border-radius:12px;padding:24px;background:var(--cnx-bg);display:flex;flex-direction:column}
.cnx-tier-lead,.cnx-tiers .cnx-tier:nth-child(2){border-color:var(--cnx-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--cnx-primary) 18%,transparent)}
.cnx-tier ul{list-style:none;margin:0 0 auto;padding:0}
.cnx-tier li{padding:5px 0;border-bottom:1px solid var(--cnx-line);font-size:.95rem}
.cnx-tier li:last-child{border-bottom:0}
.cnx-tier p:last-child{margin:18px 0 0}
.cnx-price{font-family:var(--cnx-heading-font);font-size:1.5rem;font-weight:700;color:var(--cnx-primary);margin:0 0 .6em}
.cnx-pricelist{max-width:640px;margin:0}
.cnx-priceline{display:flex;justify-content:space-between;gap:24px;align-items:baseline;padding:12px 0;border-bottom:1px solid var(--cnx-line)}
.cnx-priceline dt{font-weight:600;color:var(--cnx-ink)}
.cnx-priceline dd{margin:0;font-weight:700;color:var(--cnx-primary);white-space:nowrap}
.cnx-dur{font-weight:400;color:var(--cnx-neutral);font-size:.85rem;margin-left:8px}
.cnx-pricenote{margin-top:18px;color:var(--cnx-neutral);font-size:.9rem}
.cnx-product,.cnx-room{border:1px solid var(--cnx-line);border-radius:12px;overflow:hidden;background:var(--cnx-bg)}
.cnx-product h3,.cnx-room h3{margin:16px 20px 4px}
.cnx-product p,.cnx-room p{margin:0 20px 16px}
.cnx-product .cnx-price,.cnx-room .cnx-price{font-size:1.15rem;margin:0 20px 8px}
.cnx-product-img,.cnx-room-img{aspect-ratio:4/3;background:var(--cnx-tint)}
.cnx-whatson,.cnx-foodmenu{background:var(--cnx-tint)}
.cnx-faqlist{max-width:720px}
.cnx-faqitem{border-bottom:1px solid var(--cnx-line);padding:14px 0}
.cnx-faqitem summary{font-family:var(--cnx-heading-font);font-weight:600;color:var(--cnx-ink);cursor:pointer;font-size:1.02rem}
.cnx-faqitem p{margin:10px 0 0}
.cnx-gallery-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}
.cnx-shot{margin:0;aspect-ratio:var(--cnxw-ar,1/1);border-radius:var(--cnx-radius,12px);background:var(--cnx-tint);border:1px solid var(--cnx-line)}
.cnx-shot>a{position:absolute;inset:0;display:block;color:inherit;border-radius:inherit;overflow:hidden}
.cnx-shot>a:focus-visible{outline:2px solid var(--cnx-primary);outline-offset:2px}
.cnx-shot>a>img{width:100%;height:100%;object-fit:cover;display:block}
.cnx-shot>a>img[src=""],.cnx-shot>a>img:not([src]){display:none}
html.cnxe-on .cnx-shot>a>img[src=""]{display:block;opacity:0;cursor:pointer}
@container cnxw (max-width: 520px){.cnx-gallery-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}}
.cnx-arealist{list-style:none;margin:18px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.cnx-arealist li{border:1px solid var(--cnx-line);border-radius:20px;padding:6px 14px;font-size:.9rem;color:var(--cnx-neutral)}
.cnx-booking{background:var(--cnx-tint)}
.cnx-booking-embed{border:1px dashed var(--cnx-line);border-radius:12px;padding:40px;text-align:center;color:var(--cnx-neutral);margin-top:20px}

/* Preview only: where a CMS-driven block (events, food menus) will render
   once the site is published. Never reaches a published page - the preview
   endpoint swaps the token for this, the generator runs it for real. */
.cnx-preview-token{border:1px dashed var(--cnx-line);border-radius:12px;padding:32px;text-align:center;
  color:var(--cnx-neutral);font-size:.9rem;background:var(--cnx-bg)}


/* ---- split hero -------------------------------------------------------
   Text one side, media the other. The reference sites a client points at are
   almost never centred: a portrait, a plate or a pair of hands sits beside
   the headline and does half the persuading. The media panel falls back to
   the kit's own device, so a kit with no photograph still reads as designed
   rather than as a missing image. */
.cnx-hero-split{position:relative;background:var(--cnx-bg);border-bottom:1px solid var(--cnx-line);overflow:hidden}
/* The device washes the whole band, not just the media panel. On the sites a
   client points at, the texture runs behind everything and the photograph
   sits on top of it - confining it to one box turns an identity into a
   swatch. */
.cnx-hero-split::before{content:"";position:absolute;inset:0;pointer-events:none;
  background-image:var(--cnx-device);background-size:cover;background-position:center}
.cnx-hero-split>*{position:relative}
/* left-aligned, like every reference: a centred column of text beside an
   image reads as a slide, not a website */
.cnx-hero-split .cnx-wrap{text-align:left}
.cnx-split{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(24px,5vw,64px);align-items:center;
  padding-top:calc(clamp(40px,6vw,86px) * var(--cnx-sp,1));padding-bottom:calc(clamp(40px,6vw,86px) * var(--cnx-sp,1))}
.cnx-split-text h1{font-size:clamp(2.1rem,4.6vw,3.5rem);line-height:1.05;letter-spacing:-.025em;margin:.35em 0 .5em}
.cnx-split-text .cnx-lede{font-size:clamp(1rem,1.3vw,1.13rem);max-width:44ch;color:var(--cnx-body)}
.cnx-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin:1.6em 0 0}
.cnx-btn-quiet{display:inline-block;padding:13px 20px;border-radius:8px;font-weight:600;
  border:1px solid var(--cnx-line);color:var(--cnx-ink);text-decoration:none}
.cnx-btn-quiet:hover{border-color:var(--cnx-primary);color:var(--cnx-primary)}
.cnx-trust{margin:1.5em 0 0;font-size:.86rem;color:var(--cnx-body);opacity:.85}
/* With a photograph this is simply the photograph. Without one it has to
   look like a decision rather than a gap, so the fallback is a tinted panel
   carrying the kit's device at a readable scale - the same texture as the
   band behind it, one step stronger. A flat grey box reads as a broken
   image, which is worse than no panel at all. */
.cnx-split-media{
  min-height:clamp(280px,38vw,460px);border-radius:14px;
  background-color:color-mix(in srgb,var(--cnx-primary) 8%,#fff);
  background-image:var(--cnx-hero-img,var(--cnx-device));
  background-size:cover;background-position:center;
  box-shadow:0 24px 60px rgba(16,24,40,.10);
  border:1px solid color-mix(in srgb,var(--cnx-primary) 12%,transparent);
}
@media(max-width:860px){
  .cnx-split{grid-template-columns:1fr}
  .cnx-split-media{min-height:230px;order:-1}
}

/* ---- credibility furniture --------------------------------------------
   Star rows, an attribution with a place, a small mark on each card. None of
   it is decoration: it is what separates a page that looks like a business
   from one that looks like a template with the words swapped. */
.cnx-section-lede{max-width:56ch;color:var(--cnx-body);margin:-.4em 0 2em;font-size:1.03rem}
/* A solid accent tile, not a device-filled box - at 34px the texture just
   read as a broken image. */
.cnx-card-mark{display:block;width:38px;height:38px;border-radius:10px;margin-bottom:16px;
  background:var(--cnx-accent);opacity:.9;
  -webkit-mask:radial-gradient(circle at 30% 30%,transparent 22%,#000 23%) center/100% 100%;
          mask:radial-gradient(circle at 30% 30%,transparent 22%,#000 23%) center/100% 100%}
.cnx-stars{color:var(--cnx-accent);letter-spacing:.14em;font-size:.86rem;margin-bottom:.7em}
.cnx-testimonial cite{display:block;font-style:normal;font-weight:650;margin-top:1em;color:var(--cnx-ink)}
.cnx-testimonial cite span{display:block;font-weight:400;font-size:.86rem;color:var(--cnx-body);margin-top:2px}

/* The accent has to appear somewhere a person looks. On every reference the
   primary action is the accent colour, not the same navy as the headings -
   a palette nobody can point to is a palette that was not chosen. */
.cnx-hero-split .cnx-btn{background:var(--cnx-accent);border-color:var(--cnx-accent);color:#fff}
.cnx-hero-split .cnx-btn:hover{filter:brightness(.93)}
.cnx-hero-split .cnx-eyebrow{color:var(--cnx-accent);letter-spacing:.14em}

/* =======================================================================
   STYLES
   -----------------------------------------------------------------------
   One section library, five ways of arranging it. Everything above is the
   neutral base; everything below is a kit declaring what KIND of site it is.

   This is the alternative to forking the library per kit. A hero, a service
   card and a testimonial each exist once; a style decides whether the header
   is centred or ranged left, whether a card has a border or a photograph on
   top, whether sections alternate ground or run on white, and how loud the
   headings are. Adding a sixth style is a block of CSS, not twenty files.
   ======================================================================= */

/* ---- editorial ---------------------------------------------------------
   Consultancy and agency work. Everything ranged left, headline set tight
   and large, hairline rules instead of boxes, and a lot of air. Cards lose
   their border entirely - the grid does the separating. */
.cnx-s-editorial .cnx-header{border-bottom:1px solid var(--cnx-line)}
.cnx-s-editorial h2{font-size:clamp(1.6rem,2.9vw,2.3rem);letter-spacing:-.02em}
.cnx-s-editorial .cnx-card{border:0;background:transparent;padding:0 0 0 18px;
  border-left:2px solid var(--cnx-accent);border-radius:0}
.cnx-s-editorial .cnx-card-mark{display:none}
.cnx-s-editorial section+section{border-top:1px solid var(--cnx-line)}
.cnx-s-editorial .cnx-testimonial{border:0;border-top:2px solid var(--cnx-line);border-radius:0;padding:22px 0 0}

/* ---- warm --------------------------------------------------------------
   Restaurants and hospitality. The logo goes over the middle with the nav
   beneath it in small caps, the media panel is arched, and sections
   alternate between white and a tinted ground so the page reads as courses
   rather than as a scroll. */
.cnx-s-warm .cnx-header{flex-direction:column;gap:12px;text-align:center;padding-top:26px;padding-bottom:20px}
.cnx-s-warm .cnx-nav ul{justify-content:center;gap:26px}
.cnx-s-warm .cnx-nav a{text-transform:uppercase;letter-spacing:.14em;font-size:.78rem}
.cnx-s-warm .cnx-wordmark{font-size:1.6rem}
.cnx-s-warm .cnx-split-media{border-radius:220px 220px 14px 14px}
/* :not(.cnx-cta) matters: the call to action paints its own brand background
   with white text on it, and the banding was overriding it - white on cream,
   which is not a contrast failure you notice in a palette, only on a page. */
.cnx-s-warm section:nth-of-type(even):not(.cnx-cta):not(.cnx-pagehead):not(.cnx-marquee):not(.cnx-ctaband):not(.cnx-hero):not(.cnx-pull):not(.cnx-facts){background:var(--cnx-tint)}
.cnx-s-warm h2{text-align:center}
.cnx-s-warm .cnx-section-lede{margin-left:auto;margin-right:auto;text-align:center}
.cnx-s-warm .cnx-card{text-align:center;border-radius:14px}
.cnx-s-warm .cnx-card-mark{margin-left:auto;margin-right:auto}

/* ---- industrial --------------------------------------------------------
   Trades and construction. Dark header the full width of the window, square
   corners everywhere, uppercase nav, and a thick accent rule under each
   heading. Nothing soft: the sites this imitates are selling reliability. */
.cnx-s-industrial .cnx-header{background:var(--cnx-secondary);border-bottom:4px solid var(--cnx-accent);padding:18px 26px}
.cnx-s-industrial .cnx-header a,.cnx-s-industrial .cnx-wordmark{color:#fff}
.cnx-s-industrial .cnx-nav a{text-transform:uppercase;letter-spacing:.08em;font-weight:700;font-size:.82rem}
.cnx-s-industrial h1,.cnx-s-industrial h2,.cnx-s-industrial h3{text-transform:uppercase;letter-spacing:-.01em}
.cnx-s-industrial h2{border-bottom:4px solid var(--cnx-accent);display:inline-block;padding-bottom:6px}
.cnx-s-industrial .cnx-card,.cnx-s-industrial .cnx-testimonial,
.cnx-s-industrial .cnx-split-media,.cnx-s-industrial .cnx-btn,
.cnx-s-industrial .cnx-btn-quiet,.cnx-s-industrial .cnx-card-mark{border-radius:0}
.cnx-s-industrial .cnx-card{border:1px solid var(--cnx-line);box-shadow:6px 6px 0 var(--cnx-tint)}
.cnx-s-industrial .cnx-footer{background:var(--cnx-secondary);color:#fff}

/* ---- calm --------------------------------------------------------------
   Therapy, wellness, anything where the reader is anxious. Centred, very
   generous, no borders at all, wider leading than the base. The design gets
   out of the way. */
.cnx-s-calm .cnx-header{flex-direction:column;gap:10px;text-align:center;padding:30px 26px;border-bottom:0}
.cnx-s-calm .cnx-nav ul{justify-content:center;gap:28px}
.cnx-s-calm .cnx-wrap{max-width:960px}
.cnx-s-calm section{padding-top:calc(clamp(48px,7vw,96px) * var(--cnx-sp,1));padding-bottom:calc(clamp(48px,7vw,96px) * var(--cnx-sp,1))}
.cnx-s-calm p{line-height:1.85}
.cnx-s-calm h2{text-align:center;font-weight:500}
.cnx-s-calm .cnx-card,.cnx-s-calm .cnx-testimonial{border:0;background:transparent;text-align:center;padding:0}
.cnx-s-calm .cnx-card-mark{display:none}
.cnx-s-calm .cnx-section-lede{margin-left:auto;margin-right:auto;text-align:center}
.cnx-s-calm .cnx-split-media{border-radius:999px 999px 18px 18px}
.cnx-s-calm .cnx-stars{text-align:center}

/* ---- shopfront ---------------------------------------------------------
   Independent retail. Compact and busy in a good way: a tight header with
   the strapline beside the name, denser grid, and cards that lead with a
   coloured cap so a shelf of them reads as products. */
.cnx-s-shopfront .cnx-header{padding-top:14px;padding-bottom:14px}
.cnx-s-shopfront .cnx-nav a{font-weight:600}
.cnx-s-shopfront .cnx-wrap{max-width:1180px}
.cnx-s-shopfront section{padding-top:calc(clamp(32px,4.5vw,60px) * var(--cnx-sp,1));padding-bottom:calc(clamp(32px,4.5vw,60px) * var(--cnx-sp,1))}
.cnx-s-shopfront .cnx-grid-3{gap:14px}
.cnx-s-shopfront .cnx-card{border-radius:10px;padding-top:0;overflow:hidden;border:1px solid var(--cnx-line)}
.cnx-s-shopfront .cnx-card-mark{width:auto;height:8px;border-radius:0;margin:0 -16px 16px;
  -webkit-mask:none;mask:none;background:var(--cnx-accent);opacity:1}
.cnx-s-shopfront h2{font-size:clamp(1.4rem,2.4vw,1.9rem)}
.cnx-s-shopfront .cnx-testimonial{border-radius:10px}

/* ---- story ------------------------------------------------------------
   The second photograph. A page with one picture in the hero and none after
   it reads as a template with a header image; the reference sites all carry
   the story - the bread, the bench, the window - somewhere in the middle.
   Falls back to the device like the hero does, so kits without a second
   picture still compose. */
.cnx-story-in{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,5vw,60px);align-items:center}
.cnx-story-media{min-height:clamp(240px,30vw,400px);border-radius:14px;
  background-color:color-mix(in srgb,var(--cnx-primary) 8%,#fff);
  background-image:var(--cnx-story-img,var(--cnx-device));background-size:cover;background-position:center}
.cnx-story-text h2{margin:.2em 0 .5em}
.cnx-story-text p{max-width:46ch}
.cnx-story-more{margin-top:1.4em}
@media(max-width:820px){.cnx-story-in{grid-template-columns:1fr}}

/* each style arranges it differently, which is the point of a style */
.cnx-s-editorial .cnx-story-in{grid-template-columns:.9fr 1.1fr}
.cnx-s-editorial .cnx-story-media{order:2}              /* picture to the right */
.cnx-s-warm .cnx-story-media{border-radius:200px 14px 200px 14px}
.cnx-s-warm .cnx-story-text{text-align:center}
.cnx-s-warm .cnx-story-text p{margin-left:auto;margin-right:auto}
.cnx-s-industrial .cnx-story-media{border-radius:0;box-shadow:14px 14px 0 var(--cnx-tint)}
.cnx-s-industrial .cnx-story-in{gap:clamp(28px,6vw,72px)}
.cnx-s-calm .cnx-story-in{grid-template-columns:1fr;max-width:720px;margin:0 auto;text-align:center}
.cnx-s-calm .cnx-story-media{border-radius:18px;min-height:300px}
.cnx-s-calm .cnx-story-text p{margin-left:auto;margin-right:auto}
.cnx-s-shopfront .cnx-story-in{grid-template-columns:1.15fr .85fr;gap:26px}
.cnx-s-shopfront .cnx-story-media{border-radius:10px;min-height:240px}
/* AND THE STACK RULE HAS TO OUTRANK THEM. The one above is `.cnx-story-in`,
   one class; each style's is `.cnx-s-x .cnx-story-in`, two - so on every
   editorial and shopfront site the story block stayed two columns down to
   320px, with four words a line beside a picture the size of a stamp. The
   media query is not the problem; specificity is. Repeated here, after
   them, at their weight. */
@media(max-width:820px){
  .cnx-s-editorial .cnx-story-in,
  .cnx-s-shopfront .cnx-story-in{grid-template-columns:1fr}
  .cnx-s-editorial .cnx-story-media{order:0}            /* picture first, as every other style stacks it */
}

/* ---- the centred hero carries the imagery too --------------------------
   hero-split shows its picture in a panel; hero-banner had nowhere to put
   one, so fifteen kits composed a hero image and then never displayed it.
   The banner now sits ON the image behind a veil heavy enough to keep dark
   text readable - which is also the full-bleed treatment most restaurant and
   venue sites use anyway. */
/* A flat veil at 80%+ turned every photograph into a pale wash. This one is
   a gradient: dense behind the words, thin at the edges - so the picture is
   visible and the text is still readable on it. */
.cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed){
  background-image:
    radial-gradient(120% 90% at 50% 45%,rgba(255,255,255,.94) 0%,rgba(255,255,255,.80) 42%,rgba(255,255,255,.34) 100%),
    var(--cnx-hero-img,var(--cnx-device));
  background-size:cover,cover;background-position:center,center;
}
.cnx-s-industrial .cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed){
  background-image:
    linear-gradient(100deg,rgba(255,255,255,.95) 0%,rgba(255,255,255,.80) 46%,rgba(255,255,255,.22) 100%),
    var(--cnx-hero-img,var(--cnx-device));
}
.cnx-s-calm .cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed){
  background-image:
    radial-gradient(130% 95% at 50% 45%,rgba(255,255,255,.95) 0%,rgba(255,255,255,.86) 46%,rgba(255,255,255,.46) 100%),
    var(--cnx-hero-img,var(--cnx-device));
}

/* ---- page header -------------------------------------------------------
   A subpage had nothing at the top but its first content block, so the
   per-page photograph had nowhere to appear and every inside page looked
   like a fragment of the home page. A band with the page's own name over
   its own picture is what almost every real site does here. */
.cnx-pagehead{position:relative;padding:calc(clamp(46px,7vw,92px) * var(--cnx-sp,1)) 0;border-bottom:1px solid var(--cnx-line);
  background-color:var(--cnx-tint);
  background-image:linear-gradient(100deg,rgba(255,255,255,.93) 0%,rgba(255,255,255,.72) 50%,rgba(255,255,255,.25) 100%),var(--cnx-hero-img,var(--cnx-device));
  background-size:cover;background-position:center}
.cnx-pagehead h1{margin:.1em 0 0;font-size:clamp(1.9rem,3.6vw,2.9rem);letter-spacing:-.02em;line-height:1.08}
.cnx-pagehead .cnx-eyebrow{color:var(--cnx-accent)}
.cnx-s-warm .cnx-pagehead,.cnx-s-calm .cnx-pagehead{text-align:center}
.cnx-s-industrial .cnx-pagehead{border-bottom:4px solid var(--cnx-accent)}
.cnx-s-industrial .cnx-pagehead h1{text-transform:uppercase}
.cnx-s-shopfront .cnx-pagehead{padding:calc(clamp(30px,4vw,54px) * var(--cnx-sp,1)) 0}

/* =======================================================================
   THE PASS
   -----------------------------------------------------------------------
   Everything above makes five styles structurally different. This makes
   them worth looking at. One committed move each, and the discipline to
   keep everything around it quiet.
   ======================================================================= */

/* ---- industrial: put the words ON the photograph -----------------------
   The reference sites for trades are dark. A builder selling reliability
   does not want a pale wash behind his headline - he wants the site to look
   like the work. White type on a darkened photograph, an accent slab where
   the eye lands first, and nothing rounded anywhere. */
.cnx-s-industrial .cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed),
.cnx-s-industrial .cnx-pagehead{
  background-image:
    linear-gradient(100deg,rgba(12,17,24,.90) 0%,rgba(12,17,24,.74) 52%,rgba(12,17,24,.42) 100%),
    var(--cnx-hero-img,var(--cnx-device));
  color:#fff;
}
.cnx-s-industrial .cnx-hero h1,.cnx-s-industrial .cnx-pagehead h1,
.cnx-s-industrial .cnx-hero .cnx-lede,.cnx-s-industrial .cnx-hero p{color:#fff}
.cnx-s-industrial .cnx-hero .cnx-eyebrow,.cnx-s-industrial .cnx-pagehead .cnx-eyebrow{color:var(--cnx-accent)}
.cnx-s-industrial .cnx-hero-split{background:var(--cnx-secondary)}
.cnx-s-industrial .cnx-hero-split .cnx-split-text h1,
.cnx-s-industrial .cnx-hero-split .cnx-split-text .cnx-lede,
.cnx-s-industrial .cnx-hero-split .cnx-trust{color:#fff}
.cnx-s-industrial .cnx-hero-split .cnx-btn-quiet{border-color:rgba(255,255,255,.45);color:#fff}
.cnx-s-industrial .cnx-hero-split::before{opacity:.35}
/* the slab: a hard accent bar the width of the headline, doing the work a
   rounded button cannot */
.cnx-s-industrial .cnx-hero-split .cnx-split-text .cnx-eyebrow{
  display:inline-block;background:var(--cnx-accent);color:#0c1118;
  padding:5px 12px;font-weight:800;letter-spacing:.1em}
.cnx-s-industrial h1{font-weight:800;line-height:.98}
.cnx-s-industrial .cnx-split-media{box-shadow:18px 18px 0 var(--cnx-accent)}

/* ---- editorial: the headline is the design ----------------------------
   Consultancies sell judgement, so the page is set like something written
   rather than assembled: one very large headline, a measure that stops
   where it should, and services indexed rather than boxed. */
.cnx-s-editorial .cnx-split-text h1{font-size:clamp(2.4rem,5.4vw,4.1rem);letter-spacing:-.034em;font-weight:700}
.cnx-s-editorial .cnx-split-text .cnx-lede{font-size:1.14rem;max-width:38ch;color:var(--cnx-ink);opacity:.78}
.cnx-s-editorial .cnx-eyebrow{letter-spacing:.18em;font-size:.72rem}
.cnx-s-editorial .cnx-grid-3{counter-reset:svc;gap:0}
.cnx-s-editorial .cnx-card{counter-increment:svc;border-left:0;padding:26px 26px 26px 0;position:relative}
.cnx-s-editorial .cnx-grid-3 .cnx-card+.cnx-card{border-top:0;border-left:1px solid var(--cnx-line);padding-left:26px}
.cnx-s-editorial .cnx-card h3::before{
  content:counter(svc,decimal-leading-zero);display:block;
  font-size:.72rem;letter-spacing:.14em;color:var(--cnx-accent);margin-bottom:10px;font-weight:700}
.cnx-s-editorial .cnx-card h3{font-size:1.06rem}
.cnx-s-editorial .cnx-pagehead h1{font-size:clamp(2.2rem,5vw,3.6rem);letter-spacing:-.03em}

/* ---- warm: the arch, and a menu's manners -----------------------------
   Hospitality sites are set like a menu: centred, generous, small caps, and
   a rule with something in the middle of it. The arch from the hero repeats
   at the section heads so the page has one idea rather than five. */
.cnx-s-warm h2{position:relative;padding-bottom:.5em}
.cnx-s-warm h2::after{
  content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  width:74px;height:1px;background:var(--cnx-accent);opacity:.65}
.cnx-s-warm .cnx-eyebrow{letter-spacing:.22em;font-size:.7rem}
.cnx-s-warm .cnx-split-text h1{font-size:clamp(2.2rem,4.6vw,3.4rem);line-height:1.06}
.cnx-s-warm .cnx-card{background:transparent;border:0;padding:6px 12px}
.cnx-s-warm .cnx-card h3{font-size:1.04rem;letter-spacing:.01em}
.cnx-s-warm .cnx-btn{border-radius:0;letter-spacing:.06em;text-transform:uppercase;font-size:.8rem;padding:14px 26px}
.cnx-s-warm .cnx-btn-quiet{border-radius:0;letter-spacing:.06em;text-transform:uppercase;font-size:.8rem;padding:13px 24px}
.cnx-s-warm .cnx-pagehead{border-bottom:0}

/* ---- calm: air, and almost nothing else -------------------------------
   The move here is restraint: bigger pictures, smaller type, more space
   than feels comfortable, and no borders at all. Someone deciding whether
   to ring a therapist should not meet a busy page. */
.cnx-s-calm .cnx-wrap{max-width:880px}
.cnx-s-calm section{padding-top:calc(clamp(64px,9vw,128px) * var(--cnx-sp,1));padding-bottom:calc(clamp(64px,9vw,128px) * var(--cnx-sp,1))}
.cnx-s-calm .cnx-split-text h1{font-size:clamp(1.9rem,3.4vw,2.7rem);font-weight:400;line-height:1.22;letter-spacing:-.012em}
.cnx-s-calm .cnx-split-text .cnx-lede{font-size:1.04rem;line-height:1.9;max-width:42ch}
.cnx-s-calm .cnx-eyebrow{letter-spacing:.26em;font-size:.68rem;opacity:.9}
.cnx-s-calm h2{font-size:clamp(1.4rem,2.4vw,1.9rem);font-weight:400;letter-spacing:-.008em}
.cnx-s-calm .cnx-btn{border-radius:999px;padding:14px 30px;font-weight:500;letter-spacing:.02em}
.cnx-s-calm .cnx-btn-quiet{border-radius:999px;padding:13px 28px;font-weight:500}
.cnx-s-calm .cnx-story-media{min-height:clamp(320px,42vw,520px)}
.cnx-s-calm .cnx-testimonial p{font-size:1.08rem;line-height:1.85;font-style:italic}
.cnx-s-calm .cnx-pagehead{border-bottom:0;padding:calc(clamp(56px,8vw,110px) * var(--cnx-sp,1)) 0}

/* ---- shopfront: a shelf, not a page ------------------------------------
   Retail wants density and price. Tighter rhythm, a hairline grid that
   reads as shelving, and the accent used as a tag rather than a wash. */
.cnx-s-shopfront .cnx-split-text h1{font-size:clamp(2rem,4vw,3rem);letter-spacing:-.028em;font-weight:750}
.cnx-s-shopfront .cnx-eyebrow{display:inline-block;background:var(--cnx-accent);color:#fff;
  padding:4px 10px;border-radius:3px;letter-spacing:.1em;font-size:.68rem;font-weight:700}
.cnx-s-shopfront .cnx-grid-3{gap:1px;background:var(--cnx-line);border:1px solid var(--cnx-line);border-radius:10px;overflow:hidden}
.cnx-s-shopfront .cnx-card{border:0;border-radius:0;background:var(--cnx-bg);padding:20px}
.cnx-s-shopfront .cnx-card-mark{margin:-20px -20px 16px}
.cnx-s-shopfront .cnx-btn{border-radius:6px;font-weight:700}
.cnx-s-shopfront .cnx-pagehead{border-bottom:2px solid var(--cnx-accent)}

/* ---- shared craft ------------------------------------------------------
   Small things that read as care rather than as decoration. */
.cnx-btn{transition:transform .12s ease,filter .12s ease}
.cnx-btn:hover{transform:translateY(-1px);filter:brightness(.95)}
.cnx-card h3,.cnx-testimonial cite{text-wrap:balance}
:where(body[class*="cnx-s-"]) h1,:where(body[class*="cnx-s-"]) h2{text-wrap:balance}
@media(prefers-reduced-motion:reduce){.cnx-btn{transition:none}.cnx-btn:hover{transform:none}}

/* ══════════════════════════════════════════════════════════════════
   ARCHITECTURE
   Twenty kits drawn from one set of bands were twenty palettes of the
   same website. These are the shapes that were missing: a full-bleed
   hero, a type-only hero, a ticker, a facts strip, routes, steps, a
   timetable, a captioned work grid, a pull quote, a closing band. A
   kit picks a handful; no two kits pick the same handful.
   ══════════════════════════════════════════════════════════════════ */

/* ── hero: full-bleed photograph ───────────────────────────────── */
.cnx-hero-full{position:relative;isolation:isolate;display:grid;align-items:end;
  min-height:min(86vh,760px);padding:0;overflow:hidden;
  background-image:var(--cnx-hero-img,var(--cnx-device));
  background-size:cover;background-position:center}
.cnx-hero-full>*{position:relative;z-index:1}
/* A scrim, not a wash. Type sits in the dark end and the picture keeps
   its top third, which is where a photograph usually has its subject. */
.cnx-hero-full .cnx-hero-scrim{position:absolute;inset:0;z-index:0;
  background:linear-gradient(180deg,rgba(8,12,18,.14) 0%,rgba(8,12,18,.42) 46%,rgba(8,12,18,.86) 100%)}
.cnx-hero-full-in{padding-block:0 clamp(52px,7vw,96px);max-width:min(var(--cnx-wrap,1180px),100%)}
.cnx-hero-full .cnx-eyebrow{color:#fff;opacity:.86}
.cnx-hero-full h1{color:#fff;max-width:16ch;margin:0 0 .5em}
.cnx-hero-full .cnx-lede{color:rgba(255,255,255,.88);max-width:52ch}
.cnx-hero-full .cnx-btn-ghost{display:inline-block;padding:.72em 1.5em;border:1px solid rgba(255,255,255,.6);
  color:#fff;text-decoration:none;border-radius:inherit}
.cnx-hero-full .cnx-btn-ghost:hover{background:rgba(255,255,255,.12)}
.cnx-hero-foot{position:absolute;left:0;right:0;bottom:0;z-index:1;margin:0;padding:.7em 1.2em;
  text-align:center;font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(255,255,255,.74);background:rgba(8,12,18,.5)}
.cnx-hero-foot:empty{display:none}

/* ── hero: editorial, type only, picture below ─────────────────── */
.cnx-hero-ed{padding-bottom:0;background:var(--cnx-bg)}
.cnx-hero-ed h1{font-size:clamp(2.6rem,7.4vw,6rem);line-height:.94;letter-spacing:-.035em;
  max-width:14ch;margin:.12em 0 .5em}
.cnx-hero-ed-foot{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:clamp(20px,4vw,56px);
  align-items:end;padding-bottom:clamp(34px,5vw,58px);border-bottom:1px solid var(--cnx-line)}
.cnx-hero-ed-foot .cnx-lede{margin:0;max-width:46ch}
.cnx-hero-ed-foot .cnx-actions{margin:0;white-space:nowrap}
.cnx-hero-ed-band{height:clamp(240px,42vw,470px);margin-top:clamp(34px,5vw,58px);
  background-image:var(--cnx-hero-img,var(--cnx-device));background-size:cover;background-position:center}
@media(max-width:720px){.cnx-hero-ed-foot{grid-template-columns:1fr}}

/* ── marquee ───────────────────────────────────────────────────── */
.cnx-marquee{display:flex;gap:0;overflow:hidden;padding:0;
  background:var(--cnx-ink);color:#fff;border-block:1px solid var(--cnx-ink)}
.cnx-marquee-track{display:flex;align-items:center;gap:1.6em;flex:0 0 auto;
  padding:.92em 1.6em .92em 0;white-space:nowrap;
  font-size:.86rem;letter-spacing:.16em;text-transform:uppercase;
  animation:cnx-slide 26s linear infinite}
.cnx-marquee-track span{flex:0 0 auto}
.cnx-marquee-track span:nth-child(even){color:var(--cnx-accent)}
@keyframes cnx-slide{from{transform:translateX(0)}to{transform:translateX(-100%)}}
@media(prefers-reduced-motion:reduce){
  .cnx-marquee-track{animation:none}
  .cnx-marquee-track+.cnx-marquee-track{display:none}
}

/* ── facts strip ───────────────────────────────────────────────── */
.cnx-facts{padding-block:calc(clamp(26px,3.4vw,42px) * var(--cnx-sp,1));border-bottom:1px solid var(--cnx-line);background:var(--cnx-bg)}
.cnx-facts-in{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,2.4vw,32px)}
.cnx-fact{display:flex;flex-direction:column;gap:.3em;padding-left:clamp(14px,2vw,26px);
  border-left:1px solid var(--cnx-line)}
.cnx-fact:first-child{padding-left:0;border-left:0}
.cnx-fact-v{font-family:var(--cnx-heading-font);font-size:clamp(1.7rem,3.4vw,2.6rem);
  line-height:1;color:var(--cnx-ink);font-variant-numeric:tabular-nums}
.cnx-fact-l{font-size:.82rem;letter-spacing:.1em;text-transform:uppercase;color:var(--cnx-body)}
@media(max-width:620px){.cnx-facts-in{grid-template-columns:1fr 1fr}.cnx-fact:nth-child(3){display:none}}

/* ── choose your route ─────────────────────────────────────────── */
.cnx-path-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,2vw,24px);margin-top:clamp(22px,3vw,38px)}
.cnx-path{display:flex;flex-direction:column;text-decoration:none;color:inherit;overflow:hidden;
  border:1px solid var(--cnx-line);background:var(--cnx-bg);transition:transform .18s ease,box-shadow .18s ease}
.cnx-path-img{display:block;aspect-ratio:4/3;background-size:cover;background-position:center;background-color:var(--cnx-tint)}
.cnx-path:nth-child(1) .cnx-path-img{background-image:var(--cnx-gal-1,var(--cnx-device))}
.cnx-path:nth-child(2) .cnx-path-img{background-image:var(--cnx-gal-3,var(--cnx-device))}
.cnx-path:nth-child(3) .cnx-path-img{background-image:var(--cnx-gal-5,var(--cnx-device))}
.cnx-path-body{display:flex;flex-direction:column;gap:.35em;padding:clamp(16px,2vw,24px)}
.cnx-path-body strong{font-family:var(--cnx-heading-font);font-size:1.18rem;color:var(--cnx-ink)}
.cnx-path-body span{color:var(--cnx-body);font-size:.95rem}
.cnx-path:hover{transform:translateY(-3px);box-shadow:0 14px 30px rgba(16,24,40,.10)}
@media(prefers-reduced-motion:reduce){.cnx-path:hover{transform:none}}
@media(max-width:760px){.cnx-path-grid{grid-template-columns:1fr}}

/* ── steps. Numbered because it IS a sequence. ─────────────────── */
.cnx-step-list{counter-reset:cnxstep;list-style:none;margin:clamp(22px,3vw,38px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,3vw,40px)}
.cnx-step-list li{counter-increment:cnxstep;padding-top:1.1em;border-top:2px solid var(--cnx-ink)}
.cnx-step-list li::before{content:counter(cnxstep,decimal-leading-zero);display:block;
  font-family:var(--cnx-heading-font);font-size:.9rem;letter-spacing:.14em;
  color:var(--cnx-accent);margin-bottom:.7em}
.cnx-step-list h3{margin:0 0 .35em;font-size:1.16rem}
.cnx-step-list p{margin:0;color:var(--cnx-body)}
@media(max-width:760px){.cnx-step-list{grid-template-columns:1fr}}

/* ── timetable ─────────────────────────────────────────────────── */
/* One flat list of sessions, each row naming its day, rather than a column
   per day: a repeatable stamps one template, and a day cannot own a nested
   run of rows. The day sits in the first column in the small caps the day
   heading used to wear, and the rule under the first row does the job the
   heading's rule did. */
.cnx-tt-grid{display:grid;grid-template-columns:1fr;max-width:760px;margin-top:clamp(22px,3vw,38px);border-top:2px solid var(--cnx-ink)}
.cnx-tt-day{font-family:var(--cnx-heading-font);font-size:.8rem;letter-spacing:.16em;text-transform:uppercase;color:var(--cnx-ink)}
.cnx-tt-row{display:grid;grid-template-columns:7em 5.4em minmax(0,1fr) auto;gap:.9em;align-items:baseline;
  padding:.86em 0;border-bottom:1px solid var(--cnx-line)}
.cnx-tt-time{font-variant-numeric:tabular-nums;color:var(--cnx-accent);font-weight:600}
.cnx-tt-name{color:var(--cnx-ink);font-family:var(--cnx-heading-font)}
.cnx-tt-where{font-size:.84rem;color:var(--cnx-body);text-align:right}
@media(max-width:680px){
  .cnx-tt-row{grid-template-columns:5.2em 4.6em minmax(0,1fr)}.cnx-tt-where{display:none}}

/* ── captioned work grid ───────────────────────────────────────── */
.cnx-work-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(20px,3.2vw,46px);margin-top:clamp(22px,3vw,38px)}
.cnx-work{margin:0}
.cnx-work-img{display:block;aspect-ratio:4/3;background-size:cover;background-position:center;
  background-color:var(--cnx-tint)}
.cnx-work:nth-child(1) .cnx-work-img{background-image:var(--cnx-gal-1,var(--cnx-device))}
.cnx-work:nth-child(2) .cnx-work-img{background-image:var(--cnx-gal-2,var(--cnx-device))}
.cnx-work:nth-child(3) .cnx-work-img{background-image:var(--cnx-gal-3,var(--cnx-device))}
.cnx-work:nth-child(4) .cnx-work-img{background-image:var(--cnx-gal-4,var(--cnx-device))}
.cnx-work figcaption{display:block;margin-top:.85em;font-size:.92rem;color:var(--cnx-ink)}
.cnx-work figcaption span{display:block;margin-top:.16em;font-size:.82rem;color:var(--cnx-body)}
.cnx-work figcaption span:empty{display:none}
@media(max-width:680px){.cnx-work-grid{grid-template-columns:1fr}}

/* ── pull quote. One voice, large, no card. ────────────────────── */
.cnx-pull{padding-block:calc(clamp(56px,8vw,110px) * var(--cnx-sp,1));background:var(--cnx-tint)}
.cnx-pull blockquote{margin:0;max-width:24ch}
.cnx-pull p{font-family:var(--cnx-heading-font);font-size:clamp(1.5rem,3.6vw,2.6rem);
  line-height:1.18;letter-spacing:-.018em;color:var(--cnx-ink);margin:0 0 .8em;text-wrap:balance}
.cnx-pull p::before{content:"\201C"}
.cnx-pull p::after{content:"\201D"}
.cnx-pull cite{font-style:normal;font-size:.86rem;letter-spacing:.12em;text-transform:uppercase;color:var(--cnx-body)}
.cnx-pull cite span{display:block;margin-top:.25em;letter-spacing:.04em;text-transform:none;opacity:.75}

/* ── closing band ──────────────────────────────────────────────── */
.cnx-ctaband{padding-block:calc(clamp(64px,9vw,124px) * var(--cnx-sp,1));text-align:center;
  background:var(--cnx-ink);color:#fff;
  background-image:linear-gradient(rgba(8,12,18,.82),rgba(8,12,18,.94)),var(--cnx-gal-5,var(--cnx-device));
  background-size:cover;background-position:center}
.cnx-ctaband .cnx-eyebrow{color:var(--cnx-accent)}
.cnx-ctaband h2{color:#fff;margin:.2em auto .7em;max-width:18ch;text-wrap:balance}
.cnx-ctaband h2::after{display:none}
.cnx-ctaband-note{margin:1.1em 0 0;font-size:.86rem;color:rgba(255,255,255,.66)}
.cnx-ctaband-note:empty{display:none}

/* ── page opener: title and standfirst, no band ────────────────── */
.cnx-introlede{padding-block:calc(clamp(46px,6vw,86px) * var(--cnx-sp,1)) calc(clamp(20px,2.6vw,34px) * var(--cnx-sp,1))}
.cnx-introlede h1{margin:0 0 .34em;max-width:18ch}
.cnx-introlede p{margin:0;max-width:56ch;font-size:1.08rem;color:var(--cnx-body)}
.cnx-introlede p:empty{display:none}
/* The page's own photograph. page-header sets type ON the picture; this
   opener keeps the type on the page and puts the picture underneath it -
   a different shape, but the subpage still shows the image the kit
   shipped for it rather than declaring one nothing ever draws. */
.cnx-introlede-band{height:clamp(170px,26vw,320px);margin-top:clamp(26px,3.4vw,44px);
  background-image:var(--cnx-hero-img,var(--cnx-device));background-size:cover;background-position:center}

/* Gallery shots were tinted rectangles. They cycle the kit's own
   photographs now - the same pictures its hero and subpages use. */
.cnx-shot{background-size:cover;background-position:center}
.cnx-gallery-grid .cnx-shot:nth-child(6n+1){background-image:var(--cnx-gal-1,var(--cnx-device))}
.cnx-gallery-grid .cnx-shot:nth-child(6n+2){background-image:var(--cnx-gal-2,var(--cnx-device))}
.cnx-gallery-grid .cnx-shot:nth-child(6n+3){background-image:var(--cnx-gal-3,var(--cnx-device))}
.cnx-gallery-grid .cnx-shot:nth-child(6n+4){background-image:var(--cnx-gal-4,var(--cnx-device))}
.cnx-gallery-grid .cnx-shot:nth-child(6n+5){background-image:var(--cnx-gal-5,var(--cnx-device))}
.cnx-gallery-grid .cnx-shot:nth-child(6n+6){background-image:var(--cnx-gal-6,var(--cnx-device))}

/* ── the two new heroes own their own ground ───────────────────────
   The wash selectors above predate them and would paint a pale veil
   over both. They are excluded there; everything they need is here. */
.cnx-hero.cnx-hero-full,.cnx-hero.cnx-hero-ed{text-align:left}
.cnx-hero.cnx-hero-ed{background-image:none;background-color:var(--cnx-bg)}
.cnx-hero.cnx-hero-full{background-color:var(--cnx-ink)}
/* On a dark photograph the primary button was near-black on near-black.
   The accent is the only colour in the palette that survives here. */
.cnx-hero-full .cnx-btn{background:var(--cnx-accent);color:#0c1118;border-color:var(--cnx-accent)}
.cnx-hero-full .cnx-btn-quiet{border-color:rgba(255,255,255,.55);color:#fff}
/* Warm and calm centre their heroes; the other three range left. */
.cnx-s-warm .cnx-hero.cnx-hero-full,.cnx-s-calm .cnx-hero.cnx-hero-full{text-align:center}
.cnx-s-warm .cnx-hero-full h1,.cnx-s-calm .cnx-hero-full h1{margin-inline:auto}
.cnx-s-warm .cnx-hero-full .cnx-lede,.cnx-s-calm .cnx-hero-full .cnx-lede{margin-inline:auto}
/* Industrial wants the picture harder and the type heavier; calm wants
   the picture to stay a picture. */
.cnx-s-industrial .cnx-hero-full .cnx-hero-scrim{
  background:linear-gradient(180deg,rgba(8,12,18,.10) 0%,rgba(8,12,18,.34) 40%,rgba(8,12,18,.88) 100%)}
.cnx-s-industrial .cnx-hero-full h1{text-transform:uppercase;font-weight:800;line-height:.96}
.cnx-s-calm .cnx-hero-full .cnx-hero-scrim{
  background:linear-gradient(180deg,rgba(8,12,18,.06) 0%,rgba(8,12,18,.26) 44%,rgba(8,12,18,.72) 100%)}
.cnx-s-editorial .cnx-hero-ed h1{letter-spacing:-.04em}
/* An accent eyebrow over a mid-tone photograph fails contrast on the
   light parts of the picture. A shadow, not a heavier colour. */
.cnx-hero-full .cnx-eyebrow,.cnx-hero-full .cnx-lede,.cnx-hero-full h1{
  text-shadow:0 1px 18px rgba(8,12,18,.55)}
/* The pull quote measured itself in ch on the blockquote, where the font
   is still body size - so a 24ch cap became ~190px and a long quote fell
   into a column ten characters wide. The measure belongs on the element
   that carries the display size. */
.cnx-pull blockquote{max-width:none}
.cnx-pull p{max-width:26ch}
/* Product cards were tinted rectangles for the same reason the gallery
   was: nothing was ever pointed at them. */
.cnx-product-img{background-size:cover;background-position:center}
.cnx-grid-3 .cnx-product:nth-child(1) .cnx-product-img{background-image:var(--cnx-gal-2,var(--cnx-device))}
.cnx-grid-3 .cnx-product:nth-child(2) .cnx-product-img{background-image:var(--cnx-gal-3,var(--cnx-device))}
.cnx-grid-3 .cnx-product:nth-child(3) .cnx-product-img{background-image:var(--cnx-gal-4,var(--cnx-device))}

/* ── two things that read as broken rather than designed ───────────
   The accent slab behind an eyebrow was drawn for a three-word tagline.
   Given a long one it wraps into a solid rectangle two lines deep that
   looks like a banner nobody finished. Cloned box decoration makes it
   read as highlighted text at any length, which was always the intent. */
.cnx-s-industrial .cnx-hero-split .cnx-split-text .cnx-eyebrow,
.cnx-s-shopfront .cnx-eyebrow{
  display:inline;box-decoration-break:clone;-webkit-box-decoration-break:clone;
  padding:.28em .6em;line-height:1.85}
/* The card glyph is a 38px accent square with a bite out of it. At a
   glance, in a card that also has a heading and a paragraph, it reads as
   a picture that failed to load. A rule under the heading says the same
   thing - this card is one of a set - without pretending to be an image. */
.cnx-card-mark{width:34px;height:3px;border-radius:0;margin-bottom:18px;opacity:1;
  -webkit-mask:none;mask:none}
.cnx-s-industrial .cnx-card-mark{width:44px;height:4px}
.cnx-hours-note{margin:1.1em 0 0;font-size:.9rem;color:var(--cnx-body)}
.cnx-hours-note:empty{display:none}
/* The shopfront eyebrow is an accent tag. On the closing band, which sets
   its eyebrow to the accent colour, that became accent-on-accent: a solid
   red slab with invisible words in it. The band owns its own ground, so
   the tag treatment comes off here. */
.cnx-ctaband .cnx-eyebrow{background:none;padding:0;color:var(--cnx-accent)}
.cnx-hero-full .cnx-eyebrow{background:none;padding:0}

/* ══════════════════════════════════════════════════════════════════
   SLOTTED
   The fragments are slotted now - the same markup is a kit section and
   a Canvas section definition. Two things that asked of the stylesheet:
   pictures live in the markup, and every section carries a look.
   ══════════════════════════════════════════════════════════════════ */

/* ── pictures in the markup ─────────────────────────────────────────
   Every box that used to be a CSS background keeps that background (the
   kit's device, the gallery cycle) and gains an inner <img>. A picked
   picture fills the box; an empty one is hidden, so the background shows
   through exactly as it did when nothing had been chosen. Absolute
   positioning, not height:100%, because half these boxes size themselves
   with min-height or aspect-ratio and a percentage height would not
   resolve against either. */
.cnx-split-media,.cnx-story-media,.cnx-work-img,.cnx-path-img,.cnx-shot,
.cnx-room-img,.cnx-product-img,.cnx-hero-ed-band,.cnx-introlede-band{position:relative;overflow:hidden}
:is(.cnx-split-media,.cnx-story-media,.cnx-work-img,.cnx-path-img,.cnx-shot,.cnx-room-img,.cnx-product-img,.cnx-hero-ed-band,.cnx-introlede-band)>img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;margin:0}
:is(.cnx-split-media,.cnx-story-media,.cnx-work-img,.cnx-path-img,.cnx-shot,.cnx-room-img,.cnx-product-img,.cnx-hero-ed-band,.cnx-introlede-band)>img[src=""],
:is(.cnx-split-media,.cnx-story-media,.cnx-work-img,.cnx-path-img,.cnx-shot,.cnx-room-img,.cnx-product-img,.cnx-hero-ed-band,.cnx-introlede-band)>img:not([src]){display:none}

/* The sections whose picture IS the ground - the centred hero, the page
   header, the full-bleed hero, the closing band - carry it as a first
   child <img class="cnx-bg"> laid under everything. It sits above the
   section's own background (the device fallback) and below the content.
   The veil those sections paint in their background-image would be UNDER
   a picked picture, so when one is present the same veil is painted again
   on ::before, over the picture; with no picture, nothing changes. The
   full-bleed hero already has its scrim and is left alone. */
.cnx-hero,.cnx-pagehead,.cnx-ctaband{position:relative;isolation:isolate}
.cnx-hero>.cnx-wrap,.cnx-pagehead>.cnx-wrap,.cnx-ctaband>.cnx-wrap{position:relative;z-index:1}
.cnx-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;margin:0;z-index:-1;border-radius:0}
.cnx-bg[src=""],.cnx-bg:not([src]){display:none}
.cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed):has(>.cnx-bg:not([src=""]))::before,
.cnx-pagehead:has(>.cnx-bg:not([src=""]))::before,
.cnx-ctaband:has(>.cnx-bg:not([src=""]))::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none}
.cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed):has(>.cnx-bg:not([src=""]))::before{
  background:radial-gradient(120% 90% at 50% 45%,rgba(255,255,255,.94) 0%,rgba(255,255,255,.80) 42%,rgba(255,255,255,.34) 100%)}
.cnx-pagehead:has(>.cnx-bg:not([src=""]))::before{
  background:linear-gradient(100deg,rgba(255,255,255,.93) 0%,rgba(255,255,255,.72) 50%,rgba(255,255,255,.25) 100%)}
.cnx-ctaband:has(>.cnx-bg:not([src=""]))::before{
  background:linear-gradient(rgba(8,12,18,.82),rgba(8,12,18,.94))}
.cnx-s-calm .cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed):has(>.cnx-bg:not([src=""]))::before{
  background:radial-gradient(130% 95% at 50% 45%,rgba(255,255,255,.95) 0%,rgba(255,255,255,.86) 46%,rgba(255,255,255,.46) 100%)}
.cnx-s-industrial .cnx-hero:not(.cnx-hero-split):not(.cnx-hero-full):not(.cnx-hero-ed):has(>.cnx-bg:not([src=""]))::before,
.cnx-s-industrial .cnx-pagehead:has(>.cnx-bg:not([src=""]))::before{
  background:linear-gradient(100deg,rgba(12,17,24,.90) 0%,rgba(12,17,24,.74) 52%,rgba(12,17,24,.42) 100%)}
/* ...but WHILE EDITING an unfilled picture must be clickable, or there is
   nothing on the page to click to choose one. The overlay puts cnxe-on on
   the document while edit mode is on; the box keeps its fallback look and
   the invisible <img> over it is the click target. */
html.cnxe-on :is(.cnx-split-media,.cnx-story-media,.cnx-work-img,.cnx-path-img,.cnx-shot,.cnx-room-img,.cnx-product-img,.cnx-hero-ed-band,.cnx-introlede-band)>img[src=""],
html.cnxe-on .cnx-bg[src=""]{display:block;opacity:0;cursor:pointer}

/* ── site search ────────────────────────────────────────────────── */
.cnx-search .cdnmx-search{max-width:560px}
.cnx-search .cdnmx-search input{border-color:var(--cnx-line);border-radius:8px;padding-top:12px;padding-bottom:12px;color:var(--cnx-ink)}
.cnx-search .cdnmx-search input:focus{border-color:var(--cnx-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--cnx-primary) 15%,transparent)}
.cnx-search .cdnmx-search-r{border-color:var(--cnx-line);border-radius:10px}
.cnx-search .cdnmx-search-r i b{color:var(--cnx-primary)}

/* ── open roles (cdnmxUF_Jobs default templates) ────────────────── */
.cnx-jobs .cdnmx-jobs{display:grid;gap:16px;margin-top:8px}
.cnx-jobs .cdnmx-job{border:1px solid var(--cnx-line);border-radius:12px;padding:22px;background:var(--cnx-bg)}
.cnx-jobs .cdnmx-job-title{margin:0 0 .3em}
.cnx-jobs .cdnmx-job-title a{color:var(--cnx-ink);text-decoration:none}
.cnx-jobs .cdnmx-job-title a:hover{color:var(--cnx-primary)}
.cnx-jobs .cdnmx-job-meta{color:var(--cnx-neutral);font-size:.9rem;margin:0 0 .6em}
.cnx-jobs .cdnmx-job-summary{margin:0 0 1em}
.cnx-jobs .cdnmx-job-apply{display:inline-block;padding:10px 18px;border-radius:8px;font-weight:600;
  border:1px solid var(--cnx-line);color:var(--cnx-ink);text-decoration:none}
.cnx-jobs .cdnmx-job-apply:hover{border-color:var(--cnx-primary);color:var(--cnx-primary)}
.cnx-jobs .cdnmx-jobs-empty{color:var(--cnx-neutral)}

/* ── room availability ──────────────────────────────────────────── */
.cnx-avail{background:var(--cnx-tint)}
.cnx-avail-form{display:flex;gap:14px;flex-wrap:wrap;align-items:end;margin-top:8px}
.cnx-avail-form label{display:grid;gap:4px;font-size:.85rem;font-weight:600;color:var(--cnx-ink)}
.cnx-avail-form input{border:1px solid var(--cnx-line);border-radius:8px;padding:11px 12px;font:inherit;background:var(--cnx-bg);color:var(--cnx-ink);min-width:9em}
.cnx-avail-form input:focus{outline:none;border-color:var(--cnx-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--cnx-primary) 15%,transparent)}
button.cnx-btn{border:0;cursor:pointer;font:inherit;font-weight:600}

/* ── shop (cdnmxUF_Shop default templates) ──────────────────────── */
.cnx-shop .cdnmx-shop-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:22px;margin-top:8px}
.cnx-shop .cdnmx-shop-collection-title,.cnx-shop .cdnmx-shop-series-title{margin-top:1em}
.cnx-shop .cdnmx-shop-work{display:block;color:inherit;text-decoration:none;border:1px solid var(--cnx-line);border-radius:12px;overflow:hidden;background:var(--cnx-bg)}
.cnx-shop .cdnmx-shop-img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;background:var(--cnx-tint)}
.cnx-shop .cdnmx-shop-work-title{display:block;padding:14px 16px 4px;font-family:var(--cnx-heading-font);color:var(--cnx-ink)}
.cnx-shop .cdnmx-shop-work>span+span{display:block;padding:0 16px 14px;color:var(--cnx-body);font-size:.92rem}

/* ── picture ────────────────────────────────────────────────────── */
.cnx-figure{margin:0}
.cnx-figure img{width:100%;height:auto;display:block;border-radius:12px;background:var(--cnx-tint)}
.cnx-figure img[src=""],.cnx-figure img:not([src]){display:none}
html.cnxe-on .cnx-figure img[src=""]{display:block;min-height:180px;border:2px dashed var(--cnx-line);cursor:pointer}
.cnx-figure figcaption{margin-top:10px;font-size:.88rem;color:var(--cnx-body);text-align:center}
.cnx-figure figcaption:empty{display:none}
.cnx-picture-narrow .cnx-wrap{max-width:720px}
.cnx-picture.cnx-picture-full{padding:0}
.cnx-picture-full .cnx-wrap{max-width:none;padding:0}
.cnx-picture-full .cnx-figure img{border-radius:0}
.cnx-picture-full .cnx-figure figcaption{padding:0 24px 18px}

/* my booking: the lookup form and the card the script fills */
.cnx-lookup-form{display:flex;gap:14px;flex-wrap:wrap;align-items:end;margin-top:8px}
.cnx-lookup-form label{display:grid;gap:4px;font-size:.85rem;font-weight:600;color:var(--cnx-ink)}
.cnx-lookup-form input{border:1px solid var(--cnx-line);border-radius:8px;padding:11px 12px;font:inherit;background:var(--cnx-bg);color:var(--cnx-ink);min-width:12em}
.cnx-lookup-form input:focus{outline:none;border-color:var(--cnx-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--cnx-primary) 15%,transparent)}
.cnx-lookup-note{margin-top:14px;font-size:.9rem;color:var(--cnx-neutral)}
.cdnmx-booking-lookup-result{margin-top:18px}
.cdnmx-booking-lookup-result[hidden]{display:none}
.cdnmx-bl-card{border:1px solid var(--cnx-line);border-radius:12px;padding:18px 20px;background:var(--cnx-bg);max-width:560px}
.cdnmx-bl-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:10px;font-size:1.05rem}
.cdnmx-bl-status{font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:4px 9px;border-radius:99px;background:var(--cnx-tint);color:var(--cnx-ink)}
.cdnmx-bl-status.is-cancelled,.cdnmx-bl-status.is-noshow{background:color-mix(in srgb,#d1434b 14%,var(--cnx-bg));color:#a3323a}
.cdnmx-bl-status.is-paid{background:color-mix(in srgb,#16a34a 14%,var(--cnx-bg));color:#15803d}
.cdnmx-bl-row{display:flex;justify-content:space-between;gap:16px;padding:6px 0;border-top:1px solid var(--cnx-line);font-size:.95rem}
.cdnmx-bl-row span{color:var(--cnx-neutral)}
.cdnmx-bl-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.cdnmx-bl-note,.cdnmx-bl-error,.cdnmx-bl-wait{font-size:.92rem;color:var(--cnx-neutral)}
.cdnmx-bl-error{color:#a3323a}

/* food menus: the search-and-pick filter, then one accordion panel per menu
   (the Food Menus tool's import-shape templates: section.menu-category >
   details.menu-panel), all on the site's own tokens */
.cnx-menus{scroll-margin-top:var(--cnx-sticky-h,80px)}
.cnx-menus-top{display:block;position:relative;top:-24px}
.cnx-menus-note{margin-top:14px;font-size:.95rem;color:var(--cnx-neutral)}
.cnx-menu-filter{position:relative;display:flex;align-items:center;max-width:520px;margin-top:12px;z-index:5}
.cnx-menu-filter-icon{position:absolute;left:18px;width:20px;height:20px;color:var(--cnx-neutral);pointer-events:none}
.cnx-menu-filter-input{width:100%;padding:14px 52px 14px 50px;border-radius:999px;border:2px solid var(--cnx-ink);background:var(--cnx-bg);color:var(--cnx-ink);font:inherit;font-size:1rem}
.cnx-menu-filter-input::-webkit-search-cancel-button{-webkit-appearance:none}
.cnx-menu-filter-input:focus{outline:none;border-color:var(--cnx-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--cnx-primary) 15%,transparent)}
.cnx-menu-filter-clear{position:absolute;right:10px;width:32px;height:32px;border-radius:50%;border:0;background:color-mix(in srgb,var(--cnx-ink) 8%,transparent);color:var(--cnx-ink);font-size:1.15rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.cnx-menu-filter-clear:hover{background:color-mix(in srgb,var(--cnx-ink) 16%,transparent)}
.cnx-menu-filter-clear[hidden],.cnx-menu-filter-drop[hidden],.cnx-menu-filter-empty[hidden]{display:none}
.cnx-menu-filter-empty{margin-top:16px;color:var(--cnx-neutral)}
.cnx-menu-filter-drop{position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:40;max-height:380px;overflow-y:auto;background:var(--cnx-bg);border:2px solid var(--cnx-ink);border-radius:14px;padding:8px;box-shadow:0 14px 32px rgba(0,0,0,.16);display:flex;flex-direction:column;gap:4px}
.cnx-menu-drop-item{display:flex;align-items:center;gap:12px;padding:8px 10px;border:0;border-radius:10px;background:transparent;color:var(--cnx-ink);font:inherit;font-weight:700;font-size:.95rem;text-align:left;cursor:pointer}
.cnx-menu-drop-item:hover{background:var(--cnx-tint)}
.cnx-menu-drop-item img{width:40px;height:40px;border-radius:8px;object-fit:cover;flex-shrink:0}
.cnx-menu-filter-pills{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.cnx-menu-pill{display:inline-flex;align-items:center;gap:8px;padding:7px 8px 7px 14px;border:2px solid var(--cnx-ink);border-radius:999px;font-weight:700;font-size:.85rem;background:var(--cnx-tint);color:var(--cnx-ink)}
.cnx-menu-pill-1{background:var(--cnx-primary);color:var(--cnx-bg);border-color:var(--cnx-primary)}
.cnx-menu-pill-2{background:var(--cnx-accent);color:var(--cnx-bg);border-color:var(--cnx-accent)}
.cnx-menu-pill-3{background:var(--cnx-secondary);color:var(--cnx-bg);border-color:var(--cnx-secondary)}
.cnx-menu-pill-remove{width:22px;height:22px;border:0;border-radius:50%;background:rgba(0,0,0,.14);color:inherit;font-size:1rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.cnx-menu-pill-remove:hover{background:rgba(0,0,0,.28)}
.cnx-menu-pills-clear{border:0;background:none;color:var(--cnx-primary);font:inherit;font-weight:700;font-size:.85rem;text-decoration:underline;cursor:pointer;padding:6px 4px}
.cnx-menus .menu-category{padding:12px 0;scroll-margin-top:var(--cnx-sticky-h,80px)}
.cnx-menus .menu-category[hidden]{display:none}
.cnx-menus .menu-category h2{font-size:clamp(1.5rem,2.4vw,2.1rem);margin:.1em 0 .2em}
.cnx-menus .menu-category .note{display:block;font-size:1rem;color:var(--cnx-neutral)}
.cnx-menus .menu-panel{border:3px solid var(--cnx-ink);border-radius:18px;background:var(--cnx-bg)}
.cnx-menus .menu-panel>summary{list-style:none;cursor:pointer}
.cnx-menus .menu-panel>summary::-webkit-details-marker{display:none}
.cnx-menus .menu-panel>summary:hover h2{text-decoration:underline;text-decoration-thickness:3px;text-underline-offset:5px}
.cnx-menus .menu-panel[open]>summary{border-bottom:3px solid var(--cnx-ink)}
.cnx-menus .menu-panel-body{padding:32px 28px 10px}
.cnx-menus .menu-category-head{display:grid;grid-template-columns:auto 1fr auto;grid-template-rows:auto auto;align-items:center;column-gap:28px;padding:18px 24px}
.cnx-menus .menu-category-head>.menu-category-img{grid-column:1;grid-row:1/span 2}
.cnx-menus .menu-category-head>h2{grid-column:2;grid-row:1;align-self:end}
.cnx-menus .menu-category-head>.note{grid-column:2;grid-row:2;align-self:start}
.cnx-menus .menu-category-head>.menu-chevron{grid-column:3;grid-row:1/span 2;align-self:start;margin-top:14px}
.cnx-menus .menu-category-img{width:120px;height:120px;border-radius:14px;object-fit:cover;border:3px solid currentColor}
.cnx-menus .menu-chevron{width:14px;height:14px;border-right:3px solid currentColor;border-bottom:3px solid currentColor;transform:rotate(45deg);transition:transform .2s ease}
.cnx-menus .menu-panel[open] .menu-chevron{transform:rotate(225deg)}
.cnx-menus .menu-group{margin-bottom:2.4em}
.cnx-menus .menu-group h3{font-size:1.35rem;margin-bottom:.6em;color:var(--cnx-primary)}
.cnx-menus .dish{margin-bottom:1.1em}
.cnx-menus .dish .name{font-weight:700;font-size:1.1rem}
.cnx-menus .dish .desc{opacity:.85;margin-top:.15em}
.cnx-menus .dish .tags{font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;opacity:.7;margin-left:.4em}
.cnx-menus .menu-sample{margin:22px 0 4px;padding:18px 20px;border-radius:14px;background:var(--cnx-tint);display:flex;flex-direction:column;align-items:flex-start;gap:12px}
.cnx-menus .menu-sample-note{margin:0;font-size:.95rem;opacity:.85}
.cnx-menus .menu-back-top{display:inline-block;margin:4px 0 20px;font-weight:700;font-size:.95rem;color:var(--cnx-primary);text-decoration:underline;text-underline-offset:5px}
@media(max-width:700px){.cnx-menus .menu-category-head{column-gap:16px;padding:14px 16px}.cnx-menus .menu-category-img{width:72px;height:72px}.cnx-menus .menu-panel-body{padding:22px 16px 6px}}

/* ------------------------------------------------------------- the header
   A composed kit's header is brand, menu, utility links and one button. Three
   things it has to do that the plain flex row did not:

   1. BE HITTABLE. The links were 17px tall at 390px - an inline anchor with a
      .78rem font and no padding. 44px is the floor for anything a thumb has
      to find, and it is the floor the widget primitives already hold.
   2. NEVER WRAP. Brand + six items + a button needs about 1090px; below that
      the row used to fold onto a second and third line, at exactly the widths
      people browse at. The menu scrolls sideways in its own track instead, so
      the header stays one row at every width.
   3. GET OUT OF THE WAY ON A PHONE. Under 860px the menu becomes a drawer
      (apps/header.js builds it), and until that script runs the same rules
      leave a usable scrolling row rather than a broken stack.

   Everything here is tokens and classes; no inline style, and no dependency
   on markup the composer has not emitted yet. */
.cnx-header{flex-wrap:nowrap;gap:16px}
.cnx-header .cnx-brand{flex:none;display:inline-flex;align-items:center;min-height:44px}
.cnx-nav{flex:1 1 auto;min-width:0}
.cnx-nav ul{flex-wrap:nowrap;align-items:center;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;
  scroll-snap-type:x proximity;gap:4px}
.cnx-nav ul::-webkit-scrollbar{display:none}
.cnx-nav li{flex:none;scroll-snap-align:start}
.cnx-nav a{display:inline-flex;align-items:center;min-height:44px;padding:0 10px;white-space:nowrap}
/* AT 320 THE BAR STILL HAS TO FIT. The menu collapses to nothing and
   scrolls in its own track, which is right, but a 131px wordmark and a
   137px button and the padding between them are already wider than the
   narrowest phone - so the page scrolled sideways with an empty menu.
   Both ends may shrink: a flex item's min-width is auto by default, which
   is what stops them. The button keeps its 44px and its whole label; it
   gives up padding first, and only then lets a long label ellipsize. */
@media(max-width:420px){
  .cnx-header{gap:8px;padding-left:14px;padding-right:14px}
  .cnx-header .cnx-brand{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .cnx-header-cta{min-width:0;padding-left:10px;padding-right:10px;font-size:.82rem;
    overflow:hidden;text-overflow:ellipsis}
}
.cnx-utility{display:flex;gap:4px;list-style:none;margin:0;padding:0;flex:none}
.cnx-utility a{display:inline-flex;align-items:center;min-height:44px;padding:0 8px;font-size:.85rem;
  color:var(--cnx-neutral);text-decoration:none}
.cnx-utility a:hover{color:var(--cnx-primary)}
.cnx-header .cnx-cta{flex:none;display:inline-flex;align-items:center;min-height:44px;white-space:nowrap;
  background:var(--cnx-primary);color:var(--cnx-bg);border:2px solid var(--cnx-primary);
  border-radius:var(--cnx-radius,12px);padding:0 18px;font-weight:600;font-size:.95rem;text-decoration:none}
/* the toggle and the drawer only exist once apps/header.js has built them */
/* A KIT MAY SAY ITS HEADER IS A BAR. A style variant decides a lot, and for
   most of what it decides the variant is right - but the header is the one
   piece a kit's own design speaks to directly. The warm variant centres a
   wordmark over a centred menu, which is right for a cafe and wrong for a
   hotel: it publishes the brand, the menu and the Book button on three
   separate rows, 199px of header before anything is read, and the approved
   comp draws a single-row bar with the button on the right.
   So "header": "bar" in kit.json puts the row back for that kit alone,
   leaving every other kit on the variant untouched. Same specificity as the
   variant's own rule and later in the file, which is what makes it win. */
.cnx-h-bar .cnx-header{flex-direction:row;text-align:left;align-items:center;
  padding-top:16px;padding-bottom:16px;gap:20px}
.cnx-h-bar .cnx-nav ul{justify-content:flex-end}
.cnx-h-bar .cnx-brand{text-align:left}

/* "More": the tail of a menu that would not fit, folded by apps/header.js.
   The list is display:none until it is opened, which is also what keeps the
   folded items out of the track's scrollWidth - the measurement the fold
   itself depends on. */
.cnx-more{position:relative}
.cnx-more-btn{border:0;background:transparent;font:inherit;font-weight:600;font-size:.95rem;color:var(--cnx-body);
  cursor:pointer;padding:0 10px;display:inline-flex;align-items:center;gap:5px;min-height:44px;white-space:nowrap}
.cnx-more-btn:hover{color:var(--cnx-primary)}
.cnx-more-btn i{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;
  border-top:5px solid currentColor}
.cnx-more-list{display:none;position:absolute;top:100%;right:0;z-index:30;min-width:190px;margin:6px 0 0;
  padding:6px 0;list-style:none;background:var(--cnx-bg);border:1px solid var(--cnx-line);
  border-radius:var(--cnx-radius,12px);box-shadow:0 12px 30px color-mix(in srgb,var(--cnx-ink) 16%,transparent)}
.cnx-more.is-open .cnx-more-list{display:block}
.cnx-more-list li{width:100%}
.cnx-more-list a{display:flex;align-items:center;min-height:44px;padding:0 16px;white-space:nowrap}

.cnx-menu-toggle{display:none;border:0;background:transparent;color:var(--cnx-ink);cursor:pointer;flex:none;
  min-width:44px;min-height:44px;padding:0 6px;align-items:center;gap:8px;font:inherit;font-weight:600}
.cnx-menu-toggle i{width:22px;height:2px;background:currentColor;position:relative;display:block;border-radius:2px}
.cnx-menu-toggle i::before,.cnx-menu-toggle i::after{content:"";position:absolute;left:0;width:22px;height:2px;
  background:currentColor;border-radius:2px}
.cnx-menu-toggle i::before{top:-7px}.cnx-menu-toggle i::after{top:7px}
@media(max-width:860px){
  .cnx-header{justify-content:space-between;padding-left:16px;padding-right:16px}
  .cnx-header.has-drawer .cnx-nav,
  .cnx-header.has-drawer .cnx-header-cta{display:none}
  .cnx-header.has-drawer .cnx-menu-toggle{display:inline-flex}
  /* the centred variants stack their header; a scrolling row cannot centre */
  .cnx-s-warm .cnx-header,.cnx-s-calm .cnx-header{flex-direction:row;text-align:left;gap:12px}
}
.cnx-drawer{position:fixed;inset:0;z-index:1000}
.cnx-drawer-scrim{position:absolute;inset:0;background:color-mix(in srgb,var(--cnx-ink) 55%,transparent);border:0;width:100%;cursor:pointer}
.cnx-drawer-panel{position:absolute;top:0;right:0;bottom:0;width:min(86vw,360px);background:var(--cnx-bg);
  color:var(--cnx-ink);padding:16px 20px 28px;overflow:auto;display:flex;flex-direction:column;gap:16px;
  box-shadow:-12px 0 40px color-mix(in srgb,var(--cnx-ink) 22%,transparent)}
.cnx-drawer-top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.cnx-drawer-brand{font-weight:700;font-family:var(--cnx-heading-font)}
.cnx-drawer-close{border:0;background:var(--cnx-tint);border-radius:99px;width:44px;height:44px;font-size:1.5rem;
  line-height:1;cursor:pointer;color:inherit;flex:none}
.cnx-drawer-nav ul,.cnx-drawer-util{list-style:none;margin:0;padding:0}
.cnx-drawer-nav li a{display:block;padding:12px 0;border-bottom:1px solid var(--cnx-line);
  font-family:var(--cnx-heading-font);font-size:1.2rem;color:inherit;text-decoration:none;min-height:44px}
.cnx-drawer-util{display:flex;flex-wrap:wrap;gap:0 16px;padding-top:4px}
.cnx-drawer-util a{color:var(--cnx-neutral);text-decoration:none;display:inline-flex;align-items:center;min-height:44px}
.cnx-drawer-cta a{display:flex;align-items:center;justify-content:center;min-height:44px;width:100%;
  background:var(--cnx-primary);color:var(--cnx-bg);border-radius:var(--cnx-radius,12px);
  text-decoration:none;font-weight:600}
.cnx-drawer-open,.cnx-drawer-open body{overflow:hidden}
.cnx-footer-cols{display:grid;grid-template-columns:2fr repeat(3,1fr);gap:24px;text-align:left;
  padding:0 0 28px;margin:0 0 20px;border-bottom:1px solid var(--cnx-line)}
.cnx-footer-brand p{margin:8px 0 0;color:var(--cnx-neutral);max-width:36ch}
.cnx-footer-col{list-style:none;margin:0;padding:0}
.cnx-footer-col b{display:block;margin:0 0 8px;font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--cnx-neutral);font-family:var(--cnx-mono-font,inherit)}
.cnx-footer-col li{margin:0 0 6px}
.cnx-footer-col a{color:inherit;text-decoration:none;display:inline-flex;align-items:center;min-height:32px}
.cnx-footer-col a:hover{color:var(--cnx-primary)}
@media(max-width:700px){.cnx-footer-cols{grid-template-columns:1fr 1fr}.cnx-footer-brand{grid-column:1 / -1}}
@media (prefers-reduced-motion:no-preference){.cnx-drawer-panel{animation:cnxDrawerIn .2s ease}}
@keyframes cnxDrawerIn{from{transform:translateX(24px);opacity:0}to{transform:none;opacity:1}}

/* ══════════════════════════════════════════════════════════════════
   STYLE - the Canvas Style tab (three-stays-contract.md, "Section
   style classes"). Four row settings, each a class on the <section>,
   never an inline style: bg (tint / dark / photo), space (tight /
   roomy), width (narrow / bleed) and mobile (photo-first / hide). At
   the foot of the file on purpose: an owner's explicit choice beats a
   section's own ground, and the type inside a dark or photographed
   section resolves through the same tokens the section's ground came
   from - never a colour literal. --cnx-sp is the padding scale every
   section's padding is multiplied by (1, .5, 1.6).
   ══════════════════════════════════════════════════════════════════ */
.cnx-space-tight{--cnx-sp:.5}
.cnx-space-roomy{--cnx-sp:1.6}
section.cnx-bg-tint{background-color:var(--cnx-tint);background-image:none}
section.cnx-bg-dark{background-color:var(--cnx-secondary);background-image:none;color:var(--cnx-bg)}
/* photo: the section's first picture as the ground (the synthesiser lays it
   under the words as <img class="cnx-bg">, the same slot the section shows),
   under a gradient scrim heavy where the words are; sections that already
   put type on a picture (heroes, page header, closing band) never get this
   class and keep their own scrim */
section.cnx-bg-photo{position:relative;isolation:isolate;background-color:var(--cnx-secondary);background-image:none;color:var(--cnx-bg)}
section.cnx-bg-photo>.cnx-wrap{position:relative;z-index:1}
section.cnx-bg-photo::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(180deg,color-mix(in srgb,var(--cnx-secondary) 48%,transparent) 0%,color-mix(in srgb,var(--cnx-secondary) 82%,transparent) 100%)}
section.cnx-bg-photo>.cnx-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-1;margin:0;border-radius:0}
/* type on a dark ground: headings in the page colour, body a touch quieter,
   the accent lifted towards it so it still reads, links the page colour */
.cnx-bg-dark h1,.cnx-bg-photo h1,.cnx-bg-dark h2,.cnx-bg-photo h2,.cnx-bg-dark h3,.cnx-bg-photo h3,.cnx-bg-dark h4,.cnx-bg-photo h4,.cnx-bg-dark .cnxw-hd,.cnx-bg-photo .cnxw-hd,.cnx-bg-dark .cnx-address,.cnx-bg-photo .cnx-address,.cnx-bg-dark .cnxw-price,.cnx-bg-photo .cnxw-price,.cnx-bg-dark .cnxw-label,.cnx-bg-photo .cnxw-label,.cnx-bg-dark .cnx-fact-v,.cnx-bg-photo .cnx-fact-v,.cnx-bg-dark .cnx-stat-n,.cnx-bg-photo .cnx-stat-n,.cnx-bg-dark .cnx-priceline dt,.cnx-bg-photo .cnx-priceline dt,.cnx-bg-dark .cnx-hours-list dt,.cnx-bg-photo .cnx-hours-list dt,.cnx-bg-dark .cnxw-li-name,.cnx-bg-photo .cnxw-li-name,.cnx-bg-dark .cnxw-kv>:last-child,.cnx-bg-photo .cnxw-kv>:last-child,.cnx-bg-dark .cnx-path-body strong,.cnx-bg-photo .cnx-path-body strong,.cnx-bg-dark .cnx-tt-name,.cnx-bg-photo .cnx-tt-name,.cnx-bg-dark .cnx-tt-day,.cnx-bg-photo .cnx-tt-day,.cnx-bg-dark .cnx-work figcaption,.cnx-bg-photo .cnx-work figcaption,.cnx-bg-dark .cnx-step-list h3,.cnx-bg-photo .cnx-step-list h3,.cnx-bg-dark .cnx-faqitem summary,.cnx-bg-photo .cnx-faqitem summary,.cnx-bg-dark .cnx-reviews-n,.cnx-bg-photo .cnx-reviews-n,.cnx-bg-dark .cnx-review cite,.cnx-bg-photo .cnx-review cite,.cnx-bg-dark .cnxw-stay b,.cnx-bg-photo .cnxw-stay b,.cnx-bg-dark .cnxw-cal-title,.cnx-bg-photo .cnxw-cal-title,.cnx-bg-dark .cnxw-cal-span,.cnx-bg-photo .cnxw-cal-span,.cnx-bg-dark .cnxw-stay-d,.cnx-bg-photo .cnxw-stay-d,.cnx-bg-dark .cnxw-room-price,.cnx-bg-photo .cnxw-room-price,.cnx-bg-dark .cnxw-empty b,.cnx-bg-photo .cnxw-empty b,.cnx-bg-dark .cnxw-check,.cnx-bg-photo .cnxw-check,.cnx-bg-dark .cnx-form label,.cnx-bg-photo .cnx-form label,.cnx-bg-dark .cnxw-cal-day,.cnx-bg-photo .cnxw-cal-day,.cnx-bg-dark .cnx-tier li,.cnx-bg-photo .cnx-tier li,.cnx-bg-dark .cnx-faqitem p,.cnx-bg-photo .cnx-faqitem p,.cnx-bg-dark .cnx-menus .menu-panel,.cnx-bg-photo .cnx-menus .menu-panel{color:var(--cnx-bg)}
.cnx-bg-dark p,.cnx-bg-photo p,.cnx-bg-dark li,.cnx-bg-photo li,.cnx-bg-dark dd,.cnx-bg-photo dd,.cnx-bg-dark .cnx-lede,.cnx-bg-photo .cnx-lede,.cnx-bg-dark .cnx-section-lede,.cnx-bg-photo .cnx-section-lede,.cnx-bg-dark .cnx-trust,.cnx-bg-photo .cnx-trust,.cnx-bg-dark .cnxw-mut,.cnx-bg-photo .cnxw-mut,.cnx-bg-dark .cnx-stat-l,.cnx-bg-photo .cnx-stat-l,.cnx-bg-dark .cnx-fact-l,.cnx-bg-photo .cnx-fact-l,.cnx-bg-dark .cnx-pricenote,.cnx-bg-photo .cnx-pricenote,.cnx-bg-dark .cnxw-kv>:first-child,.cnx-bg-photo .cnxw-kv>:first-child,.cnx-bg-dark .cnx-testimonial cite,.cnx-bg-photo .cnx-testimonial cite,.cnx-bg-dark .cnx-work figcaption span,.cnx-bg-photo .cnx-work figcaption span,.cnx-bg-dark .cnx-step-list p,.cnx-bg-photo .cnx-step-list p,.cnx-bg-dark .cnx-tt-where,.cnx-bg-photo .cnx-tt-where,.cnx-bg-dark .cnxw-hint,.cnx-bg-photo .cnxw-hint,.cnx-bg-dark .cnx-figure figcaption,.cnx-bg-photo .cnx-figure figcaption,.cnx-bg-dark .cnxw-gal-tile figcaption,.cnx-bg-photo .cnxw-gal-tile figcaption,.cnx-bg-dark .cnx-review cite span,.cnx-bg-photo .cnx-review cite span,.cnx-bg-dark .cnx-reviews-meta,.cnx-bg-photo .cnx-reviews-meta,.cnx-bg-dark .cnx-path-body span,.cnx-bg-photo .cnx-path-body span,.cnx-bg-dark .cnx-dur,.cnx-bg-photo .cnx-dur,.cnx-bg-dark .cnx-logos-title,.cnx-bg-photo .cnx-logos-title,.cnx-bg-dark .cnxw-room-price small,.cnx-bg-photo .cnxw-room-price small,.cnx-bg-dark .cnxw-stay-d small,.cnx-bg-photo .cnxw-stay-d small,.cnx-bg-dark .cnxw-cal-dow,.cnx-bg-photo .cnxw-cal-dow,.cnx-bg-dark .cnxw-empty,.cnx-bg-photo .cnxw-empty,.cnx-bg-dark .cnxw-steps,.cnx-bg-photo .cnxw-steps,.cnx-bg-dark .cnx-hours-note,.cnx-bg-photo .cnx-hours-note,.cnx-bg-dark .cnx-ctaband-note,.cnx-bg-photo .cnx-ctaband-note,.cnx-bg-dark .cnxw-li-crumb,.cnx-bg-photo .cnxw-li-crumb,.cnx-bg-dark .cnxw-li-meta,.cnx-bg-photo .cnxw-li-meta,.cnx-bg-dark .cnxw-li-sum,.cnx-bg-photo .cnxw-li-sum,.cnx-bg-dark .cnx-lookup-note,.cnx-bg-photo .cnx-lookup-note,.cnx-bg-dark .cnx-menus-note,.cnx-bg-photo .cnx-menus-note,.cnx-bg-dark .cnxw-cal-day>small,.cnx-bg-photo .cnxw-cal-day>small{color:color-mix(in srgb,var(--cnx-bg) 78%,var(--cnx-secondary))}
.cnx-bg-dark .cnx-eyebrow,.cnx-bg-photo .cnx-eyebrow,.cnx-bg-dark .cnxw-eyebrow,.cnx-bg-photo .cnxw-eyebrow,.cnx-bg-dark .cnx-role,.cnx-bg-photo .cnx-role,.cnx-bg-dark .cnx-stars,.cnx-bg-photo .cnx-stars,.cnx-bg-dark .cnx-price,.cnx-bg-photo .cnx-price,.cnx-bg-dark .cnx-priceline dd,.cnx-bg-photo .cnx-priceline dd,.cnx-bg-dark .cnx-tt-time,.cnx-bg-photo .cnx-tt-time,.cnx-bg-dark .cnx-step-list li::before,.cnx-bg-photo .cnx-step-list li::before,.cnx-bg-dark .cnxw-li-more,.cnx-bg-photo .cnxw-li-more,.cnx-bg-dark .cnxw-stars::before,.cnx-bg-photo .cnxw-stars::before{color:color-mix(in srgb,var(--cnx-accent) 62%,var(--cnx-bg))}
.cnx-bg-dark .cnxw-stars,.cnx-bg-photo .cnxw-stars{color:color-mix(in srgb,var(--cnx-bg) 26%,var(--cnx-secondary))}
.cnx-bg-dark a,.cnx-bg-photo a{color:var(--cnx-bg)}
.cnx-bg-dark .cnx-nav a,.cnx-bg-photo .cnx-nav a{color:var(--cnx-bg)}
.cnx-bg-dark .cnx-btn,.cnx-bg-photo .cnx-btn,.cnx-bg-dark .cnxw-btn,.cnx-bg-photo .cnxw-btn,.cnx-bg-dark .cnx-btn-invert,.cnx-bg-photo .cnx-btn-invert,.cnx-bg-dark .cnx-signup-form button,.cnx-bg-photo .cnx-signup-form button,.cnx-bg-dark .cnx-form button,.cnx-bg-photo .cnx-form button,.cnx-bg-dark .cnx-contact .cdnmx-form form button,.cnx-bg-photo .cnx-contact .cdnmx-form form button{background:var(--cnx-bg);color:var(--cnx-secondary);border-color:var(--cnx-bg)}
.cnx-bg-dark .cnx-btn:hover,.cnx-bg-photo .cnx-btn:hover,.cnx-bg-dark .cnxw-btn:hover,.cnx-bg-photo .cnxw-btn:hover{background:var(--cnx-bg);color:var(--cnx-secondary);opacity:.9;filter:none}
.cnx-bg-dark .cnx-btn-quiet,.cnx-bg-photo .cnx-btn-quiet,.cnx-bg-dark .cnxw-btn-quiet,.cnx-bg-photo .cnxw-btn-quiet,.cnx-bg-dark .cnx-btn-ghost,.cnx-bg-photo .cnx-btn-ghost,.cnx-bg-dark .cnx-jobs .cdnmx-job-apply,.cnx-bg-photo .cnx-jobs .cdnmx-job-apply,.cnx-bg-dark .cnxw-btn-quiet:hover,.cnx-bg-photo .cnxw-btn-quiet:hover{background:transparent;color:var(--cnx-bg);border-color:color-mix(in srgb,var(--cnx-bg) 55%,transparent)}
.cnx-bg-dark .cnx-card,.cnx-bg-photo .cnx-card,.cnx-bg-dark .cnx-person,.cnx-bg-photo .cnx-person,.cnx-bg-dark .cnx-testimonial,.cnx-bg-photo .cnx-testimonial,.cnx-bg-dark .cnx-tier,.cnx-bg-photo .cnx-tier,.cnx-bg-dark .cnx-product,.cnx-bg-photo .cnx-product,.cnx-bg-dark .cnx-room,.cnx-bg-photo .cnx-room,.cnx-bg-dark .cnxw-card,.cnx-bg-photo .cnxw-card,.cnx-bg-dark .cnxw-done,.cnx-bg-photo .cnxw-done,.cnx-bg-dark .cnxw-empty,.cnx-bg-photo .cnxw-empty,.cnx-bg-dark .cnx-path,.cnx-bg-photo .cnx-path,.cnx-bg-dark .cnx-jobs .cdnmx-job,.cnx-bg-photo .cnx-jobs .cdnmx-job,.cnx-bg-dark .cnx-review,.cnx-bg-photo .cnx-review,.cnx-bg-dark .cnx-map-embed,.cnx-bg-photo .cnx-map-embed,.cnx-bg-dark .cnx-booking-embed,.cnx-bg-photo .cnx-booking-embed,.cnx-bg-dark .cnx-preview-token,.cnx-bg-photo .cnx-preview-token,.cnx-bg-dark .cdnmx-bl-card,.cnx-bg-photo .cdnmx-bl-card,.cnx-bg-dark .cnx-faqitem,.cnx-bg-photo .cnx-faqitem,.cnx-bg-dark .cnx-menus .menu-panel,.cnx-bg-photo .cnx-menus .menu-panel{background:color-mix(in srgb,var(--cnx-bg) 7%,var(--cnx-secondary));border-color:color-mix(in srgb,var(--cnx-bg) 18%,transparent);color:inherit;box-shadow:none}
.cnx-bg-dark .cnxw-card-tint,.cnx-bg-photo .cnxw-card-tint,.cnx-bg-dark .cnxw-note,.cnx-bg-photo .cnxw-note,.cnx-bg-dark .cnxw-badge,.cnx-bg-photo .cnxw-badge,.cnx-bg-dark .cnxw-pill,.cnx-bg-photo .cnxw-pill,.cnx-bg-dark .cnx-arealist li,.cnx-bg-photo .cnx-arealist li,.cnx-bg-dark .cnxw-skel,.cnx-bg-photo .cnxw-skel,.cnx-bg-dark .cnx-menu-pill,.cnx-bg-photo .cnx-menu-pill,.cnx-bg-dark .cdnmx-bl-status,.cnx-bg-photo .cdnmx-bl-status,.cnx-bg-dark .cnxw-cal-day.is-span,.cnx-bg-photo .cnxw-cal-day.is-span{background:color-mix(in srgb,var(--cnx-bg) 12%,var(--cnx-secondary));color:var(--cnx-bg);border-color:color-mix(in srgb,var(--cnx-bg) 24%,transparent)}
.cnx-bg-dark .cnxw-input,.cnx-bg-photo .cnxw-input,.cnx-bg-dark .cnx-form input,.cnx-bg-photo .cnx-form input,.cnx-bg-dark .cnx-form textarea,.cnx-bg-photo .cnx-form textarea,.cnx-bg-dark .cnx-signup-form input,.cnx-bg-photo .cnx-signup-form input,.cnx-bg-dark .cnx-signup-input,.cnx-bg-photo .cnx-signup-input,.cnx-bg-dark .cnx-avail-form input,.cnx-bg-photo .cnx-avail-form input,.cnx-bg-dark .cnx-lookup-form input,.cnx-bg-photo .cnx-lookup-form input,.cnx-bg-dark .cnx-contact .cdnmx-form form input,.cnx-bg-photo .cnx-contact .cdnmx-form form input,.cnx-bg-dark .cnx-contact .cdnmx-form form textarea,.cnx-bg-photo .cnx-contact .cdnmx-form form textarea,.cnx-bg-dark .cnx-contact .cdnmx-form form select,.cnx-bg-photo .cnx-contact .cdnmx-form form select,.cnx-bg-dark .cnx-search .cdnmx-search input,.cnx-bg-photo .cnx-search .cdnmx-search input,.cnx-bg-dark .cnx-menu-filter-input,.cnx-bg-photo .cnx-menu-filter-input{background:color-mix(in srgb,var(--cnx-bg) 10%,var(--cnx-secondary));color:var(--cnx-bg);border-color:color-mix(in srgb,var(--cnx-bg) 32%,transparent)}
.cnx-bg-dark .cnxw-input::placeholder,.cnx-bg-photo .cnxw-input::placeholder,.cnx-bg-dark .cnx-form input::placeholder,.cnx-bg-photo .cnx-form input::placeholder{color:color-mix(in srgb,var(--cnx-bg) 55%,transparent)}
.cnx-bg-dark .cnxw-rule,.cnx-bg-photo .cnxw-rule,.cnx-bg-dark .cnxw-kv,.cnx-bg-photo .cnxw-kv,.cnx-bg-dark .cnxw-kv-total,.cnx-bg-photo .cnxw-kv-total,.cnx-bg-dark .cnxw-list>li,.cnx-bg-photo .cnxw-list>li,.cnx-bg-dark .cnx-priceline,.cnx-bg-photo .cnx-priceline,.cnx-bg-dark .cnx-tier li,.cnx-bg-photo .cnx-tier li,.cnx-bg-dark .cnx-faqitem,.cnx-bg-photo .cnx-faqitem,.cnx-bg-dark .cnx-tt-row,.cnx-bg-photo .cnx-tt-row,.cnx-bg-dark .cnx-tt-grid,.cnx-bg-photo .cnx-tt-grid,.cnx-bg-dark .cnx-step-list li,.cnx-bg-photo .cnx-step-list li,.cnx-bg-dark .cnxw-steps li,.cnx-bg-photo .cnxw-steps li,.cnx-bg-dark .cnxw-stay,.cnx-bg-photo .cnxw-stay,.cnx-bg-dark .cnxw-qty,.cnx-bg-photo .cnxw-qty,.cnx-bg-dark .cnxw-qty span,.cnx-bg-photo .cnxw-qty span,.cnx-bg-dark .cnx-fact,.cnx-bg-photo .cnx-fact,.cnx-bg-dark .cnx-review,.cnx-bg-photo .cnx-review,.cnx-bg-dark .cnx-hours-list,.cnx-bg-photo .cnx-hours-list,.cnx-bg-dark .cdnmx-bl-row,.cnx-bg-photo .cdnmx-bl-row,.cnx-bg-dark .cnx-features-list li,.cnx-bg-photo .cnx-features-list li,.cnx-bg-dark .cnx-hero-ed-foot,.cnx-bg-photo .cnx-hero-ed-foot{border-color:color-mix(in srgb,var(--cnx-bg) 24%,transparent)}
.cnx-bg-dark .cnxw-qty button,.cnx-bg-photo .cnxw-qty button,.cnx-bg-dark .cnxw-qty span,.cnx-bg-photo .cnxw-qty span{background:transparent;color:var(--cnx-bg)}
.cnx-bg-dark .cnxw-cal-day.is-edge,.cnx-bg-photo .cnxw-cal-day.is-edge,.cnx-bg-dark .cnxw-pill[aria-pressed="true"],.cnx-bg-photo .cnxw-pill[aria-pressed="true"],.cnx-bg-dark .cnxw-pill.is-on,.cnx-bg-photo .cnxw-pill.is-on{background:var(--cnx-bg);color:var(--cnx-secondary);border-color:var(--cnx-bg)}
.cnx-bg-dark .cnxw-media,.cnx-bg-photo .cnxw-media,.cnx-bg-dark .cnxw-gal-tile>a,.cnx-bg-photo .cnxw-gal-tile>a,.cnx-bg-dark .cnx-shot,.cnx-bg-photo .cnx-shot,.cnx-bg-dark .cnx-product-img,.cnx-bg-photo .cnx-product-img,.cnx-bg-dark .cnx-room-img,.cnx-bg-photo .cnx-room-img,.cnx-bg-dark .cnx-split-media,.cnx-bg-photo .cnx-split-media,.cnx-bg-dark .cnx-story-media,.cnx-bg-photo .cnx-story-media{background-color:color-mix(in srgb,var(--cnx-bg) 12%,var(--cnx-secondary))}
.cnx-bg-dark a:focus-visible,.cnx-bg-photo a:focus-visible,.cnx-bg-dark button:focus-visible,.cnx-bg-photo button:focus-visible,.cnx-bg-dark [tabindex]:focus-visible,.cnx-bg-photo [tabindex]:focus-visible,.cnx-bg-dark .cnxw-input:focus-visible,.cnx-bg-photo .cnxw-input:focus-visible{outline-color:var(--cnx-bg);border-color:var(--cnx-bg)}
.cnx-bg-dark.cnx-look-bordered,.cnx-bg-photo.cnx-look-bordered{border-color:color-mix(in srgb,var(--cnx-bg) 24%,transparent)}
/* width: a reading measure, or the whole window (the gutter stays, the
   measure rules on prose stay, so the words keep to the page while a grid
   or a strip runs to the edges) */
.cnx-w-narrow .cnx-wrap,.cnx-w-narrow .cnxw-wrap{max-width:min(68ch,100%)}
.cnx-w-bleed .cnx-wrap,.cnx-w-bleed .cnxw-wrap{max-width:none}
.cnx-w-bleed .cnx-section-head{max-width:1080px;margin-inline:auto}
/* on a phone: the picture first, or nothing at all */
@media (max-width:520px){
  .cnx-m-hide{display:none}
  .cnx-m-photo-first .cnx-wrap:not(.cnx-split):not(.cnx-story-in){display:flex;flex-direction:column}
  .cnx-m-photo-first{display:flex;flex-direction:column}
  .cnx-m-photo-first .cnx-split-media,.cnx-m-photo-first .cnx-story-media,.cnx-m-photo-first .cnx-introlede-band,
  .cnx-m-photo-first .cnx-figure,.cnx-m-photo-first .cnxw-gal,.cnx-m-photo-first .cnxw-gal-wrap,.cnx-m-photo-first .cnx-gallery-grid,
  .cnx-m-photo-first .cnx-hero-ed-band,.cnx-m-photo-first .cnxw-media,.cnx-m-photo-first .cnxw-room-gal{order:-1}
}

/* ── reviews: a score, its count and source, then the quotes ──────
   Stars are text - five in the rule colour with the accent painted over
   the first N fifths (cnxw-stars-1 .. -5) - and a role="img" label says
   the number, so a screen reader hears "5 out of 5", not five symbols. */
.cnx-reviews-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 18px;margin-bottom:24px}
.cnx-reviews-head .cnxw-eyebrow{flex-basis:100%;margin:0 0 2px}
.cnx-reviews-score{margin:0;display:flex;align-items:center;gap:12px}
.cnx-reviews-n{font-family:var(--cnx-heading-font);font-size:2.4rem;line-height:1;color:var(--cnx-ink)}
.cnx-reviews-meta{margin:0}
.cnxw-stars{position:relative;display:inline-block;letter-spacing:.12em;font-size:1rem;line-height:1;color:var(--cnx-line);--cnxw-stars:100%}
.cnxw-stars>span{display:inline-block}
.cnxw-stars::before{content:"\2605\2605\2605\2605\2605";position:absolute;left:0;top:0;overflow:hidden;white-space:nowrap;width:var(--cnxw-stars);color:var(--cnx-accent);letter-spacing:inherit}
.cnxw-stars-1{--cnxw-stars:20%}.cnxw-stars-2{--cnxw-stars:40%}.cnxw-stars-3{--cnxw-stars:60%}.cnxw-stars-4{--cnxw-stars:80%}.cnxw-stars-5{--cnxw-stars:100%}
.cnx-review-grid{display:grid;gap:18px;grid-template-columns:repeat(3,minmax(0,1fr))}
.cnx-review{margin:0;border:1px solid var(--cnx-line);border-radius:var(--cnx-radius,12px);padding:22px;background:var(--cnx-bg);display:flex;flex-direction:column;gap:12px}
.cnx-review p{margin:0;flex:1}
.cnx-review cite{font-style:normal;font-weight:600;color:var(--cnx-ink);font-size:.92rem}
.cnx-review cite span{display:block;font-weight:400;color:var(--cnx-neutral);font-size:.84rem;margin-top:2px}
.cnx-reviews-list .cnx-review-grid{grid-template-columns:minmax(0,1fr);gap:0;max-width:68ch}
.cnx-reviews-list .cnx-review{border:0;border-top:1px solid var(--cnx-line);border-radius:0;padding:20px 0;background:transparent}
.cnx-reviews-list .cnx-review:last-child{border-bottom:1px solid var(--cnx-line)}
@container cnxw (max-width: 900px){.cnx-review-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@container cnxw (max-width: 520px){.cnx-review-grid{grid-template-columns:minmax(0,1fr)}.cnx-reviews-n{font-size:2rem}}

/* ---- a photograph's focal point -------------------------------------- */
/* Nine classes on a 3x3 grid, written onto an <img> at publish time from
   the asset's own focalX/focalY (modules/canvasPhotos.php). object-position
   is what survives a crop: a hero band, a card's media box and a gallery
   tile all cover-fit their picture, and without this every one of them
   crops to the middle - which is how a portrait of a person ends up as a
   photograph of a shoulder. Dead centre is the browser's own default and
   deliberately has no class, so a site that never set one publishes the
   markup it always published. */
.cnx-fp-tl{object-position:left top}
.cnx-fp-tc{object-position:center top}
.cnx-fp-tr{object-position:right top}
.cnx-fp-ml{object-position:left center}
.cnx-fp-mc{object-position:center center}
.cnx-fp-mr{object-position:right center}
.cnx-fp-bl{object-position:left bottom}
.cnx-fp-bc{object-position:center bottom}
.cnx-fp-br{object-position:right bottom}
