/* ============================================================================
   Med&X member portal v2 — APP CSS (chrome, layout, overlays, responsive)
   Sources: Portal Chrome.dc.html (chrome), Mobile Portal.dc.html (≤430px
   pattern), responsive.css (≤900 / ≤700 / ≤500 rules — translated from the
   export's [style*=…] selectors to the class hooks the v2 templates carry),
   Profile.dc.html (toast), System Pages.dc.html + deploy/staging/launcher.js
   (waking overlay voice).
   Artboard markup keeps its inline styles verbatim; rules here only add
   behaviour (drawer motion, hover/focus, responsive overrides, overlays).
   ========================================================================== */

/* ---- base (from the artboards' own <style> blocks) ---------------------- */
html { -webkit-text-size-adjust: 100%; touch-action: manipulation; }   /* no double-tap zoom: a tap answers at once */
body { margin: 0; background: #f7f1e6; font-family: var(--font-ui); color: #191512; }
body[data-layout="auth"] { background: #191512; }
a { color: #9b1b22; text-decoration: none; transition: color var(--t-quick) var(--ease); }
@media (hover: hover) { a:hover { color: #191512; } }
::selection { background: rgba(201,169,98,.34); }
input, textarea, select, button { font-family: var(--font-ui); }
input:focus, textarea:focus { outline: 1px solid #9b1b22; outline-offset: -1px; }
/* every <select> is a hairline field like the inputs beside it, at the inputs' --r-sm (ROUND3-RULES §2). WebKit on iOS
   drew a pill with its own double chevron. The chevron is drawn here (the Accelerator form's). The !important beats the
   artboards' inline `background:` shorthand, which would otherwise reset the image */
select { -webkit-appearance: none; appearance: none; border-radius: var(--r-sm);
  background-image: linear-gradient(45deg, transparent 50%, #4a4239 50%), linear-gradient(135deg, #4a4239 50%, transparent 50%) !important;
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50% !important; background-size: 5px 5px, 5px 5px !important;
  background-repeat: no-repeat !important; padding-right: 30px !important; }
img { max-width: 100%; }
[hidden] { display: none !important; }

/* ---- corners (ROUND3-RULES §2, A1): tokens.css rounds the buttons, .btn-sm, .input, .chip and .card. The two classes it
   leaves square take their corners here (app.css loads after it). A switch is a rounded rectangle like the buttons,
   never a capsule (D3: capsules are for glass and chips), and its knob keeps the track's corner minus the inset between
   them. A view that makes a .btn-sm 44 px or taller gives it --r-md in its own stylesheet ---- */
.placeholder { border-radius: var(--r-lg); }
.toggle { border-radius: var(--r-xs); }
.toggle::after { border-radius: calc(var(--r-xs) - 2px); }

/* ---- brand lockup (top bar · mobile top bar) ----------------------------
   logo.png is a fixed-ratio asset — 750×165, i.e. 4.545:1. The bar that holds it is a flex row,
   and the lockup's anchor is a flex item at the default `flex: 0 1 auto`. Because its only child
   is an image already capped by `img { max-width: 100% }` two lines up, the anchor's min-content
   width collapses to zero, so it shrinks freely — and the image shrinks with it while the inline
   `height` stays pinned, compressing the logo horizontally only. Measured 71.0×17 (4.17:1, 8%
   squashed) on the 320px mobile bar, and up to 22% squashed on the desktop bar for a member with
   a long display name at 901–1050px. `flex: none` on the ANCHOR is the load-bearing half: the
   image is not the flex item, so width/flex on the image alone changes nothing. */
.mx-brand { flex: none !important; }
.mx-brand img { width: auto !important; max-width: none !important; }   /* height stays the inline one */

/* clickable spans from the artboards (onClick → data-act): pointer + keyboard focus ring */
[data-act], [data-nav] { cursor: pointer; }
[data-act]:focus-visible, [data-nav]:focus-visible, a:focus-visible, button:focus-visible, [role="switch"]:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid #9b1b22; outline-offset: 3px;
}
/* on the ink ground (drawer, tab bar, dark bands, photo heroes) the ring turns gold so it stays visible */
#mx-drawer :focus-visible, #mx-tabbar.is-dark :focus-visible, .mx-ink :focus-visible, .mx-toast :focus-visible, .mx-gbtn--dark:focus-visible,
[style*="background:#191512"] :focus-visible, .mx-waking :focus-visible, .btn-ghost-ink:focus-visible { outline-color: #c9a962; }
#mx-tabbar a:focus-visible { outline-offset: -4px; }
/* smooth-member 3.1: the disabled look is .4 (up from .55), no press and no feel (js/ui.js). A control waiting on its own
   tap (ui.bind's busy contract, data-mx-busy) keeps its look for 300 ms, then takes the calm busy look: never a flash */
[data-act][aria-disabled="true"]:not([data-mx-busy]) { opacity: .4; cursor: default; }
[data-mx-busy] { cursor: progress; }
[data-mx-busy="late"] { opacity: .62; transition: opacity var(--t-quick) var(--ease); }

/* ---- shell -------------------------------------------------------------- */
#app { position: relative; min-height: 100vh; }
#view { position: relative; }
/* Home artboard root: position:relative;overflow:hidden;min-height:100vh (inline on the view root) */
/* portal screens: the chrome and the screen share ONE window height. Each view root carries the artboard's
   inline min-height:100vh, but it sits under ~103 px of chrome (top bar + stats strip), so every short page
   scrolled that far into blank cream and Messages showed an empty band under its composer. #app is a column,
   the view takes what the chrome leaves, and the screen root fills exactly that */
body[data-layout="portal"] #app { display: flex; flex-direction: column; }
body[data-layout="portal"] #view { flex: 1 0 auto; display: flex; flex-direction: column; }
body[data-layout="portal"] #view > [data-screen-label] { flex: 1 0 auto; min-height: 0 !important; }
/* notch / home-indicator devices (the web app added to the Home Screen runs viewport-fit=cover): the desktop
   chrome, the drawer and the search sheet start below the status bar — the same elements and properties the
   iOS app's native layer uses, so the two never add up */
#mx-desktop-chrome { padding-top: env(safe-area-inset-top); }

/* ---- Portal Chrome: drawer + scrim (Portal Chrome.dc.html) --------------- */
/* The drawer/scrim markup and inline styles are verbatim; these rules only carry the
   open/closed state that the mock expressed through {{ dx }} {{ sc }} {{ pe }}. */
#mx-scrim { position: fixed; inset: 0; z-index: 40; transition: background-color var(--t-reveal) var(--ease-fade); background: rgba(25,21,18,0); pointer-events: none; cursor: pointer; }
/* Glass Quiet: the menu floats as dark glass 8px off the screen edges with 24px corners. The glass lives on ::before
   and the entries scroll inside .mx-dr-scroll, so the blur never scrolls away with them */
#mx-drawer { position: fixed; top: calc(8px + env(safe-area-inset-top)); bottom: calc(8px + env(safe-area-inset-bottom)); left: -320px; width: 300px; z-index: 41; color: #f7f1e6;
  border-radius: var(--r-drawer); overflow: hidden; isolation: isolate; background: transparent;
  transform: translateX(0px); display: flex; flex-direction: column; padding: 0; box-sizing: border-box; box-shadow: none; visibility: hidden;
  transition: box-shadow var(--spring-dur) var(--spring), visibility 0s linear var(--spring-dur); }
#mx-drawer::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; background: rgba(25,21,18,.78); box-shadow: var(--glass-edge-dark);
  -webkit-backdrop-filter: blur(var(--glass-blur-sheet)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur-sheet)) saturate(var(--glass-sat)); }
#mx-drawer > .mx-dr-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; padding: 24px 0 28px; box-sizing: border-box; }
/* the shadow only exists while the drawer is open — closed, its 44px blur used to bleed a grey band
   down the left edge of every page (the drawer parks at left:-312px, the blur reached ~40px in) */
body.drawer-open #mx-scrim { background: rgba(25,21,18,.32); pointer-events: auto; }
/* a list scrolled to its end inside the menu, a sheet or a dropdown never drags the page behind it along */
#mx-drawer, .mx-modal, .mx-search, .mx-modal-scroll { overscroll-behavior: contain; }
/* the menu slides on the ui spring both ways (ROUND3-RULES §4.1b and §7.2: no frame steps more than 8 percent of its 328 px
   plus 1 px), its lines follow on the enter spring. The slide itself is keyframes on the compositor (chrome.js › slideDrawer),
   the class says where the menu rests */
body.drawer-open #mx-drawer { transform: translateX(328px); box-shadow: var(--glass-shadow-dark); visibility: visible;
  transition: box-shadow var(--spring-dur) var(--spring), visibility 0s; }
#mx-drawer a, #mx-drawer [data-act] { transition: color var(--t-quick) var(--ease), background-color var(--t-quick) var(--ease), transform var(--t-quick) var(--ease); }
/* opening: the entries follow the panel in one after another — every menu line, not each list as a slab.
   chrome.openDrawer marks the lines .mx-dr-i with --dr-d (22 ms apart, capped at 160 ms) and sets
   .is-entering for one pass */
@media (prefers-reduced-motion: no-preference) {
  #mx-drawer.is-entering .mx-dr-i { animation: mx-drawer-in var(--spring-enter-dur) var(--spring-enter) backwards; animation-delay: var(--dr-d, 0ms); }
}
/* the lines fade in as the panel carries them (no travel of their own: two motions on one line stepped past the §7.2 bound) */
@keyframes mx-drawer-in { from { opacity: 0; } to { opacity: 1; } }
/* a menu entry leans in a few pixels under the pointer — the active one (gold rule) stays put */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  #mx-drawer a[href]:not([style*="border-left"]):hover { transform: translateX(4px); }
}

/* ---- top-bar dropdowns (SEARCH / ALERTS) — no artboard; built from tokens ---- */
.mx-pop { position: absolute; top: 60px; right: 36px; z-index: 35; width: 380px; max-width: calc(100vw - 36px); border-radius: var(--r-pop); overflow: hidden; box-shadow: var(--glass-shadow); }
.mx-pop-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--hair-soft); }
.mx-pop-list { max-height: 60vh; overflow-y: auto; overscroll-behavior: contain; }
.mx-pop-row { display: flex; gap: 12px; align-items: flex-start; padding: 11px 16px; border-bottom: 1px solid rgba(25,21,18,.1); color: #191512; cursor: pointer; }
.mx-pop-row { transition: background-color var(--t-quick) var(--ease), box-shadow var(--t-quick) var(--ease); }
@media (hover: hover) { .mx-pop-row:hover { background: var(--row-hover); } }
.mx-pop-row:last-child { border-bottom: 0; }
.mx-search { position: fixed; inset: 0; z-index: 50; background: rgba(25,21,18,.32); display: flex; align-items: flex-start; justify-content: center; padding: calc(10vh + env(safe-area-inset-top)) 18px 0; }
.mx-search-panel { width: 640px; max-width: 100%; border-radius: var(--r-pop); overflow: hidden; box-shadow: 0 16px 44px rgba(25,21,18,.22); }
.mx-search-panel input { border: 0; border-bottom: 1px solid rgba(25,21,18,.16); background: transparent; padding: 18px 20px; font: 16px var(--font-ui); color: #191512; width: 100%; box-sizing: border-box; }
.mx-search-panel input:focus { outline: 0; }
.mx-search-panel input::-webkit-search-cancel-button, .mx-search-panel input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
/* the field row: a magnifier, the 16px field and a 44px close (the phone had no visible way out but the backdrop) */
.mx-search-field { display: flex; align-items: center; gap: 10px; padding: 4px 4px 4px 18px; border-bottom: 1px solid var(--hair-soft); color: var(--soft); }
.mx-search-field > .mx-ic { flex: none; }
.mx-search-panel .mx-search-field input { flex: 1 1 auto; min-width: 0; width: auto; border-bottom: 0; padding: 14px 0; }
.mx-pop-scrim { display: none; }
@media (max-width: 500px) { .mx-pop-scrim { display: block; position: fixed; inset: 0; z-index: 34; background: rgba(25,21,18,.32); } }
.mx-search-group { padding: 14px 20px 6px; font: 600 12px/16px var(--font-ui); letter-spacing: .12em; color: #6e5626; }
/* SEARCH / ALERTS open with a short fade and a few pixels of travel; they fade out on close.
   chrome.js adds .mx-pop-in for the opening pass only (--pop-t continues it across a re-render). */
/* Entrances fill `backwards` only: a finished entrance must not keep an identity transform on the panel
   (it would stay a containing block for anything fixed or sticky inside it). Exits fill `forwards`. */
@media (prefers-reduced-motion: no-preference) {
  .mx-pop.mx-pop-in { animation: mx-drop-t var(--t-settle) var(--ease-settle) backwards; animation-delay: var(--pop-t, 0ms); }
  .mx-pop.mx-pop-in::before, .mx-pop.mx-pop-in > *, .mx-search.mx-pop-in .mx-search-panel::before, .mx-search.mx-pop-in .mx-search-panel > * {
    animation: mx-fade var(--t-reveal) var(--ease-fade) backwards; animation-delay: var(--pop-t, 0ms); }
  .mx-search.mx-pop-in { animation: mx-scrim-in var(--t-reveal) var(--ease-fade) backwards; animation-delay: var(--pop-t, 0ms); }
  .mx-search.mx-pop-in .mx-search-panel { animation: mx-drop-t var(--t-settle) var(--ease-settle) backwards; animation-delay: var(--pop-t, 0ms); }
  .mx-pop-scrim { animation: mx-scrim-in var(--t-reveal) var(--ease-fade) backwards; }
  .mx-search.mx-pop-out, .mx-pop-scrim.mx-pop-out { animation: mx-scrim-out var(--t-exit) var(--ease-exit) forwards; pointer-events: none; }
  .mx-pop.mx-pop-out { pointer-events: none; }
  .mx-pop.mx-pop-out::before, .mx-pop.mx-pop-out > *, .mx-search.mx-pop-out .mx-search-panel::before, .mx-search.mx-pop-out .mx-search-panel > * { animation: mx-fade-out var(--t-exit) var(--ease-exit) forwards; }
  .mx-pop.mx-pop-out, .mx-search.mx-pop-out .mx-search-panel { transform: translateY(-4px); box-shadow: none; transition: transform var(--t-exit) var(--ease-exit), box-shadow var(--t-exit) var(--ease-exit); }
}
@keyframes mx-scrim-in { from { background-color: rgba(25,21,18,0); } }
@keyframes mx-scrim-out { to { background-color: rgba(25,21,18,0); } }
/* the search panel: ↑ / ↓ move a visible active row (chrome.js › .is-active), Enter opens it */
.mx-pop-row.is-active { background: var(--row-hover); box-shadow: inset 2px 0 0 #c9a962; }
@keyframes mx-drop { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes mx-drop-t { from { transform: translateY(-8px); } to { transform: none; } }
@keyframes mx-fade-out { from { opacity: 1; } to { opacity: 0; } }

/* ---- toast (Profile.dc.html bottom toast, verbatim look) -----------------
   width:max-content — with left:50% the shrink-to-fit width was capped at the right HALF of the viewport,
   so on a phone a long toast was squeezed into a 195 px column six lines tall. It rises in at the reveal
   timing, lifted off the page by its shadow, and leaves at the exit timing. A toast wider than the window
   wraps (centred) instead of being cut off mid-word — it used to be nowrap above 500 px. */
/* Glass Quiet (GLASS-RULES §1.9.4): a dark glass capsule, 44 tall, 14px cream. Glass never fades its own opacity (its blur
   would go blind mid-fade): it rises in and settles while its glass layer and its words fade, and leaves the same way */
.mx-toast { position: fixed; left: 50%; bottom: calc(26px + env(safe-area-inset-bottom)); transform: translateX(-50%) translateY(14px) scale(.96); color: transparent; padding: 12px 22px;
  font: 500 14px/20px var(--font-ui); letter-spacing: 0; z-index: 70; white-space: normal; text-align: center; border-radius: var(--r-capsule); isolation: isolate;
  min-height: 44px; display: flex; align-items: center; justify-content: center;
  width: max-content; max-width: calc(100vw - 36px); box-sizing: border-box; box-shadow: none;
  transition: color var(--t-exit) var(--ease-exit), transform var(--t-exit) var(--ease-exit), box-shadow var(--t-exit) var(--ease-exit); }
.mx-toast::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; background: var(--glass-dark); box-shadow: var(--glass-edge-dark);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  opacity: 0; transition: opacity var(--t-exit) var(--ease-exit); }
.mx-toast.show { color: #f7f1e6; transform: translateX(-50%); pointer-events: auto; box-shadow: var(--glass-shadow-dark);
  transition: color var(--t-reveal) var(--ease-fade), transform var(--t-settle) var(--ease-settle), box-shadow var(--t-reveal) var(--ease-fade); }
.mx-toast.show::before { opacity: 1; transition: opacity var(--t-reveal) var(--ease-fade); }
/* a faded toast stays in the DOM — it must never catch the taps meant for the tab bar under it */
.mx-toast:not(.show) { pointer-events: none; }
/* the old words of a toast that takes a new message fade out over the pill, without a pill of their own (ui.swapText) */
.mx-toast.mx-glide-ghost::before { display: none; }
.mx-toast::before { background: rgba(25,21,18,.80); }   /* a toast floats over cream as often as over photos: the darker tint keeps 14px cream at 4.5:1 (§1.7) */
.mx-toast.error::before { background: rgba(110,18,24,.84); }
@media (max-width: 500px) { .mx-toast { max-width: calc(100vw - 32px); } }
/* phones: the toast floats 12px above the tab bar (--mx-tabbar-h already holds that gap), never under the home indicator */
@media (max-width: 500px) { body[data-layout="portal"] .mx-toast { bottom: max(var(--mx-tabbar-h), calc(12px + env(safe-area-inset-bottom))); } }

/* ---- modal / confirm (brand vocabulary: ink scrim, cream sheet, hairlines) ---- */
.mx-modal { position: fixed; inset: 0; z-index: 60; background: rgba(25,21,18,.32); display: flex; align-items: safe center; justify-content: center; padding: 18px; overflow-y: auto; }
/* a sheet taller than the window (REPORT on a small phone, the keyboard up) scrolls inside itself instead of
   running off the top and bottom of the screen with its × out of reach */
/* Glass Quiet (GLASS-RULES §1.9.4): the sheet is strong light glass, at --r-xl on every width (ROUND3-RULES §2: every
   sheet). The glass element never scrolls: the body and the actions scroll inside .mx-modal-scroll, the head (title or
   nothing, the ×) stays */
.mx-modal-sheet { width: 460px; max-width: 100%; box-shadow: 0 18px 50px rgba(25,21,18,.26), 0 1px 3px rgba(25,21,18,.10); border-radius: var(--r-xl); overflow: hidden;
  display: flex; flex-direction: column; max-height: calc(100vh - 36px); max-height: calc(100dvh - 36px); box-sizing: border-box; }
.mx-modal-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.mx-modal-sheet.is-wide { width: 880px; }   /* the photo viewer (ui.lightbox) */
.mx-modal-sheet:focus { outline: none; }   /* it holds focus on open (ui.modal): a container, not a control, so no ring */
/* the head: the sheet's title (the display face at 22) on the left or nothing, the close × in a 44px glass circle on the right. The caps
   eyebrow of the old head is gone (the title says it); without a title it stays as the dialog's hidden name */
.mx-modal-head { position: relative; flex: none; display: flex; align-items: center; gap: 12px; min-height: 60px; padding: 12px 12px 4px 22px; box-sizing: border-box; }
.mx-modal-head .mx-modal-title { flex: 1 1 auto; min-width: 0; margin: 0; font: var(--fw-title2) 22px/28px var(--font-display); letter-spacing: var(--ls-title2); color: #191512; text-wrap: balance; }
.mx-modal-eb { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.mx-modal-head [data-act="close"] { margin-left: auto; flex: none; color: var(--ink); }
.mx-modal-body { padding: 6px 22px 22px; font-size: 16px; color: #4a4239; line-height: 1.5; }
.mx-modal-body .mx-modal-title { font-family: var(--font-display); font-weight: var(--fw-title2); letter-spacing: var(--ls-title2); font-size: 22px; line-height: 1.15; color: #191512; margin-bottom: 10px; }
.mx-modal-foot { display: flex; gap: 10px; justify-content: flex-end; padding: 0 22px 22px; flex-wrap: wrap; }
/* a field a view draws inline inside a sheet takes the inputs' corner (ROUND3-RULES §2) */
.mx-modal-body :is(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), textarea, select) { border-radius: var(--r-sm); }
/* a sheet rises in and settles (--ease-settle) while its scrim fades in; closing, the pair fades out on the exit
   timing as the sheet sinks a few pixels. A sheet opened as another leaves (.is-chained, ui.modal) keeps the scrim
   that is already there at full strength — it never dips and fades in again. The leaving one lets its own go at once
   and fades out ABOVE it (.is-handed): one scrim on screen, and the leaving sheet never darkens under the new one */
@media (prefers-reduced-motion: no-preference) {
  .mx-modal { animation: mx-scrim-in var(--t-reveal) var(--ease-fade) backwards; }
  .mx-modal.is-chained { animation: none; }
  .mx-modal .mx-modal-sheet { animation: mx-settle-up var(--t-settle) var(--ease-settle) backwards; }
  .mx-modal .mx-modal-sheet::before, .mx-modal .mx-modal-sheet > * { animation: mx-fade var(--t-reveal) var(--ease-fade) backwards; }
  /* a sheet leaves on the sheet timing (ROUND3-RULES §4.1b: 450 to 550 ms, never under 250), as it came */
  .mx-modal.is-leaving { animation: mx-scrim-out var(--t-settle) var(--ease-fade) forwards; pointer-events: none; }
  .mx-modal.is-leaving .mx-modal-sheet { animation: mx-sink var(--t-settle) var(--ease-settle) forwards; box-shadow: none; transition: box-shadow var(--t-settle) var(--ease-fade); }
  .mx-modal.is-leaving .mx-modal-sheet::before, .mx-modal.is-leaving .mx-modal-sheet > * { animation: mx-fade-out var(--t-settle) linear forwards; }
}
.mx-modal.is-leaving { pointer-events: none; }
.mx-modal.is-leaving.is-handed { background: transparent; z-index: 61; }
@keyframes mx-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes mx-settle-up { from { transform: translateY(16px) scale(.985); } to { transform: none; } }
@keyframes mx-sink { to { transform: translateY(6px) scale(.99); } }

/* ---- "waking up" overlay (staging backend boots for up to ~2 min) --------- */
.mx-waking { position: fixed; inset: 0; z-index: 80; background: #191512; color: #f7f1e6; display: flex; align-items: center; justify-content: center; text-align: center; padding: 32px; }
.mx-waking-inner { max-width: 440px; display: flex; flex-direction: column; align-items: center; }
/* the display titles the views draw inline (font-family:var(--font-display)) take the title weight from their class */
.mx-display-30, .mx-display-34 { font-weight: var(--fw-title1); }
.mx-waking .line { font-family: var(--font-display); font-weight: var(--fw-display); letter-spacing: var(--ls-display); font-style: italic; font-size: 34px; line-height: 1.1; margin-top: 20px; }
.mx-waking .why { font-size: 14px; color: rgba(247,241,230,.8); margin: 14px 0 0; line-height: 1.6; }
.mx-waking .status { font: 600 12px var(--font-ui); letter-spacing: var(--ls-caps); color: #c9a962; margin-top: 22px; }
.mx-waking .bar { width: 120px; height: 1px; background: rgba(247,241,230,.18); margin-top: 18px; position: relative; overflow: hidden; }
.mx-waking .bar::after { content: ""; position: absolute; left: 0; top: 0; width: 40%; height: 100%; background: #c9a962; transform: translateX(-100%); animation: mx-sweep 1.6s var(--ease) infinite; }
@keyframes mx-sweep { from { transform: translateX(-100%); } to { transform: translateX(250%); } }   /* transform, not left — no layout per frame */
/* reduced motion: the sweep cannot run (the kill switch below stops it after one 1 ms pass, which parked it
   off the track and left an empty line that looked hung) — a still gold segment holds the track instead */
@media (prefers-reduced-motion: reduce) { .mx-waking .bar::after { animation: none !important; transform: translateX(75%); } }
/* it arrives and leaves as a fade (api.js hideWaking keeps it 420 ms for the exit), never a one-frame flash */
@media (prefers-reduced-motion: no-preference) {
  .mx-waking { animation: mx-fade var(--t-reveal) var(--ease-fade) backwards; }
  .mx-waking .mx-waking-inner { animation: mx-lift-in 520ms var(--ease) 80ms backwards; }
  .mx-waking.is-leaving { animation: mx-fade-out 400ms var(--ease-exit) forwards; }
}
.mx-waking.is-leaving { pointer-events: none; }

/* ---- hero photo rotation (Home photo band) ------------------------------ */
.mx-rotator img { transition: opacity var(--t-drift) var(--ease); }
.mx-rotator img.out { opacity: 0; }

/* ---- responsive (translated from responsive.css; hooks = class names) ----- */
@media (max-width: 900px) {
  .mx-gutter { padding-left: 18px !important; padding-right: 18px !important; }
  .mx-pad-hero { padding: 38px 18px 32px !important; }
  .mx-pad-band { padding: 16px 18px !important; }
  .mx-pad-36 { padding: 24px 18px !important; }
  .mx-topbar { height: auto !important; flex-wrap: wrap !important; padding: 10px 18px !important; gap: 10px 14px !important; }
  .mx-topbar > span, .mx-topbar > a { white-space: nowrap; }
  .mx-stats { flex-wrap: wrap !important; gap: 6px 16px !important; }
  /* the date strip and the email banner keep the 18 px gutter the top bar and the page switch to */
  .mx-stats, [data-role="banner"] { padding-left: 18px !important; padding-right: 18px !important; }
  .mx-wrap-row { flex-wrap: wrap !important; }
  .mx-wrap-center { flex-wrap: wrap !important; gap: 10px 18px !important; }
  .mx-grid-4, .mx-grid-6 { grid-template-columns: 1fr 1fr !important; }
  /* five cards: 3 + 2 on a tablet (two across left Building Bridges alone on a third row) */
  .mx-grid-5 { grid-template-columns: repeat(3, 1fr) !important; }
  .mx-grid-side, .mx-grid-latest, .mx-grid-hero { grid-template-columns: 1fr !important; }
  /* home › GETTING STARTED: the desktop card hugs the right edge (padding 0 left, 20 right) — stacked it
     sat flush against the left screen edge; give it the page gutter on both sides */
  .mx-grid-hero > [data-block="start"] { padding: 0 18px 22px !important; }
  .mx-w250 { width: 100% !important; max-width: 250px; }
  .mx-pop { right: 18px; }
}
/* Home › NEXT EVENT band: one row needs ~1,080 px. Below that it wraps — title and countdown on the first
   line, the two buttons together on their own — instead of an overflow:hidden ancestor cutting REGISTER off */
@media (max-width: 1100px) {
  .mx-next-event { flex-wrap: wrap !important; row-gap: 16px !important; }
  .mx-next-event > .mx-vrule { display: none !important; }
  .mx-next-event > .mx-cta-row { margin-left: 0 !important; flex-basis: 100%; flex-wrap: wrap; }
}
@media (max-width: 700px) {
  .mx-grid-3, .mx-grid-2 { grid-template-columns: 1fr !important; }
  .mx-topbar .mx-identity-text { display: none !important; }
  .mx-grid-5 { grid-template-columns: 1fr 1fr !important; }
  .mx-grid-5 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (max-width: 600px) {
  .mx-stats > span:first-child { flex-basis: 100%; white-space: nowrap; }
}
@media (max-width: 500px) {
  .mx-grid-5, .mx-grid-4, .mx-grid-6 { grid-template-columns: 1fr !important; }
  .mx-display-46 { font-size: 28px !important; }
  .mx-display-30 { font-size: 22px !important; }
  .mx-display-26 { font-size: 20px !important; }
  .mx-w230, .mx-w220 { width: 100% !important; }
}

/* ---- ≤500px: the Mobile Portal pattern (Mobile Portal.dc.html) ----------- */
/* Desktop chrome hides; the compact sticky top bar + ink bottom tab bar show. The view
   content keeps its desktop templates (stacked by the rules above) — "carry full content".
   Every phone gets it, the 440 px Pro Max / Plus included (it used to switch at 430 and hand those the
   desktop bar with 13 px text targets and no tab bar) — medx-native.css and boot.js say 500 too.
   The bar sticks: #chrome (its box) is the sticky element — a sticky bar inside a static header exactly as
   tall as itself had no room to stick and scrolled away with the page.
   Safe areas: in the web app added to the Home Screen the bar clears the clock and the tab bar the home
   indicator (same elements and values as the iOS app's layer, so the two never add up). */
#mx-mobile-top, #mx-tabbar, .mx-mobile-only { display: none !important; }
@media (max-width: 500px) {
  body[data-layout="portal"] #chrome { position: sticky; top: 0; z-index: 20; }
  body[data-layout="portal"] #mx-desktop-chrome { display: none !important; }
  body[data-layout="portal"] #mx-mobile-top, body[data-layout="portal"] .mx-mobile-only { display: flex !important; }
  body[data-layout="portal"] #mx-tabbar { display: flex !important; }
  body[data-layout="portal"] #mx-mobile-top { padding-top: calc(6px + env(safe-area-inset-top)) !important; }
  /* the space the floating tab bar keeps free (web bar or native bar, GLASS-RULES §1.10) */
  body[data-layout="portal"] #view { padding-bottom: var(--mx-tabbar-h); }
  /* ALERTS floats as a glass panel under the bar, 8px off both edges */
  .mx-pop { top: calc(100% + 4px); left: 8px; right: 8px; width: auto; max-width: none; }
}

/* Netlify HUD badge iframe overlaps bottom-right controls on the review deploy — hide it (2026-08-28) */
#nl-badge-frame, iframe[id^="nl-badge"] { display: none !important; pointer-events: none !important; }

/* ---- 44px tap targets (UXFIX-M2 #13, 2026-09-02; widened 2026-09-23) --------------------------------
   The audit measured 12px-tall tab links and 11px breadcrumb links at 390px. Type size stays;
   only the touch area grows. Two layers:
   · LAYOUT, phones and narrow split views (≤600px): section-tab strips become one left-aligned
     horizontally scrollable row instead of two centred wrapped rows; a long breadcrumb stays one row.
   · TARGETS, every phone AND every touch screen (pointer: coarse — an iPad gets the desktop chrome at
     every width, and it used to keep 11–14 px targets): tabs, breadcrumbs and chips take min-height:44px
     (inline-flex, centred); the small text controls keep their drawn size and get an invisible 44 px hit
     area (::after), so nothing on the page moves.
   Hooks: .mx-tabs (accelerator — class added). Strips and breadcrumb
   rows in views that carry no hook yet are matched by their verbatim artboard inline signature —
   the same [style*=…] technique the export's responsive.css used (see the header note above);
   when those views gain .mx-tabs / .mx-crumbs hooks the attribute selectors can be dropped. */
@media (max-width: 600px) {
  .mx-tabs,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"] {
    justify-content: flex-start !important; flex-wrap: nowrap !important;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .mx-tabs::-webkit-scrollbar,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"]::-webkit-scrollbar { display: none; }
  .mx-tabs > a, .mx-tabs > span,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"] > a,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"] > span { flex: none; }
  /* a three-step trail (PROJECTS → PLEXUS WEEK → PROGRAM & SPEAKERS) used to wrap at 390 px into two
     44 px rows with an arrow dangling at the end of the first; it stays one row, the current step
     yields with an ellipsis if it must */
  .mx-crumbs { flex-wrap: nowrap !important; gap: 9px !important; min-width: 0; }
  .mx-crumbs > * { flex: none; }
  .mx-crumbs > span[style*="color:#191512"], .mx-crumbs > .is-here { display: block !important; flex: 0 1 auto; min-width: 0; min-height: 0 !important; line-height: 43px !important; padding-top: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* hero eyebrow boxes break evenly instead of leaving one word alone on the second line */
  .mx-pad-hero > span:first-child { text-wrap: balance; }
}
@media (max-width: 600px), (pointer: coarse) {
  .mx-tabs,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"] {
    padding-top: 0 !important; padding-bottom: 0 !important;
  }
  .mx-tabs > a, .mx-tabs > span,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"] > a,
  .mx-gutter[style*="gap:26px;padding:13px 36px;border-bottom"] > span {
    display: inline-flex !important; align-items: center; min-height: 44px;
  }
  .mx-crumbs, .mx-gutter[style*="gap:13px;padding:10px 36px"] {
    padding-top: 0 !important; padding-bottom: 0 !important;
  }
  .mx-crumbs > a, .mx-crumbs > span,
  .mx-gutter[style*="gap:13px;padding:10px 36px"] > a,
  .mx-gutter[style*="gap:13px;padding:10px 36px"] > span {
    display: inline-flex !important; align-items: center; min-height: 44px;
  }
  .chip, .mx-nl-chips > span, .mx-profile-btn { min-height: 44px; display: inline-flex; align-items: center; box-sizing: border-box; }
  .mx-profile-btn { justify-content: center; }
  /* small text controls: the drawn size stays, an invisible hit area reaches 44 × 44 around the centre */
  .mx-topbar > [data-act], [data-act="hideStart"], [data-act="hideBanner"], .mx-switch, .mx-me-link, [data-act="present"],
  .mx-msg-link, .mx-msg-back, .mx-profile-x, .mx-profile-link, [data-act="editions"], [data-act="dlIcs"], [data-act="bioClose"],
  .mx-modal-head [data-act="close"], .mx-pop-head [data-act], #mx-mobile-top a[href="/app/me"],
  .mx-auth-screen a[href="/app/auth/reset"], .mx-net-act, .mx-msg-attach { position: relative; }
  .mx-topbar > [data-act]::after, [data-act="hideStart"]::after, [data-act="hideBanner"]::after, .mx-switch::after, .mx-me-link::after, [data-act="present"]::after,
  .mx-msg-link::after, .mx-msg-back::after, .mx-profile-x::after, .mx-profile-link::after, [data-act="editions"]::after, [data-act="dlIcs"]::after, [data-act="bioClose"]::after,
  .mx-modal-head [data-act="close"]::after, .mx-pop-head [data-act]::after, #mx-mobile-top a[href="/app/me"]::after,
  .mx-auth-screen a[href="/app/auth/reset"]::after, .mx-net-act::after, .mx-msg-attach::after {
    content: ""; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%);
  }
  /* …and every quiet text control on a screen (an unpadded link or [data-act] span: ALL SPEAKERS →, ALL PHOTOS →,
     EDIT PROFILE →, a link in running text), the logo, the member link, the ⋯ menus and every switch. What already
     draws with ::after keeps it: section tabs (their rule), the whole-card links (their stretched hit area), the
     event app (its own targets), and the PHONE CALM KIT's rows, cards and links (they are 44px+ by design) */
  #view a[href]:not([style*="padding"]):not(.mx-tab):not(.mx-card-link):not(.mx-proj-card):not(.lv *):not(.mx-week-card > a):not(:is(.mx-row, .mx-person-row, .mx-person, .mx-pcard, .mx-pcard-main, .mx-start-row, .mx-next-media, .mx-next-link, .mx-pcard-cta, .mx-sh-a, .mx-fact-go, .mx-fact, .mx-tile, .mx-tl-row, .mx-iconbtn, .mx-media, .mx-shelf-item, .mx-linkcard, .mx-seg > *, .mx-gbtn, .mx-tag--glass)),
  #view span[data-act]:not([style*="padding"]):not(.mx-tab):not(.chip):not(.lv *):not([data-act="vb"]):not(.mx-ph):not(:is(.mx-row, .mx-person-row, .mx-person, .mx-pcard, .mx-pcard-main, .mx-start-row, .mx-next-media, .mx-next-link, .mx-pcard-cta, .mx-sh-a, .mx-fact-go, .mx-fact, .mx-tile, .mx-tl-row, .mx-iconbtn, .mx-media, .mx-shelf-item, .mx-linkcard, .mx-seg > *, .mx-gbtn, .mx-tag--glass)),
  .mx-brand, .mx-topbar > a[href="/app/me"], .mx-safe-more, [role="switch"]:not(.lv-att) { position: relative; }
  #view a[href]:not([style*="padding"]):not(.mx-tab):not(.mx-card-link):not(.mx-proj-card):not(.lv *):not(.mx-week-card > a):not(:is(.mx-row, .mx-person-row, .mx-person, .mx-pcard, .mx-pcard-main, .mx-start-row, .mx-next-media, .mx-next-link, .mx-pcard-cta, .mx-sh-a, .mx-fact-go, .mx-fact, .mx-tile, .mx-tl-row, .mx-iconbtn, .mx-media, .mx-shelf-item, .mx-linkcard, .mx-seg > *, .mx-gbtn, .mx-tag--glass))::after,
  #view span[data-act]:not([style*="padding"]):not(.mx-tab):not(.chip):not(.lv *):not([data-act="vb"]):not(.mx-ph):not(:is(.mx-row, .mx-person-row, .mx-person, .mx-pcard, .mx-pcard-main, .mx-start-row, .mx-next-media, .mx-next-link, .mx-pcard-cta, .mx-sh-a, .mx-fact-go, .mx-fact, .mx-tile, .mx-tl-row, .mx-iconbtn, .mx-media, .mx-shelf-item, .mx-linkcard, .mx-seg > *, .mx-gbtn, .mx-tag--glass))::after,
  .mx-brand::after, .mx-topbar > a[href="/app/me"]::after, .mx-safe-more::after, [role="switch"]:not(.lv-att)::after {
    content: ""; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%);
  }
  [data-act="tgSpec"] { min-height: 44px; display: inline-flex; align-items: center; box-sizing: border-box; }
}

/* ---- monogram portrait (ui.monogram) — a person without a photo: gold initials on the ink ground,
   a hairline gold frame inset. Fills its positioned parent, font-size set per use (40 by default, a display size). ---- */
.mx-mono { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 95% at 30% 18%, #3a2f27 0%, #241d18 48%, #191512 100%);
  color: #c9a962; font-family: var(--font-display); font-weight: var(--fw-title1); letter-spacing: .05em; line-height: 1; user-select: none; }
.mx-mono::after { content: ''; position: absolute; inset: 8px; border: 1px solid rgba(201,169,98,.24); pointer-events: none; }

/* phone safety: a grid cell never grows past its track because of one long word or nowrap line
   (Plexus week cards and the Accelerator eligibility chips pushed the page 4px sideways at 390px) */
.mx-grid-2 > *, .mx-grid-3 > *, .mx-grid-4 > *, .mx-grid-5 > *, .mx-grid-6 > * { min-width: 0; }
@media (max-width: 560px) {
  .mx-week-grid { grid-template-columns: 1fr !important; }
  .mx-ax-chip { white-space: normal !important; line-height: 1.5; }
}

/* ============================================================================
   MOTION + INTERACTION LAYER (one language for every surface — tokens.css › --ease, --t-*)
   Rules: animate opacity / transform / colour / shadow only; hover lives under (hover: hover);
   nothing moves for prefers-reduced-motion; no transform on an ancestor of a sticky/fixed layer
   (#view itself only ever fades); entrances run on elements that exist at paint, from a visible
   end state, and are done within ~500 ms.
   ========================================================================== */

/* ---- screen entrance: the router adds .mx-enter AFTER the view has drawn its content (and takes it
   off again a second later), so the fade shows the page itself, not an empty frame while data loads ---- */
@keyframes mx-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes mx-lift-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes mx-settle { from { transform: scale(1.045); } to { transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  #view.mx-enter { animation: mx-fade var(--t-reveal) var(--ease) backwards; }
  /* card grids cascade in — 35 ms apart, capped so the last card lands by ~500 ms */
  #view.mx-enter :is(.mx-grid-2, .mx-grid-3, .mx-grid-4, .mx-grid-5, .mx-ax-hosts) > * { animation: mx-lift-in var(--t-reveal) var(--ease) backwards; }
  #view.mx-enter :is(.mx-grid-2, .mx-grid-3, .mx-grid-4, .mx-grid-5, .mx-ax-hosts) > :nth-child(2) { animation-delay: 35ms; }
  #view.mx-enter :is(.mx-grid-2, .mx-grid-3, .mx-grid-4, .mx-grid-5, .mx-ax-hosts) > :nth-child(3) { animation-delay: 70ms; }
  #view.mx-enter :is(.mx-grid-2, .mx-grid-3, .mx-grid-4, .mx-grid-5, .mx-ax-hosts) > :nth-child(4) { animation-delay: 105ms; }
  #view.mx-enter :is(.mx-grid-2, .mx-grid-3, .mx-grid-4, .mx-grid-5, .mx-ax-hosts) > :nth-child(n+5) { animation-delay: 140ms; }
  /* hero copy rises in line by line — eyebrow, headline, lead, actions */
  #view.mx-enter :is(.mx-pad-hero, .mx-pad-hero-z, .mx-pad-mine) > * { animation: mx-lift-in var(--t-reveal) var(--ease) backwards; }
  #view.mx-enter :is(.mx-pad-hero, .mx-pad-hero-z, .mx-pad-mine) > :nth-child(2) { animation-delay: 40ms; }
  #view.mx-enter :is(.mx-pad-hero, .mx-pad-hero-z, .mx-pad-mine) > :nth-child(3) { animation-delay: 80ms; }
  #view.mx-enter :is(.mx-pad-hero, .mx-pad-hero-z, .mx-pad-mine) > :nth-child(4) { animation-delay: 115ms; }
  #view.mx-enter :is(.mx-pad-hero, .mx-pad-hero-z, .mx-pad-mine) > :nth-child(n+5) { animation-delay: 140ms; }
  /* photo heroes settle into place with a slow, barely-there zoom-out. Only on a screen drawn without a crossing: during a
     push the crossing is the one motion (ROUND3-RULES §4.1), and a Ken Burns hero never settles (kit.css) */
  #view.mx-enter:not(.mx-vt) .mx-hero-photo { animation: mx-settle var(--t-drift) var(--spring-enter) backwards; }
  /* a stage hero's photo already carries a transform, translate3d(0, var(--py), 0) written by ui.recede on scroll (kit.css,
     ROUND3-RULES §6.1): its settle is the scale property alone, so a scroll inside the settle moves the photo with the page
     and never snaps. An engine without the scale property skips this settle */
  #view.mx-enter:not(.mx-vt) .mx-hero--stage > .mx-hero-photo { animation-name: mx-settle-scale; }
}
@keyframes mx-settle-scale { from { scale: 1.045; } to { scale: 1; } }
/* ink fact bands (Plexus / Gala countdowns, Accelerator stats): a line break after the countdown that exists only
   once the band no longer fits one row — each view's css switches it on at that width, together with hiding the
   vertical rules, so a rule is never left dangling at a line end and no fact sits alone on a second row */
.mx-band-break { display: none; }
/* the photo heroes sit on ink, so a photo still arriving rises out of the dark, never out of cream */
.mx-ink { background: #191512; }

/* ---- between screens (router.js › holdLeaving): the screen you are leaving stays where it is until the
   next one has drawn — no blank frame. It is never clickable or focusable (inert). A warm server answers
   inside ~250 ms and nothing else shows; past that (a cold server) the old screen dims and a gold hairline
   creeps along the top of the window, then sweeps home and fades as the new screen lands (body.mx-held —
   on the body, not in #view, so the new screen's own fade never swallows the sweep).
   On a tab switch the breadcrumb and the tab strip stay lit, the tab you pressed takes its underline at
   once, and only the content around them rises in (.mx-enter-tab › .mx-tab-in) while the rule slides.
   The ~250 ms threshold is a router TIMER (body.mx-slow), not a css delay, so reduced motion keeps it:
   there the old screen dims and a still hairline shows, both at once, with nothing travelling. ---- */
#view .mx-leaving { pointer-events: none; }
/* round 3 (Phase 2A): a return from the background re-reads the screen (router.js › watchLife). Until the fresh read lands,
   the pay, register, reserve and join controls hold their taps (a capture listener) and dim a little, the same list as
   router.js › PAY_GUARD (VIEW-CONTRACT §9). Nothing about them changes but their opacity */
html.mx-paycheck #view :is([data-pay-guard], a[href*="pick="], a[href*="pay" i], a[href*="register" i], a[href*="reserve" i], a[href*="checkout" i],
  [data-act*="pay" i], [data-act*="register" i], [data-act*="reserve" i], [data-act*="join" i], [data-act*="transfer" i], [data-act*="checkout" i]),
html.mx-paycheck .mx-actionbar-btn,
/* smooth-member 2.4: a kept screen shown at once holds those controls silently (html.mx-payhold, no look of its own) until its
   fresh read lands; a tap that waits on it past 400 ms dims them the same way (html.mx-paywait, router.js › holdPay) */
html.mx-paywait #view :is([data-pay-guard], a[href*="pick="], a[href*="pay" i], a[href*="register" i], a[href*="reserve" i], a[href*="checkout" i],
  [data-act*="pay" i], [data-act*="register" i], [data-act*="reserve" i], [data-act*="join" i], [data-act*="transfer" i], [data-act*="checkout" i]),
html.mx-paywait .mx-actionbar-btn { opacity: .55; transition: opacity var(--t-quick) var(--ease); }
/* round 3 (Phase 2B): a kept screen with pay controls or payment state comes back from the router's stack hidden until its
   re-read from the answers that just landed has updated it in place (router.js › restoreRender, VIEW-CONTRACT §12), so its
   old state is never painted or tapped. The re-read normally ends before the first frame */
#view.mx-restoring > * { visibility: hidden; }
body::before { content: ""; position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 75; background: #c9a962; pointer-events: none;
  opacity: 0; transform: scaleX(0); transform-origin: 0 50%; }
body.mx-holding.mx-slow #view .mx-leaving { opacity: .7; }
body.mx-holding.mx-slow::before { opacity: 1; transform: scaleX(.9); }
@media (prefers-reduced-motion: no-preference) {
  body.mx-holding.mx-slow #view .mx-leaving { transition: opacity var(--t-reveal) var(--ease); }
  body.mx-holding.mx-slow::before { transition: transform 9s cubic-bezier(.08,.7,.2,1), opacity 0s; }
  body.mx-held::before { opacity: 0; transform: none; transition: transform var(--t-quick) var(--ease), opacity var(--t-reveal) var(--ease) var(--t-quick); }
}
@media (prefers-reduced-motion: reduce) { body.mx-holding.mx-slow::before { opacity: .55; transform: none; } }

/* ---- SCREEN CHANGES (router.js › ctx.ready — View Transitions: Safari and the iOS app from 18, Chrome 111+).
   Once the new screen has its data the two screens cross over; the page never blanks in between.
   Phones (≤500 px, the iOS app's iPhone): a step forward is the native push — the new screen slides in from the
   right edge over the one left behind, which drifts a third of the way left and dims a little; back is the same in
   reverse (the screen on top slides off to the right). The top bar and the tab bar hold still (the bar's title and
   back arrow cross-fade in place); a bar that exists on one side only (the event app has none) travels with its
   screen. Wider screens (iPad, desktop): the screens dissolve into each other while drifting a few pixels the way
   you are going. A jump from the tab bar, the menu or the logo and another tab of a section dissolve in place;
   dissolves keep the browser's additive blend with matched curves, so whatever the two screens share (a breadcrumb,
   a heading, a band, the cream ground) stays perfectly still — no dip, no flash. A re-read of the same screen (pull
   to refresh) has no crossing at all: it updates in place. Reduced motion: a plain short dissolve, nothing travels.
   Browsers without the API keep the #view fade below. */
/* layers of their own only for the steps that travel (a dissolve keeps whatever the two screens share still by
   itself; WebKit also drew named bars a few hundred px off for a frame when a dissolve left a scrolled page) */
/* html.mx-vt-step: a push or a pop (forward, back, and the photo morph the router may turn them into inside the update) */
html.mx-vt-step.mx-vt-bars #mx-tabbar { view-transition-name: mx-tabbar; }
html.mx-vt-step.mx-vt-chrome body[data-layout="portal"] #chrome { view-transition-name: mx-chrome; }
html.mx-vt-step .mx-toast { view-transition-name: mx-toast; }
/* round 3 (Phase 2A): the web tab bar (browsers, and the app below iOS 26) keeps still through every crossing. A layer of
   its own, drawn solid while it crosses, its two pictures stacked still with no blend (the new one live on top, so a tab
   jump's lens slides). It used to fade almost to nothing mid-push and pop back at the end (map item 12, finding 4):
   WebKit blended the group's default cross-fade into the screens under it, which a hidden old picture does not cure
   (measured in Playwright WebKit, round3/after/phase2a/engine) */
html[data-mx-nav] #mx-tabbar.mx-glass::before { background: var(--glass-solid-light); -webkit-backdrop-filter: none; backdrop-filter: none; }
/* r5 (router.js › holdOffscreen): what lies wholly outside the screen when a crossing ends is drawn a frame later. Its visibility
   only, so no box moves. Inherited: no descendant rule (a '.mx-off *' made every style pass look up its ancestors), and the
   few parts that set visibility: visible themselves (the action bar, the FAB, the drawer) are fixed and never held */
.mx-off { visibility: hidden !important; }
html[data-mx-nav] #mx-tabbar.mx-glass.is-dark::before { background: var(--glass-solid-dark); }
::view-transition-group(mx-tabbar) { animation: none; }
::view-transition-old(mx-tabbar), ::view-transition-new(mx-tabbar) { animation: none; mix-blend-mode: normal; }
/* fix round 1: the phone top bar is drawn solid the same way while a crossing runs (its opacity still --bar-p, its tone
   --bar-t). Scrolled, the bar is part of the screen's picture, and WebKit draws a picture with no backdrop-filter: the page's
   text showed through the Plexus Week bar for the whole Back slide and the glass snapped back on the last frame */
html[data-mx-nav] #mx-mobile-top.mx-mt::before { background: var(--glass-solid-light); -webkit-backdrop-filter: none; backdrop-filter: none; }
html[data-mx-nav] #mx-mobile-top.mx-mt.is-dark::before { background: var(--glass-solid-dark); }
@supports (background: color-mix(in srgb, red calc(.5 * 100%), blue)) {
  html[data-mx-nav] #mx-mobile-top.mx-mt::before,
  html[data-mx-nav] #mx-mobile-top.mx-mt.is-dark::before { background: color-mix(in srgb, var(--glass-solid-dark) calc(var(--bar-t, 0) * 100%), var(--glass-solid-light)); }
}
/* the bars stay above a photo that grows or shrinks under them, and above what lies on that photo (the morph below) */
::view-transition-group(mx-tabbar), ::view-transition-group(mx-chrome), ::view-transition-group(mx-toast) { z-index: 3; }
::view-transition-new(mx-chrome):only-child { mix-blend-mode: normal; }
.mx-vt-tabs { view-transition-name: mx-tabs; }
.mx-vt-tabs-in { view-transition-name: mx-tabs-in; }
:root { --vt-push: 440ms; --vt-push-ease: cubic-bezier(.32,.72,0,1); --vt-drift: 340ms; --vt-fade: 300ms; --vt-fade-ease: cubic-bezier(.4,0,.2,1); --vt-jump: 140ms; }
/* a tab jump (the tab bar, the phone wordmark) is no crossing: the root is drawn at once, in the tap's task, on the lens's
   frame, and fades up from .45 in 140 ms. Nothing else moves (§4.2 web tab switch, one motion per moment) */
#view.mx-enter-jump { animation: mx-jump-in var(--vt-jump) var(--vt-fade-ease) both; }
@keyframes mx-jump-in { from { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { #view.mx-enter-jump { animation: none; } }
/* a tab switch (the tab bar, web or native, and the phone wordmark: router.js › rootIn, ROUND3-RULES §4.2 the tab switch
   line, Alen 27 Sept): a veil of the page's ground fades over the root being left for 120 ms (router.js › rootOut), the new
   root is drawn under it meanwhile, then the veil fades away as the new root settles from scale .985 and a 6 px rise to rest
   on the ui spring, about the middle of the window (--mx-root-oy). Both play as keyframes on the compositor (router.js ›
   settleRoot, ui.springFrames). No slide, no overlap. #view carries no fixed box (plexus.css says the same for its band), so
   the scale moves nothing but the page. The tab bar and the top bar stay still: they live outside #view. Reduce Motion: out
   over 80 ms, in over 160 ms, opacity only */
#view.mx-enter-root { transform-origin: 50% var(--mx-root-oy, 50%); }
/* a tab jump's shell on its first frame (router.js › drawShell): the glass on its photos is drawn one frame later, so the
   frame on the lens's tap is cheap to paint. A hidden glass layer loses its backdrop too: an element with a backdrop-filter
   takes a layer of its own even while hidden, and inside a photo's masked box (.mx-media) that layer made the whole card a
   masked layer. The photos themselves stay: hidden for a frame, a hero showed as a flat ink box */
#view.mx-bare :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip) { visibility: hidden; }
#view.mx-bare :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip)::before { -webkit-backdrop-filter: none; backdrop-filter: none; }
/* Reduce Motion: the reset below gives every box and pseudo-element a 1 ms transition, so the glass coming back after
   mx-bare was a visibility transition that WebKit drew hidden for one or two more frames. Through the jump's entrance
   (#view.mx-enter-jump, one second) the glass and what it holds take no transition, and it shows on the next frame here too */
@media (prefers-reduced-motion: reduce) {
  #view:is(.mx-enter-jump, .mx-enter-root) :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip),
  #view:is(.mx-enter-jump, .mx-enter-root) :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip) *,
  #view:is(.mx-enter-jump, .mx-enter-root) :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip)::before,
  #view:is(.mx-enter-jump, .mx-enter-root) :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip)::after,
  #view:is(.mx-enter-jump, .mx-enter-root) :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip) *::before,
  #view:is(.mx-enter-jump, .mx-enter-root) :is(.mx-glass, .mx-tag--glass, .mx-gbtn, .mx-countdown--chip) *::after { transition: none !important; }
}
/* a kept screen back on a tab jump (router.js › holdPhotos): a photo on view is drawn once it is decoded, the box under it
   showing meanwhile, so its decode never holds the frame. Under Reduce Motion no transition brings it back (the reset's
   1 ms one would draw it hidden a frame or two longer, as it did the glass above) */
#view img[data-mx-pic] { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { #view:is(.mx-enter-jump, .mx-enter-root) img { transition: none !important; } }
/* a shell's held places (VIEW-CONTRACT §2): what the view fills once a read the cache never holds has landed (Home's next
   event action, a project card's action row, the lines on the member card). The box keeps its final size and shows no
   label, never a guess. .mx-hold takes a box's own size (a button), .mx-hold-line is one line of text in the colour of
   the words around it. Still: a pulse would be a second ambient loop (ROUND3-RULES §4.1) */
#view .mx-hold { color: transparent; background: rgba(25,21,18,.06); border-color: transparent; box-shadow: none; pointer-events: none; }
#view .mx-hold > * { visibility: hidden; }
#view .mx-hold-line { display: inline-block; max-width: 100%; border-radius: var(--r-xs, 6px); background: currentColor; opacity: .12; pointer-events: none; }
/* a segmented control's place in a shell (render() mounts the real ui.seg over it): the kit's track and item metrics
   (kit.css › ui.seg) with the labels and no lens, so the fill only adds the lens. Its own names, so the §7.3 inventory
   gate counts no second control. The kit's ui.seg markup stays the one source for the control itself */
#view .mx-hold-track { position: relative; display: flex; align-items: center; max-width: 100%; min-height: 44px; padding: 4px; box-sizing: border-box;
  border-radius: var(--r-capsule); background: rgba(25,21,18,.06); box-shadow: inset 0 0 0 .5px rgba(25,21,18,.08); overflow: hidden; pointer-events: none; }
#view .mx-hold-track > span { flex: 1 0 auto; display: inline-flex; align-items: center; justify-content: center; min-height: 36px; padding: 0 16px; box-sizing: border-box;
  font: 500 var(--fs-2nd)/20px var(--font-ui); letter-spacing: 0; color: var(--soft); white-space: nowrap; }
#view .mx-hold-track > span.is-lit { color: var(--ink); font-weight: 600; }
#view .mx-hold-track i { display: inline-grid; justify-items: center; font-style: normal; }
#view .mx-hold-track i::after { content: attr(data-label); font-weight: 600; height: 0; overflow: hidden; visibility: hidden; }
#view .mx-sh > .mx-hold-track { flex: none; margin-left: auto; }
@media (max-width: 400px) { #view .mx-hold-track > span { flex: 1 1 auto; padding: 0 10px; } }
@media (max-width: 360px) { #view .mx-hold-track > span { padding: 0 7px; font-size: 13px; } }
::view-transition-group(*) { animation-duration: var(--vt-drift); animation-timing-function: var(--ease); }
/* dissolves: the default additive cross-fade, eased in and out (a front-loaded curve read as a cut) */
::view-transition-old(root) { animation: mx-vt-fade-out var(--vt-fade) var(--vt-fade-ease) both; }
::view-transition-new(root) { animation: mx-vt-fade-in var(--vt-fade) var(--vt-fade-ease) both; }
/* wider screens: a dissolve that drifts the way you are going. The fade eases in and out like the other dissolves
   (on the front-loaded --ease, 40 % of the change landed in the first frame or two); the drift keeps --ease */
html[data-mx-nav="forward"]::view-transition-old(root) { animation: mx-vt-fade-out var(--vt-drift) var(--vt-fade-ease) both, mx-vt-drift-out-l var(--vt-drift) var(--ease) both; }
html[data-mx-nav="forward"]::view-transition-new(root) { animation: mx-vt-fade-in var(--vt-drift) var(--vt-fade-ease) both, mx-vt-drift-in-r var(--vt-drift) var(--ease) both; }
html[data-mx-nav="back"]::view-transition-old(root) { animation: mx-vt-fade-out var(--vt-drift) var(--vt-fade-ease) both, mx-vt-drift-out-r var(--vt-drift) var(--ease) both; }
html[data-mx-nav="back"]::view-transition-new(root) { animation: mx-vt-fade-in var(--vt-drift) var(--vt-fade-ease) both, mx-vt-drift-in-l var(--vt-drift) var(--ease) both; }
@keyframes mx-vt-fade-out { to { opacity: 0; } }
@keyframes mx-vt-fade-in { from { opacity: 0; } }
@keyframes mx-vt-drift-out-l { to { transform: translateX(-16px); } }
@keyframes mx-vt-drift-out-r { to { transform: translateX(16px); } }
@keyframes mx-vt-drift-in-r { from { transform: translateX(24px); } }
@keyframes mx-vt-drift-in-l { from { transform: translateX(-24px); } }
/* phones: the push. The screen on top is opaque and carries a soft edge shadow; the one under it dims */
@media (max-width: 500px) {
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-old(root),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-new(root) { mix-blend-mode: normal; }
  html[data-mx-nav="forward"]::view-transition-old(root) { animation: mx-vt-under-l var(--vt-push) var(--vt-push-ease) both; }
  html[data-mx-nav="forward"]::view-transition-new(root) { animation: mx-vt-over-in var(--vt-push) var(--vt-push-ease) both; box-shadow: -10px 0 28px rgba(25,21,18,.14); }
  html[data-mx-nav="back"]::view-transition-old(root) { animation: mx-vt-over-out var(--vt-push) var(--vt-push-ease) both; z-index: 1; box-shadow: -10px 0 28px rgba(25,21,18,.14); }
  html[data-mx-nav="back"]::view-transition-new(root) { animation: mx-vt-under-in var(--vt-push) var(--vt-push-ease) both; }
  /* a bar on one side only rides with its screen */
  html[data-mx-nav="forward"]::view-transition-old(*):only-child { animation: mx-vt-under-l var(--vt-push) var(--vt-push-ease) both; }
  html[data-mx-nav="forward"]::view-transition-new(*):only-child { animation: mx-vt-over-in var(--vt-push) var(--vt-push-ease) both; }
  html[data-mx-nav="back"]::view-transition-old(*):only-child { animation: mx-vt-over-out var(--vt-push) var(--vt-push-ease) both; }
  html[data-mx-nav="back"]::view-transition-new(*):only-child { animation: mx-vt-under-in var(--vt-push) var(--vt-push-ease) both; }
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(*) { animation-duration: var(--vt-push); animation-timing-function: var(--vt-push-ease); }
}
@keyframes mx-vt-over-in { from { transform: translateX(100%); } }
@keyframes mx-vt-over-out { to { transform: translateX(100%); } }
@keyframes mx-vt-under-l { to { transform: translateX(-30%); filter: brightness(.9); } }
@keyframes mx-vt-under-in { from { transform: translateX(-30%); filter: brightness(.9); } }
/* the shared-element photo morph (ROUND3-RULES §5.2, VIEW-CONTRACT §7): the router names the tapped card's photo and the
   new screen's hero photo mx-morph (or, on Back, the hero's photo and the card's). Only the photo: it travels and resizes on
   the push curve, its corners going from --mx-morph-r0 to --mx-morph-r1 (§4.1 exception 4), both pictures covering the
   moving box. What lies on a photo (a card's tag, a hero's scrim, its words and action) is named mx-mo-o1..4 on
   the screen being left and mx-mo-n1..4 on the new one, and stays where it is above the photo: the old side's is gone in the
   first 120 ms, the new side's comes in over the last 200 ms, so no tag or title is drawn scaled or twice and nothing pops
   in at the end. The screens around them dissolve in place (nothing slides while a photo grows) */
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(root) { animation: mx-vt-fade-out var(--vt-push) var(--vt-fade-ease) both; }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(root) { animation: mx-vt-fade-in var(--vt-push) var(--vt-fade-ease) both; }
::view-transition-group(mx-morph) { z-index: 1; animation-duration: var(--vt-push); animation-timing-function: var(--vt-push-ease); overflow: hidden; }
::view-transition-image-pair(mx-morph) { isolation: auto; }
::view-transition-old(mx-morph), ::view-transition-new(mx-morph) { inset: 0; width: 100%; height: 100%; object-fit: cover; mix-blend-mode: normal; overflow: hidden; }
::view-transition-old(mx-morph) { animation: mx-morph-r var(--vt-push) var(--vt-push-ease) both; }
::view-transition-new(mx-morph) { animation: mx-vt-fade-in 180ms var(--ease-fade) both, mx-morph-r var(--vt-push) var(--vt-push-ease) both; }
/* Back: the card's small picture would show blown up at the hero's size, so the hero's own picture carries the start and
   the card's comes in once the box is near its size */
html[data-mx-nav="morph-back"]::view-transition-new(mx-morph) { animation: mx-vt-fade-in 180ms var(--ease-fade) 170ms both, mx-morph-r var(--vt-push) var(--vt-push-ease) both; }
::view-transition-group(mx-mo-o1), ::view-transition-group(mx-mo-o2), ::view-transition-group(mx-mo-o3), ::view-transition-group(mx-mo-o4),
::view-transition-group(mx-mo-n1), ::view-transition-group(mx-mo-n2), ::view-transition-group(mx-mo-n3), ::view-transition-group(mx-mo-n4) { z-index: 2; }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-o1),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-o2),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-o3),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-o4) {
  animation: mx-vt-fade-out 120ms var(--ease-fade) both; mix-blend-mode: normal; }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-n1),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-n2),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-n3),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-n4) {
  animation: mx-vt-fade-in 200ms var(--ease-fade) 240ms both; mix-blend-mode: normal; }
/* r2 (router.js › nameMorph): the light over the photo (its melt, shade, scrim) cross-fades over the whole push, so the photo
   is never bare between the two screens' light, and the words that read the same on both sides (the Plexus title and its
   dates, Home's top to the Plexus top) travel with the photo on the push curve. Words with no partner fade as the others */
::view-transition-group(mx-mo-go1), ::view-transition-group(mx-mo-go2), ::view-transition-group(mx-mo-go3), ::view-transition-group(mx-mo-go4),
::view-transition-group(mx-mo-gn1), ::view-transition-group(mx-mo-gn2), ::view-transition-group(mx-mo-gn3), ::view-transition-group(mx-mo-gn4) { z-index: 2; }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-go1),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-go2),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-go3),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-go4) {
  animation: mx-vt-fade-out var(--vt-push) var(--vt-fade-ease) both; mix-blend-mode: normal; }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-gn1),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-gn2),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-gn3),
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-gn4) {
  animation: mx-vt-fade-in var(--vt-push) var(--vt-fade-ease) both; mix-blend-mode: normal; }
::view-transition-group(mx-mo-s1), ::view-transition-group(mx-mo-s2), ::view-transition-group(mx-mo-s3) {
  z-index: 3; animation-duration: var(--vt-push); animation-timing-function: var(--vt-push-ease); }
::view-transition-old(mx-mo-s1), ::view-transition-old(mx-mo-s2), ::view-transition-old(mx-mo-s3),
::view-transition-new(mx-mo-s1), ::view-transition-new(mx-mo-s2), ::view-transition-new(mx-mo-s3) { animation-duration: var(--vt-push); animation-timing-function: var(--vt-push-ease); }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-s1):only-child,
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-s2):only-child,
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-old(mx-mo-s3):only-child { animation: mx-vt-fade-out 120ms var(--ease-fade) both; }
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-s1):only-child,
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-s2):only-child,
html:is([data-mx-nav="morph"], [data-mx-nav="morph-back"])::view-transition-new(mx-mo-s3):only-child { animation: mx-vt-fade-in 200ms var(--ease-fade) 240ms both; }
/* a photo that found no partner (the router names it before it can know) rides with its screen under the push rules above.
   On a phone it goes under both screens, so it never floats over the screen sliding in */
@media (max-width: 500px) {
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-go1),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-go2),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-go3),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-go4),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-s1),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-s2),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-s3),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-morph),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-o1),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-o2),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-o3),
  html:is([data-mx-nav="forward"], [data-mx-nav="back"])::view-transition-group(mx-mo-o4) { z-index: -1; }
}
/* a photo with no partner on the new screen (its card is off screen, the screen has no hero) stays part of its screen:
   on a phone it rides with it (the "(*):only-child" push rules above), on a wider screen it drifts and dissolves with it */
@media (min-width: 501px) {
  html[data-mx-nav="forward"]::view-transition-old(mx-morph):only-child { animation: mx-vt-fade-out var(--vt-drift) var(--vt-fade-ease) both, mx-vt-drift-out-l var(--vt-drift) var(--ease) both; }
  html[data-mx-nav="back"]::view-transition-old(mx-morph):only-child { animation: mx-vt-fade-out var(--vt-drift) var(--vt-fade-ease) both, mx-vt-drift-out-r var(--vt-drift) var(--ease) both; }
}
@keyframes mx-morph-r { from { border-radius: var(--mx-morph-r0, 0px); } to { border-radius: var(--mx-morph-r1, 0px); } }
/* the tab strip, drawn in the same spot: the new strip at once (its rule slides from the old tab), never a ghost of
   the old one. Drawn elsewhere (router.js › nameTabs): the old strip fades out where it was, the new one fades in */
::view-transition-old(mx-tabs) { animation: none; opacity: 0; }
::view-transition-new(mx-tabs) { animation: none; }
::view-transition-old(mx-tabs):only-child { animation: mx-vt-fade-out var(--vt-fade) var(--vt-fade-ease) both; opacity: 1; }
::view-transition-group(mx-tabs-in) { animation: none; }
::view-transition-new(mx-tabs-in) { animation: mx-vt-fade-in var(--vt-fade) var(--vt-fade-ease) both; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*) { animation: none !important; }
  ::view-transition-old(*) { animation: mx-vt-fade-out 160ms linear both !important; mix-blend-mode: plus-lighter !important; box-shadow: none !important; }
  ::view-transition-new(*) { animation: mx-vt-fade-in 160ms linear both !important; mix-blend-mode: plus-lighter !important; box-shadow: none !important; }
  ::view-transition-old(mx-tabs) { animation: none !important; opacity: 0; }
  ::view-transition-new(mx-tabs) { animation: none !important; }
  ::view-transition-old(mx-tabs):only-child { animation: mx-vt-fade-out 160ms linear both !important; opacity: 1; }
  ::view-transition-old(mx-tabbar), ::view-transition-new(mx-tabbar) { animation: none !important; mix-blend-mode: normal !important; }
}
/* crossed over (#view.mx-vt): the crossing is the entrance, so the #view fade, the card / hero / tab-content cascades and
   the photo settle stand down (one motion per moment, ROUND3-RULES §4.1). The tab rule still runs inside the new screen */
#view.mx-vt.mx-enter { animation: none; }
#view.mx-vt.mx-enter :is(.mx-grid-2, .mx-grid-3, .mx-grid-4, .mx-grid-5, .mx-ax-hosts, .mx-pad-hero, .mx-pad-hero-z, .mx-pad-mine) > * { animation: none; }
#view.mx-vt.mx-enter-tab .mx-tab-in { animation: none; }

.mx-tab.is-pending { color: #191512 !important; }
.mx-tab.is-pending::after { transform: none; }
@media (prefers-reduced-motion: no-preference) {
  #view.mx-enter-tab .mx-tab-in { animation: mx-lift-in var(--t-reveal) var(--ease) backwards; }
  #view.mx-enter-tab .mx-tab-in ~ .mx-tab-in { animation-delay: 45ms; }
}

/* ---- every artboard hover (ui.js data-hover delegate writes inline colours) eases instead of snapping ---- */
[data-hover] { transition: color var(--t-quick) var(--ease), background-color var(--t-quick) var(--ease), border-color var(--t-quick) var(--ease), opacity var(--t-quick) var(--ease), transform var(--t-quick) var(--ease); }

/* ---- press: a filled or outlined BUTTON sinks one pixel while held (touch included). Button-shaped =
   it carries its own tracked uppercase label (letter-spacing in its style); list rows and whole cards
   with a hover background do not sink — cards have their own press below ---- */
:is(a, span, div):is([data-hover*="background"], [data-hover*="border-color"])[style*="letter-spacing"]:not(.mx-card-link):not(.mx-proj-card):active { transform: translateY(1px); }
a, [data-act], [data-nav], button { -webkit-tap-highlight-color: transparent; }

/* ---- trailing arrows: ui.js wraps a control's closing → / ↗ in .mx-arr and marks that control
   .mx-has-arr; hovering the control leans its arrow forward ---- */
.mx-arr { display: inline-block; font-style: normal; line-height: 1; transition: transform var(--t-quick) var(--ease); }
@media (prefers-reduced-motion: no-preference) {   /* a keyboard focus leans the arrow too (the admin portal's rule) */
  .mx-has-arr:focus-visible .mx-arr { transform: translateX(3px); }
  .mx-has-arr:focus-visible .mx-arr.ne { transform: translate(2px, -2px); }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .mx-has-arr:hover .mx-arr { transform: translateX(3px); }
  .mx-has-arr:hover .mx-arr.ne { transform: translate(2px, -2px); }
}

/* ---- running-text links (text only — no inline style, no class, no child elements): a hairline
   underline fades in on hover ---- */
:is(#view, .mx-modal-body) a:not([style]):not([class]):not(:has(*)) {
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: transparent;
  transition: color var(--t-quick) var(--ease), text-decoration-color var(--t-quick) var(--ease);
}
@media (hover: hover) { :is(#view, .mx-modal-body) a:not([style]):not([class]):not(:has(*)):hover { text-decoration-color: currentColor; } }

/* ---- breadcrumbs: a hairline underline fades in under the hovered step ---- */
.mx-crumbs :is(a, [data-nav]) { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: transparent;
  transition: color var(--t-quick) var(--ease), text-decoration-color var(--t-quick) var(--ease); }
@media (hover: hover) { .mx-crumbs :is(a, [data-nav]):hover { text-decoration-color: rgba(25,21,18,.45); } }

/* ---- section tabs (.mx-tab inside [data-tabs]): the underline is a drawn rule, not a border — the active
   one draws in from the centre on arrival (or slides over from the tab you left: router.js sets
   --tab-dx / --tab-sx and .is-sliding); under the pointer an inactive tab draws a crimson hairline in
   from the left (the admin nav, sub-tabs and Inbox tabs do the same) ---- */
/* the strip keeps its drawn height (the old active tab carried 5px of border + padding) */
.mx-tabs[data-tabs] { min-height: 44px; box-sizing: border-box; }
.mx-tab { position: relative; }
.mx-tab::after { content: ""; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px; background: #9b1b22;
  transform: scaleX(0); transform-origin: 50% 50%; transition: transform var(--t-quick) var(--ease); pointer-events: none; }
.mx-tab.is-on::after { transform: none; }
.mx-tab:not(.is-on)::after { height: 1px; opacity: .45; transform-origin: 0 50%; }
@media (hover: hover) { .mx-tab:not(.is-on):hover::after { transform: none; } }
/* phones and touch iPads draw the strip as 44px tap rows with no vertical padding (the tap layer above),
   so the rule sits on the tab's own bottom edge; it must come after the base rule to win */
@media (max-width: 600px), (pointer: coarse) { .mx-tab::after { bottom: 0; } }
@keyframes mx-draw { from { transform: scaleX(0); } to { transform: none; } }
@keyframes mx-tab-slide { from { transform: translateX(var(--tab-dx, 0)) scaleX(var(--tab-sx, 1)); } to { transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  #view:is(.mx-enter, .mx-enter-tab) .mx-tab.is-on:not(.is-sliding)::after { animation: mx-draw var(--t-reveal) var(--ease) backwards; animation-delay: 60ms; }
  .mx-tab.is-on.is-sliding::after { transform-origin: 0 50%; animation: mx-tab-slide var(--t-reveal) var(--ease) backwards; }
}
@media (max-width: 600px) {
  /* a strip that scrolls sideways fades at its edges, so a clipped tab reads as "more this way", not cut off
     (the right fade is long enough to read as a fade, not as a label cut mid-word) */
  .mx-tabs[data-tabs] {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 48px), transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 48px), transparent 100%);
  }
}

/* ---- clickable cards lift 2px on --shadow-lift (the same lift in both portals and the event app); their photo drifts (the Home project cards set the pattern). One
   transition list for everything a card may change — it replaces the [data-hover] list on the same
   element, so the hover background and colour must be in it too, or they snap ---- */
.mx-proj-card, .mx-card-link { transition: transform var(--t-quick) var(--ease), box-shadow var(--t-quick) var(--ease), border-color var(--t-quick) var(--ease),
  background-color var(--t-quick) var(--ease), color var(--t-quick) var(--ease), opacity var(--t-quick) var(--ease); }
.mx-ph { display: block; overflow: hidden; }
.mx-proj-card img, .mx-ph img, .mx-ph .mx-mono { transition: transform var(--t-drift) var(--ease), opacity var(--t-reveal) var(--ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .mx-proj-card:hover, .mx-card-link:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
  .mx-proj-card:hover img, .mx-ph:hover img, .mx-card-link:hover .mx-ph img, .mx-ph:hover .mx-mono, .mx-card-link:hover .mx-ph .mx-mono { transform: scale(1.045); }
  /* pressed, a lifted card settles most of the way back — the same gesture on every card */
  .mx-proj-card:active, .mx-card-link:active, .mx-proj-card.is-pressed, .mx-card-link.is-pressed { transform: translateY(-1px); box-shadow: 0 10px 22px -18px rgba(25,21,18,.5); }
}
/* touch: no hover, so a card answers the press itself */
@media (hover: none) { .mx-proj-card:active, .mx-card-link:active, .mx-proj-card.is-pressed, .mx-card-link.is-pressed { opacity: .86; } }
/* a card link keeps its own ink (never the crimson of a bare link, never the global link hover) */
a.mx-proj-card.dark { color: #f7f1e6; }
a.mx-card-link { color: #191512; }
@media (hover: hover) { a.mx-proj-card:hover, a.mx-card-link:hover { color: #191512; } a.mx-proj-card.dark:hover { color: #f7f1e6; } }

/* ---- sections below the first screen rise in as they scroll into view (ui.revealOnScroll — views opt in
   with `reveal: true`). Marked by script only, so without it nothing is hidden; print shows everything
   (.mx-rv, not .mx-sr: in the admin portal .mx-sr is screen-reader-only text — one name, two meanings) ---- */
@media (prefers-reduced-motion: no-preference) {
  .mx-rv { opacity: 0; transform: translateY(14px); }
  .mx-rv-in { transition: opacity var(--t-reveal) var(--ease) var(--rv-d, 0ms), transform var(--t-reveal) var(--ease) var(--rv-d, 0ms); }
}
/* blocks arriving together follow each other in (ui.js sets the class — never the block's inline style) */
.mx-rv-d1 { --rv-d: 60ms; } .mx-rv-d2 { --rv-d: 120ms; } .mx-rv-d3 { --rv-d: 180ms; }
@media print { .mx-rv { opacity: 1 !important; transform: none !important; } }

/* ---- disclosure panels (FAQ answer, host detail): the opened panel fades down into place ---- */
@media (prefers-reduced-motion: no-preference) { .mx-reveal { animation: mx-drop var(--t-reveal) var(--ease) backwards; } }

/* ---- images arrive with a short fade instead of painting in rows. ui.js marks only view / sheet images
   still loading a frame after they were drawn (never the chrome's logo, never a photo hero) and clears
   the mark on load or error — an image is never left hidden ---- */
img.mx-img-wait { opacity: 0; }
/* a photo fades in once decoded, on the enter spring (ui.js › fadeImages runs it as an animation of its own, .1 to .9 in
   about 300 ms, §4.1b), so a card's own transition list (its drift) never cancels it. mx-img-wait holds it until then */

/* ---- follow switches (.mx-switch, role=switch): the state lives in aria-checked, so the views flip it in
   place the moment it is pressed (ui.setSwitch) and the track and knob ease across together; the
   save runs behind it and a failed save flips it back ---- */
.mx-switch { display: inline-block; position: relative; width: 34px; height: 18px; flex: none; cursor: pointer; background-color: rgba(247,241,230,.3); border-radius: var(--r-xs);
  transition: background-color var(--t-quick) var(--ease), box-shadow var(--t-quick) var(--ease); }
.mx-switch > span { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; background: #f7f1e6; border-radius: calc(var(--r-xs) - 2px); transition: transform var(--t-quick) var(--ease); }
.mx-switch[aria-checked="true"] { background-color: #9b1b22; }
.mx-switch[aria-checked="true"] > span { transform: translateX(16px); }
.mx-switch[aria-busy="true"] { cursor: progress; }
@media (hover: hover) {
  .mx-switch[aria-checked="false"]:hover { background-color: rgba(247,241,230,.42); }
  .mx-switch[aria-checked="true"]:hover { background-color: #7e151b; }
}
/* legacy: a switch re-drawn in its new state (ui.flipSwitch) slides its knob over from the old side */
@keyframes mx-knob { from { transform: translateX(var(--knob-from, 0)); } to { transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  [role="switch"]:not(.mx-switch).mx-sw-flip > span { animation: mx-knob var(--t-quick) var(--ease) backwards; }
  [role="switch"][aria-checked="true"].mx-sw-flip > span { --knob-from: -16px; }
  [role="switch"][aria-checked="false"].mx-sw-flip > span { --knob-from: 16px; }
}

/* ---- chrome: the top bar answers the pointer ---- */
.mx-topbar [data-act="tg"] > span:first-child > span:last-child { transform-origin: 0 50%; transition: transform var(--t-quick) var(--ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .mx-topbar [data-act="tg"]:hover > span:first-child > span:last-child { transform: scaleX(1.5); }
}
.mx-avatar { transition: box-shadow var(--t-quick) var(--ease); }
@media (hover: hover) { a:hover > .mx-avatar { box-shadow: 0 0 0 2px #f7f1e6, 0 0 0 3px #c9a962; } }
/* phone bar + tab bar: touch feedback while pressed (no hover on touch) */
#mx-mobile-top [data-act], #mx-mobile-top a { transition: opacity var(--t-quick) var(--ease); }
#mx-mobile-top .mx-mt-back { transition: transform 120ms var(--ease), color var(--t-quick) var(--ease); }
#mx-mobile-top [data-act]:active, #mx-mobile-top a:active { opacity: .55; }
/* r4 (the r3 perf verifier: the bar's Med&X home link and Search took .is-pressed with no look): the .is-pressed twins of the
   bar's :active rules (js/ui.js installPress, the pointerdown's task) */
#mx-mobile-top [data-act].is-pressed, #mx-mobile-top a.is-pressed { opacity: .55; }
/* tab bar: see LIQUID GLASS › the floating tab bar (a pressed item gives a little, the bar never moves) */

/* countdown digits: ui.tick() fades a changed number up into place (Web Animations; skipped for reduced motion).
   Tabular figures, so a changing digit never nudges the units beside it */
[data-cd] { font-variant-numeric: tabular-nums; }

/* ---- reduced motion: nothing travels, fades or zooms (1 ms keeps animationend/transitionend firing) ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-delay: 0ms !important; animation-iteration-count: 1 !important;
    transition-duration: 1ms !important; transition-delay: 0ms !important; scroll-behavior: auto !important; }
}
/* …except inside the drawer. It opens by switching visibility, and the rule above gave the drawer and every
   box in it (their transition-property defaults to all) a 1 ms transition that carried the inherited
   visibility too: its first link was still hidden at the instant chrome.openDrawer focused it, so keyboard
   focus stayed on MENU. With reduced motion the drawer simply appears and goes. */
@media (prefers-reduced-motion: reduce) { #mx-drawer, #mx-drawer * { transition: none !important; } }

/* home › 01 OUR PROJECTS: the cards of one row share their row tracks (subgrid), so a status or a title that
   wraps (APPLICATIONS OPEN 15 NOVEMBER, Plexus Conference 2026) moves the same line in every card of that row
   at every width, three across on a tablet or five across on a laptop. Each card spans five tracks (photo,
   status, title, detail, CTA); its body box steps aside (display: contents) and its 16px padding and 8px
   rhythm move onto the lines. Without subgrid the cards keep their own flex column. */
@supports (grid-template-rows: subgrid) {
  .mx-grid-5 > .mx-proj-card { display: grid !important; grid-row: span 5; grid-template-rows: subgrid; row-gap: 8px; }
  .mx-proj-card > div { display: contents !important; }
  .mx-proj-card > div > * { margin: 0 16px; min-width: 0; }
  .mx-proj-card > div > .mx-proj-status { margin-top: 8px; }
  .mx-proj-card > div > .mx-proj-cta { align-self: end; margin-bottom: 16px; }
}
/* five across between 901 and 1439 px a long CTA (RESERVE A SEAT · €150 →) wraps inside its card instead of
   running out through the border */
@media (min-width: 901px) and (max-width: 1439px) {
  .mx-proj-card .mx-proj-cta { white-space: normal !important; text-wrap: balance; }
}

/* /app/projects: a phone keeps the artboard's row (name left, CTA right); side by side on a wider screen each
   card stacks it like Home's cards, the CTA on the card's foot */
@media (min-width: 561px) {
  .mx-projx-body { flex-direction: column; align-items: flex-start !important; gap: 10px !important; }
  .mx-projx-body > span:first-child { flex: none !important; }
  .mx-projx-body > span:last-child { margin-top: auto; }
}

/* home › newsletter: the topic chips get their own line (they used to wrap one chip onto a second row
   between the text and the e-mail field); on phones everything stacks as before */
@media (min-width: 901px) {
  .mx-nl .mx-nl-sub { flex: 1 1 auto !important; }
  .mx-nl .mx-nl-chips { order: 10; flex: 1 1 100% !important; }
}

/* FROM THE FORUM strip on a phone: label + time on the first line, the post title gets its own full line */
@media (max-width: 500px) {
  .mx-fstrip { flex-wrap: wrap !important; row-gap: 6px !important; }
  .mx-fstrip-div { display: none !important; }
  .mx-fstrip-title { flex: 1 1 100% !important; order: 3; }
  .mx-fstrip-title > span:last-child { white-space: normal !important; }
}

/* ============================================================================
   PHONE CALM KIT (DESIGN-RULES.md §10 · 2026-09-25) — the shared components every screen composes from.
   One idea per block, facts in rows, people in circles, one filled button per screen height. Phone first
   (≤500 px), and every class also holds at 1280 px (facts 640 wide, timeline 720, shelves become grids).
   Views override only inside their own [data-screen-label] scope. Catalogue: DESIGN-RULES.md §14.
   ========================================================================== */

/* ---- type scale (ROUND3-RULES §3): the display face only from 22 px up, each step with its weight and tracking tokens
   (a D2 pick lands in tokens.css). Text under 22 px set in the display classes (title3 rows and names) is the UI face,
   upright, 600, with the title3 tracking. Every figure that changes or carries money is the UI face, tabular, and from
   20 px up --fw-num at --ls-num ---- */
.t-display { font: var(--fw-display) var(--fs-display)/38px var(--font-display); letter-spacing: var(--ls-display); }
.t-title1 { font: var(--fw-title1) var(--fs-title1)/36px var(--font-display); letter-spacing: var(--ls-title1); }
.t-title2 { font: var(--fw-title2) var(--fs-title2)/28px var(--font-display); letter-spacing: var(--ls-title2); }
.t-title3 { font: 600 var(--fs-title3)/24px var(--font-ui); letter-spacing: var(--ls-title3); }
.t-body { font: 400 var(--fs-body)/24px var(--font-ui); }
.t-2nd { font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); }
.t-label { font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; }
.t-num { font: var(--fw-num) var(--fs-num)/1 var(--font-ui); letter-spacing: var(--ls-num); font-variant-numeric: tabular-nums lining-nums; }
.mx-ic { display: block; flex: none; }

/* ---- page wrapper, large title, lede, sections ---- */
.mx-p { --g: var(--gutter-p); padding: 0 var(--g) 56px; box-sizing: border-box; width: 100%; min-width: 0; }
@media (min-width: 501px) { .mx-p { --g: 36px; } }
@media (min-width: 901px) { .mx-p { max-width: 1180px; margin: 0 auto; padding-bottom: 88px; } }
.mx-sec { margin-top: var(--sp-48); min-width: 0; }
.mx-sec--tight { margin-top: var(--sp-32); }
.mx-lt { font: var(--fw-title1) var(--fs-title1)/36px var(--font-display); letter-spacing: var(--ls-title1); color: var(--ink); margin: 20px 0 0; text-wrap: balance; }
.mx-lt i, .mx-hero-title i, .t-display i, .t-title1 i, .t-title2 i { font-style: italic; }
.mx-lede { font: 400 var(--fs-body)/24px var(--font-ui); color: var(--soft); margin: 6px 0 0; max-width: 560px; }
@media (min-width: 901px) { .mx-lt { font-size: 42px; line-height: 48px; margin-top: 44px; } .mx-lede { font-size: 17px; line-height: 26px; } }

/* ---- section head: 01 + TITLE + optional right link, one line that never wraps ---- */
.mx-sh { display: flex; align-items: center; gap: 12px; min-width: 0; margin: 0 0 var(--sp-16); }
/* Glass Quiet Q2: section heads carry no numerals (the 01 · 02 … counted as words and carried nothing). A view that still
   writes .mx-sh-n draws nothing there; .mx-p--num numbers nothing */
.mx-sh-n { display: none !important; }
.mx-sh-t { flex: 1 1 auto; min-width: 0; margin: 0; font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-sh-a { flex: none; margin: -12px 0 -12px auto; padding: 0 0 0 8px; min-height: 44px; min-width: 44px; box-sizing: border-box; justify-content: flex-end; display: inline-flex; align-items: center; gap: 4px;
  font: 500 var(--fs-2nd)/20px var(--font-ui); color: var(--crimson); white-space: nowrap; text-decoration: none; cursor: pointer; }
.mx-sh-sub { margin: -8px 0 var(--sp-16); font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); }
.mx-sh select, .mx-sh .mx-sh-ctl { flex: none; margin-left: auto; font: 500 var(--fs-2nd) var(--font-ui); min-height: 36px; border: 1px solid var(--hair); border-radius: var(--r-sm); background-color: transparent; padding: 0 12px; color: var(--ink); }

/* ---- facts list: icon · value · sub-line · optional trailing link or switch ---- */
.mx-facts { list-style: none; margin: 0; padding: 0; max-width: 640px; }
.mx-fact { display: flex; align-items: center; gap: 14px; min-height: 56px; padding: 12px 0; box-sizing: border-box; border-top: 1px solid var(--hair-soft); color: var(--ink); text-decoration: none; }
.mx-fact:last-child { border-bottom: 1px solid var(--hair-soft); }
.mx-fact > .mx-ic { align-self: flex-start; margin-top: 2px; color: var(--gold-dark); }
.mx-fact-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mx-fact-v { font: 400 var(--fs-body)/24px var(--font-ui); color: var(--ink); }
.mx-fact-s { font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); }
.mx-fact-go { flex: none; min-height: 44px; min-width: 44px; box-sizing: border-box; justify-content: flex-end; margin: -10px 0; padding-left: 8px; display: inline-flex; align-items: center; gap: 4px;
  font: 500 var(--fs-2nd)/20px var(--font-ui); color: var(--crimson); white-space: nowrap; text-decoration: none; cursor: pointer; }
a.mx-fact, .mx-fact[data-act] { cursor: pointer; transition: background-color var(--t-quick) var(--ease); }
@media (hover: hover) { a.mx-fact:hover, .mx-fact[data-act]:hover { background: var(--row-hover); color: var(--ink); } }

/* ---- checklist rows ---- */
.mx-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; max-width: 640px; }
.mx-checks > li { display: flex; gap: 12px; align-items: flex-start; font: 400 var(--fs-body)/24px var(--font-ui); color: var(--ink); }
.mx-checks > li > .mx-ic { margin-top: 2px; color: var(--gold-dark); }

/* ---- timeline rows (agendas, key dates): 56px time column · title · one sub-line ---- */
.mx-timeline { list-style: none; margin: 0; padding: 0; max-width: 720px; }
.mx-tl-row { display: grid; grid-template-columns: 56px minmax(0, 1fr); column-gap: 12px; align-items: baseline; padding: 14px 0; border-top: 1px solid var(--hair-soft);
  color: var(--ink); text-decoration: none; box-sizing: border-box; }
.mx-tl-row:last-child { border-bottom: 1px solid var(--hair-soft); }
.mx-timeline--wide .mx-tl-row { grid-template-columns: 72px minmax(0, 1fr); }
a.mx-tl-row, .mx-tl-row[data-act] { grid-template-columns: 56px minmax(0, 1fr) 20px; cursor: pointer; transition: background-color var(--t-quick) var(--ease); }
.mx-timeline--wide a.mx-tl-row, .mx-timeline--wide .mx-tl-row[data-act] { grid-template-columns: 72px minmax(0, 1fr) 20px; }
a.mx-tl-row > .mx-ic, .mx-tl-row[data-act] > .mx-ic { align-self: center; color: rgba(25,21,18,.32); }
@media (hover: hover) { a.mx-tl-row:hover, .mx-tl-row[data-act]:hover { background: var(--row-hover); color: var(--ink); } }
.mx-tl-time { font: 500 var(--fs-2nd)/24px var(--font-ui); color: var(--crimson); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mx-tl-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mx-tl-title { font: 600 var(--fs-title3)/24px var(--font-ui); letter-spacing: var(--ls-title3); color: var(--ink); }
.mx-tl-sub { font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); }
.mx-tl-row.is-gold { padding-left: 12px; margin-left: -12px; border-radius: var(--r-xs); box-shadow: inset 2px 0 0 var(--gold); background: linear-gradient(90deg, rgba(201,169,98,.14), rgba(201,169,98,0) 75%); }
.mx-tl-row.is-gold .mx-tl-time { color: var(--gold-dark); }

/* ---- stat tiles: a numeral over a 12 caps label (2 across, --3 for three). The numeral is a figure: the UI face,
   tabular, --fw-num and --ls-num from 20 px up (ROUND3-RULES §3.1) ---- */
.mx-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.mx-tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 701px) { .mx-tiles, .mx-tiles--3 { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; } }
@media (min-width: 701px) and (max-width: 1000px) { .mx-tiles:not(.mx-tiles--3) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.mx-tile { display: flex; flex-direction: column; justify-content: space-between; gap: 10px; padding: 16px; min-width: 0; min-height: 96px; box-sizing: border-box;
  background: var(--card); border: 1px solid var(--hair-soft); border-radius: var(--r-lg); color: var(--ink); text-decoration: none; }
.mx-tile-n { font: var(--fw-num) var(--fs-num)/1 var(--font-ui); font-variant-numeric: tabular-nums lining-nums; color: var(--ink); white-space: nowrap; letter-spacing: var(--ls-num); }
.mx-tile-l { font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--soft); }
.mx-tiles--3 .mx-tile { padding: 14px 12px; }
.mx-tiles--3 .mx-tile-n { font-size: 34px; }
.mx-tiles--3 .mx-tile-l { font: 500 var(--fs-2nd)/18px var(--font-ui); letter-spacing: 0; text-transform: none; }
.mx-tiles--ink .mx-tile { background: rgba(247,241,230,.04); border-color: var(--hair-ink-soft); color: var(--cream); }
.mx-tiles--ink .mx-tile-n { color: var(--cream); }
.mx-tiles--ink .mx-tile-l { color: var(--gold); }
a.mx-tile { cursor: pointer; transition: border-color var(--t-quick) var(--ease), background-color var(--t-quick) var(--ease); }
@media (hover: hover) { a.mx-tile:hover { border-color: var(--ink); color: var(--ink); } }

/* ---- people: the circle (ui.portrait), the card (96) and the row (64 / 44) ---- */
.mx-pic { position: relative; display: inline-block; flex: none; overflow: hidden; border-radius: 50%; vertical-align: middle; isolation: isolate;
  background: radial-gradient(120% 95% at 30% 18%, #3a2f27 0%, #241d18 48%, #191512 100%); }
.mx-pic-32 { width: 32px; height: 32px; } .mx-pic-44 { width: 44px; height: 44px; } .mx-pic-64 { width: 64px; height: 64px; } .mx-pic-96 { width: 96px; height: 96px; }
.mx-pic-i { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--gold); font-family: var(--font-display);
  font-weight: var(--fw-title1); letter-spacing: .03em; line-height: 1; user-select: none; }
.mx-pic-32 .mx-pic-i { font-size: 12px; } .mx-pic-44 .mx-pic-i { font-size: 17px; } .mx-pic-64 .mx-pic-i { font-size: 24px; } .mx-pic-96 .mx-pic-i { font-size: 36px; }
/* initials under 22 px (the 32 and 44 circles) are the UI face (ROUND3-RULES §3.1), the 64 and 96 keep the display face */
.mx-pic-32 .mx-pic-i, .mx-pic-44 .mx-pic-i { font-family: var(--font-ui); font-weight: 600; }
.mx-pic > img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; display: block; object-fit: cover; object-position: 50% 22%; border-radius: 50%; }
.mx-pic::after { content: ""; position: absolute; inset: 0; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--pic-ring); pointer-events: none; z-index: 1; }
.mx-pic.is-ring::after { box-shadow: inset 0 0 0 1px var(--gold); }
.mx-person { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 2px; min-width: 0; color: var(--ink); text-decoration: none; background: none; border: 0; padding: 0; font: inherit; }
.mx-person > .mx-pic { margin-bottom: 12px; }
a.mx-person, button.mx-person, .mx-person[data-act] { cursor: pointer; }
.mx-person-name { font: 600 var(--fs-title3)/24px var(--font-ui); letter-spacing: var(--ls-title3); color: var(--ink); overflow-wrap: anywhere; }
.mx-person-role { font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mx-person-tag { font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--gold-dark); margin-top: 2px; }
.mx-person-row { display: flex; align-items: center; gap: 14px; min-height: 64px; padding: 8px 0; box-sizing: border-box; border-top: 1px solid var(--hair-soft);
  color: var(--ink); text-decoration: none; text-align: left; width: 100%; background: none; font: inherit; }
.mx-person-row:last-child { border-bottom: 1px solid var(--hair-soft); }
.mx-person-rows { max-width: 720px; }
.mx-person-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* a row's name may take two lines (a long name on a 320 phone read "Ellen …"), its role two (the institution is the
   point of the line); the reason tag stays one line */
.mx-person-row .mx-person-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: normal; }
.mx-person-row .mx-person-role { -webkit-line-clamp: 2; }
.mx-person-row .mx-person-tag { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 400px) { .mx-person-row { gap: 12px; } .mx-person-row .mx-person-tag { letter-spacing: .08em; } }
@media (max-width: 340px) { .mx-person-row { gap: 10px; } .mx-person-row .mx-person-tag { letter-spacing: .03em; } }
.mx-person-row > .mx-ic { color: rgba(25,21,18,.32); }
.mx-person-act { flex: none; display: flex; align-items: center; gap: 8px; }
a.mx-person-row, .mx-person-row[data-act] { cursor: pointer; transition: background-color var(--t-quick) var(--ease); }
@media (hover: hover) { a.mx-person-row:hover, .mx-person-row[data-act]:hover { background: var(--row-hover); color: var(--ink); } }

/* ---- 2-column grid · horizontal shelf ---- */
.mx-grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 12px; }
.mx-grid2 > * { min-width: 0; }
@media (min-width: 701px) { .mx-grid2 { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 36px 24px; } }
.mx-shelf { display: grid; grid-auto-flow: column; grid-auto-columns: var(--w, 240px); gap: 12px; overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-padding: 0 var(--g, var(--gutter-p)); padding: 0 var(--g, var(--gutter-p)) 4px; margin: 0 calc(-1 * var(--g, var(--gutter-p)));
  scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.mx-shelf::-webkit-scrollbar { display: none; }
.mx-shelf > * { scroll-snap-align: start; min-width: 0; }
@media (min-width: 901px) {
  .mx-shelf { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(auto-fill, minmax(var(--w, 240px), 1fr)); overflow: visible; margin: 0; padding: 0; gap: 24px; }
}
.mx-shelf-item { display: flex; flex-direction: column; gap: 10px; color: var(--ink); text-decoration: none; min-width: 0; }
.mx-shelf-title { font: 600 var(--fs-title3)/24px var(--font-ui); letter-spacing: var(--ls-title3); color: var(--ink); }
.mx-shelf-sub { font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); margin-top: -6px; }

/* ---- media at fixed ratios (object-fit: cover, object-position set per photo when the subject is off-centre). A photo on
   the page is a photo card at --r-lg (ROUND3-RULES §2, A15). It is its own clip: overflow, isolation and the WebKit mask
   keep its corners round while the image inside settles or drifts. The mask also clips an outside focus ring, so a
   focusable photo draws its ring inside. Inside a card (.mx-pcard, .mx-next) it takes the card's corners minus the
   card's 1 px hairline, so the card itself needs no clip and keeps its lift shadow ---- */
.mx-media { position: relative; display: block; overflow: hidden; background: var(--ink); width: 100%;
  border-radius: var(--r-lg); isolation: isolate; -webkit-mask-image: -webkit-radial-gradient(white, black); }
.mx-media:focus-visible { outline-offset: -3px; }
/* r4 (the r3 perf verifier: Home's photo link never took the pressed state): the Today card's photo link, a hero over most of
   the screen, presses with a light dim of its photo (js/ui.js PRESS_BIG lets it press despite its size), in 100 ms, and comes
   back on the quick ease when the finger lifts or the press is cancelled */
.mx-today-media { transition: opacity var(--t-quick) var(--ease); }
.mx-today-media.is-pressed { opacity: .86; transition-duration: var(--t-press); }
.mx-media.r-16x9 { aspect-ratio: 16 / 9; } .mx-media.r-4x3 { aspect-ratio: 4 / 3; } .mx-media.r-1x1 { aspect-ratio: 1 / 1; } .mx-media.r-4x5 { aspect-ratio: 4 / 5; }
.mx-media > img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; display: block; object-fit: cover; }
.mx-media > img.mx-media-mark { inset: auto; left: 50%; top: 50%; width: 32px; height: 32px; transform: translate(-50%, -50%); object-fit: contain; opacity: .9; }
.mx-media-cap { font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--soft); margin-top: 8px; }

/* ---- hero: eyebrow · title · one date line · ONE action, over a 4:5 photo on the scrim (or ink / cream) ---- */
.mx-hero { position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-end; width: 100%; box-sizing: border-box;
  aspect-ratio: 4 / 5; max-height: 480px; min-height: 380px; background: var(--ink); color: var(--cream); }
@media (min-width: 701px) { .mx-hero { aspect-ratio: auto; height: 540px; max-height: none; } }
.mx-hero > .mx-hero-photo { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; display: block; }
.mx-scrim { position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(25,21,18,.15) 0%, rgba(25,21,18,.35) 45%, rgba(25,21,18,.88) 100%); }
.mx-hero-body { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: flex-start; padding: 28px var(--gutter-p) 28px; max-width: 820px; box-sizing: border-box; }
@media (min-width: 501px) { .mx-hero-body { padding: 40px 36px 44px; } }
/* wide screens: the hero copy and the countdown line up with the centred .mx-p column below them */
@media (min-width: 901px) {
  .mx-hero-body { padding-left: max(36px, calc((100vw - 1180px) / 2 + 36px)); max-width: none; width: 100%; }
  .mx-hero-body > * { max-width: 760px; }
  .mx-countdown { padding-left: max(36px, calc((100vw - 1180px) / 2 + 36px)); padding-right: max(36px, calc((100vw - 1180px) / 2 + 36px)); }
}
.mx-hero-eyebrow { font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--gold); }
/* over a photo the copy gets its own band of the scrim: it starts 96px above the eyebrow and is .78 ink by the
   eyebrow's line, so the 12px gold label keeps 4.5:1 even over white chairs or a bright slide; the top of the
   photo stays as light as before. The eyebrow takes the lighter gold on a photo. */
.mx-hero:not(.mx-hero--ink):not(.mx-hero--cream) > .mx-hero-body::before { content: ""; position: absolute; z-index: -1; left: 0; right: 0; bottom: 0; top: -96px; pointer-events: none;
  background: linear-gradient(180deg, rgba(25,21,18,0) 0, rgba(25,21,18,.78) 104px, rgba(25,21,18,.86) 100%); }
.mx-hero:not(.mx-hero--ink):not(.mx-hero--cream) .mx-hero-eyebrow { color: var(--gold-hover); }
.mx-hero-title { margin: 10px 0 0; font: var(--fw-display) var(--fs-display)/38px var(--font-display); letter-spacing: var(--ls-display); color: var(--cream); text-wrap: balance; }
@media (min-width: 901px) { .mx-hero-title { font-size: 58px; line-height: 62px; } }
.mx-hero-date { margin: 10px 0 0; font: 400 var(--fs-body)/24px var(--font-ui); color: rgba(247,241,230,.88); }
.mx-hero-cta { margin-top: 22px; width: 100%; display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
.mx-hero-cta > * { box-sizing: border-box; }
@media (max-width: 500px) { .mx-hero-cta > * { width: 100%; min-height: 48px; display: flex !important; align-items: center; justify-content: center; text-align: center; } }
@media (min-width: 501px) { .mx-hero-cta { width: auto; flex-direction: row; align-items: center; } }
.mx-hero--ink, .mx-hero--cream { aspect-ratio: auto; min-height: 0; height: auto; max-height: none; }
.mx-hero--ink .mx-hero-body, .mx-hero--cream .mx-hero-body { padding-top: 36px; }
.mx-hero--cream { background: var(--cream); color: var(--ink); }
.mx-hero--cream .mx-hero-eyebrow { color: var(--crimson); }
.mx-hero--cream .mx-hero-title { color: var(--ink); }
.mx-hero--cream .mx-hero-date { color: var(--soft); }

/* ---- countdown band: label + days / hours / minutes, nothing else ---- */
.mx-countdown { display: flex; align-items: center; gap: 24px; padding: 16px var(--gutter-p); box-sizing: border-box; background: var(--ink); color: var(--cream);
  border-top: 1px solid var(--hair-ink-soft); }
@media (min-width: 501px) { .mx-countdown { padding: 18px 36px; } }
.mx-cd-label { margin-right: auto; font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--gold); white-space: nowrap; }
.mx-cd-cell { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.mx-cd-num { font: var(--fw-num) 38px/1 var(--font-ui); letter-spacing: var(--ls-num); font-variant-numeric: tabular-nums lining-nums; color: var(--cream); font-style: normal; }
.mx-cd-unit { font: 500 var(--fs-2nd)/20px var(--font-ui); letter-spacing: 0; text-transform: none; font-style: normal; color: rgba(247,241,230,.66); }
@media (max-width: 500px) {
  .mx-countdown { display: grid; grid-template-columns: repeat(3, max-content); justify-content: start; column-gap: 28px; row-gap: 6px; }
  .mx-cd-label { grid-column: 1 / -1; }
  .mx-cd-num { font-size: 36px; }
}
/* wide screens: the band's label and numbers start on the page column, as one group (the 501px padding above used to
   win over the column rule, so "Begins in" sat at the window edge and the numbers at the far right) */
@media (min-width: 901px) {
  .mx-countdown { padding-left: max(36px, calc((100vw - 1180px) / 2 + 36px)); padding-right: max(36px, calc((100vw - 1180px) / 2 + 36px)); }
  .mx-cd-label { margin-right: 12px; }
}
/* a countdown as one quiet line inside a card */
.mx-countdown--line { display: flex !important; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; padding: 0; background: none; border: 0; color: inherit; }
.mx-countdown--line .mx-cd-label { grid-column: auto; margin-right: 0; }
.mx-countdown--line .mx-cd-num { font-size: 24px; color: inherit; }
.mx-countdown--line .mx-cd-unit { color: currentColor; opacity: .62; }

/* ---- tags (printed labels on paper, --r-xs) and chips (a tag standing on a photo is a chip: the capsule, ROUND3-RULES §2) ---- */
.mx-tag { display: inline-flex; align-items: center; min-height: 26px; padding: 0 9px; box-sizing: border-box; white-space: nowrap; border-radius: var(--r-xs);
  font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .1em; text-transform: uppercase; }
:is(.mx-media, .mx-hero) > .mx-tag { border-radius: var(--r-capsule); }
.mx-tag--gold { background: var(--gold); color: var(--ink); }
.mx-tag--cream { background: var(--cream); color: var(--ink); }
.mx-tag--line { border: 1px solid rgba(247,241,230,.75); color: var(--cream); background: rgba(25,21,18,.5); }
.mx-tag--ink { background: var(--ink); color: var(--cream); }
.mx-tag--crimson { background: var(--crimson); color: var(--cream); }
.mx-tag--soft { border: 1px solid var(--hair); color: var(--soft); }

/* ---- accordion (<details>): anything longer than two lines ---- */
.mx-accs { max-width: 720px; border-top: 1px solid var(--hair-soft); }
.mx-acc { border-bottom: 1px solid var(--hair-soft); }
.mx-acc > summary { list-style: none; display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 12px 0; box-sizing: border-box; cursor: pointer;
  font: 500 var(--fs-body)/24px var(--font-ui); color: var(--ink); }
.mx-acc > summary::-webkit-details-marker { display: none; }
.mx-acc > summary::after { content: ""; flex: none; margin-left: auto; width: 8px; height: 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  opacity: .5; transform: translateY(-3px) rotate(45deg); transition: transform var(--t-quick) var(--ease); }
.mx-acc[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.mx-acc > summary > .mx-ic { color: var(--gold-dark); }
.mx-acc-a { padding: 0 0 18px; font: 400 var(--fs-body)/24px var(--font-ui); color: var(--soft); }
/* what a closed accordion holds is never drawn, but the engines keep a box for it (a probe reading the screen took it for a
   line on show that went in one frame as the fold opened and came back in one frame as it shut): closed, it is clear too,
   so the fold's fade in starts from what shows and its fade out ends there (ui.fold, ROUND3-RULES §4.1b) */
:is(details.mx-acc, details[data-fold]):not([open]) > :not(summary) { opacity: 0; }
.mx-acc-a > :first-child { margin-top: 0; } .mx-acc-a > :last-child { margin-bottom: 0; }
/* the answer fades in as the accordion grows (ui.fold, the ui spring on its height, §4.1b), no separate drop */

/* ---- grouped list rows (the Settings pattern): icon · label · value · chevron ---- */
/* a grouped list is one rounded box (--r-md, ROUND3-RULES §2) that clips its rows, so a highlighted first or last row keeps
   the list's corners. A row's keyboard ring is drawn inside for the same reason */
.mx-list { max-width: 720px; background: var(--card); border: 1px solid var(--hair-soft); border-radius: var(--r-md); overflow: hidden; }
.mx-list :is(.mx-row, a, button, [data-act]):focus-visible { outline-offset: -3px; }
.mx-list--plain { background: none; border: 0; border-top: 1px solid var(--hair-soft); border-bottom: 1px solid var(--hair-soft); border-radius: 0; overflow: visible; }
.mx-row { position: relative; display: flex; align-items: center; gap: 14px; width: 100%; min-height: 56px; padding: 10px 16px; box-sizing: border-box;
  color: var(--ink); text-decoration: none; text-align: left; background: none; border: 0; font: inherit; cursor: pointer; transition: background-color var(--t-quick) var(--ease); }
.mx-list--plain > .mx-row { padding-left: 0; padding-right: 0; }
.mx-row + .mx-row::before { content: ""; position: absolute; top: 0; left: 16px; right: 0; height: 1px; background: var(--hair-soft); }
.mx-list--plain > .mx-row + .mx-row::before { left: 0; }
.mx-row > .mx-ic:first-child { color: var(--gold-dark); }
.mx-row > .mx-ic:last-child:not(:first-child) { color: rgba(25,21,18,.32); }
.mx-row-l { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; font: 400 var(--fs-body)/22px var(--font-ui); color: inherit; }
.mx-row-s { font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); }
.mx-row-v { flex: 0 1 auto; min-width: 0; max-width: 55%; font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-row.is-danger { color: var(--crimson); }
.mx-row.is-danger > .mx-ic:first-child { color: var(--crimson); }
.mx-row .mx-switch { cursor: pointer; }
@media (hover: hover) { .mx-row:hover { background: var(--row-hover); color: var(--ink); } .mx-row.is-danger:hover { color: var(--crimson); } }
.mx-badge { flex: none; min-width: 20px; height: 20px; padding: 0 6px; box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
  background: var(--crimson); color: var(--cream); font: 600 var(--fs-label)/1 var(--font-ui); border-radius: var(--r-capsule); font-variant-numeric: tabular-nums; }

/* the follow switch in a light row: a visible off track, a thumb-sized knob */
.mx-fact .mx-switch, .mx-row .mx-switch { width: 44px; height: 26px; border-radius: var(--r-sm); }
.mx-fact .mx-switch > span, .mx-row .mx-switch > span { top: 3px; left: 3px; width: 20px; height: 20px; border-radius: calc(var(--r-sm) - 3px); }
.mx-fact .mx-switch[aria-checked="true"] > span, .mx-row .mx-switch[aria-checked="true"] > span { transform: translateX(18px); }
.mx-fact .mx-switch[aria-checked="false"], .mx-row .mx-switch[aria-checked="false"] { background-color: rgba(25,21,18,.2); }
@media (hover: hover) { .mx-fact .mx-switch[aria-checked="false"]:hover, .mx-row .mx-switch[aria-checked="false"]:hover { background-color: rgba(25,21,18,.3); } }

/* ---- segmented control (section switcher) ---- */
.mx-seg { display: flex; gap: 0; max-width: 100%; min-height: 44px; padding: 4px; box-sizing: border-box; border-radius: var(--r-capsule); border: 0;
  background: rgba(25,21,18,.06); box-shadow: inset 0 0 0 .5px rgba(25,21,18,.08); overflow-x: auto; scrollbar-width: none; }
.mx-seg::-webkit-scrollbar { display: none; }
.mx-seg > a, .mx-seg > span, .mx-seg > button { position: relative; isolation: isolate; flex: 1 0 auto; display: inline-flex; align-items: center; justify-content: center; min-height: 36px; padding: 0 16px;
  border-radius: var(--r-capsule); font: 500 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); white-space: nowrap; text-decoration: none; background: none; border: 0; cursor: pointer;
  transition: color var(--t-quick) var(--ease); }
/* the raised capsule behind the selected item is its own layer, so it can slide over from the item left (router.js › settleTabs) */
.mx-seg > .is-on, .mx-seg > [aria-current="page"] { color: var(--ink); font-weight: 600; background: none; }
.mx-seg > .is-on::before, .mx-seg > [aria-current="page"]::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: #fffdf8; box-shadow: 0 1px 3px rgba(25,21,18,.16), 0 0 0 .5px rgba(25,21,18,.04); transform-origin: 0 50%; }
/* a 44 px tap target for a 36 px capsule */
.mx-seg > a::after, .mx-seg > span[data-act]::after, .mx-seg > button::after { content: ""; position: absolute; left: 0; right: 0; top: -4px; bottom: -4px; }
@keyframes mx-seg-slide { from { transform: translateX(var(--seg-dx, 0)) scaleX(var(--seg-sx, 1)); } }
@media (prefers-reduced-motion: no-preference) {
  .mx-seg > .is-sliding::before { animation: mx-seg-slide 220ms var(--ease) backwards; }
}
/* small phones: the items share the row (four fit at 320 without a sideways scroll; ui.js keeps the active one in view) */
@media (max-width: 400px) { .mx-seg > a, .mx-seg > span, .mx-seg > button { flex: 1 1 auto; padding: 0 10px; } }
@media (max-width: 360px) { .mx-seg > a, .mx-seg > span, .mx-seg > button { padding: 0 7px; font-size: 13px; } }
@media (hover: hover) { .mx-seg > :not(.is-on):not([aria-current="page"]):hover { color: var(--ink); background: rgba(25,21,18,.04); } }

/* ---- icon button (44 × 44) ---- */
.mx-iconbtn { flex: none; width: 44px; height: 44px; padding: 0; display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; border-radius: var(--r-md);
  color: var(--ink); cursor: pointer; text-decoration: none; transition: background-color var(--t-quick) var(--ease), color var(--t-quick) var(--ease); }
.mx-iconbtn--fill { background: var(--crimson); color: var(--cream); }
@media (hover: hover) { .mx-iconbtn:hover { background: var(--row-hover); color: var(--ink); } .mx-iconbtn--fill:hover { background: var(--crimson-hover); color: var(--cream); } }

/* ---- feature card (project / event): 16:9 photo, status tag top-left, title on the photo, facts line + one line under it.
   The card's main link stretches over the whole card (.mx-pcard-main::after); a CTA with its own href sits above it ---- */
.mx-pcard { position: relative; display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--hair-soft); border-radius: var(--r-lg); color: var(--ink); min-width: 0;
  transition: transform var(--t-quick) var(--ease), box-shadow var(--t-quick) var(--ease), border-color var(--t-quick) var(--ease); }
.mx-pcard > .mx-media { border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0; }
.mx-pcard .mx-media > .mx-tag { position: absolute; top: 14px; left: 14px; z-index: 1; }
.mx-pcard-title { position: absolute; left: 16px; right: 16px; bottom: 14px; z-index: 1; margin: 0; font: var(--fw-title2) 24px/28px var(--font-display); letter-spacing: var(--ls-title2); color: var(--cream); text-wrap: balance; }
.mx-pcard-title i { font-style: italic; }
.mx-pcard-body { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px 16px; }
.mx-pcard-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--ink); }
.mx-pcard-meta .mx-ic { color: var(--gold-dark); }
.mx-pcard-meta > .mx-sep { width: 8px; }
.mx-pcard-price { margin-left: auto; font: 600 var(--fs-2nd)/20px var(--font-ui); font-variant-numeric: tabular-nums; color: var(--gold-dark); white-space: nowrap; }
.mx-pcard-line { margin: 0; font: 400 var(--fs-2nd)/20px var(--font-ui); color: var(--soft); }
.mx-pcard-main { color: inherit; text-decoration: none; }
.mx-pcard-main::after { content: ""; position: absolute; inset: 0; z-index: 1; }
/* the card's own link as a cover over the whole card (a title link inside the photo's positioned title only covered
   the 30px title line); the CTA with its own href sits above it */
.mx-pcard-cover { position: absolute; inset: 0; z-index: 1; }
.mx-pcard-cover::after { content: none; }
.mx-pcard-cta { position: relative; z-index: 2; align-self: flex-start; min-height: 44px; margin: -4px 0 -12px; display: inline-flex; align-items: center; gap: 6px;
  font: 600 var(--fs-btn)/16px var(--font-ui); letter-spacing: .1em; text-transform: uppercase; color: var(--crimson); text-decoration: none; }
.mx-pcard .mx-media > img { transition: transform var(--t-drift) var(--ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .mx-pcard:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
  .mx-pcard:hover .mx-media > img { transform: scale(1.04); }
}
@media (hover: none) { .mx-pcard:has(.mx-pcard-main:active), .mx-pcard:has(.mx-pcard-main.is-pressed) { opacity: .86; } }

/* ---- a quiet row card (one line into a place: "My Plexus ›", "Newsletter · choose topics ›") ---- */
.mx-linkcard { display: flex; align-items: center; gap: 14px; min-height: 64px; padding: 12px 16px; box-sizing: border-box; background: var(--card); border: 1px solid var(--hair-soft); border-radius: var(--r-lg);
  color: var(--ink); text-decoration: none; cursor: pointer; max-width: 720px; transition: border-color var(--t-quick) var(--ease), background-color var(--t-quick) var(--ease); }
.mx-linkcard > .mx-ic:first-child { color: var(--gold-dark); }
.mx-linkcard > .mx-ic:last-child { color: rgba(25,21,18,.32); }
@media (hover: hover) { .mx-linkcard:hover { border-color: var(--ink); color: var(--ink); } }

/* ---- the kit on ink (.mx-dark on the container) ---- */
.mx-dark { background: var(--ink); color: var(--cream); }
.mx-dark :is(.mx-sh-t, .mx-fact, .mx-fact-v, .mx-tl-row, .mx-tl-title, .mx-person-name, .mx-person, .mx-person-row, .mx-tile, .mx-tile-n, .mx-acc > summary, .mx-lt, .mx-checks > li, .mx-shelf-item, .mx-shelf-title) { color: var(--cream); }
.mx-dark :is(.mx-fact-s, .mx-tl-sub, .mx-person-role, .mx-acc-a, .mx-lede, .mx-sh-sub, .mx-shelf-sub, .mx-row-s, .mx-row-v) { color: rgba(247,241,230,.72); }
.mx-dark :is(.mx-fact, .mx-tl-row, .mx-acc, .mx-accs, .mx-person-row, .mx-tile) { border-color: var(--hair-ink-soft); }
.mx-dark :is(.mx-fact > .mx-ic, .mx-sh-n, .mx-tl-time, .mx-fact-go, .mx-sh-a, .mx-checks > li > .mx-ic, .mx-tile-l, .mx-person-tag, .mx-acc > summary > .mx-ic) { color: var(--gold); }
.mx-dark .mx-tile { background: rgba(247,241,230,.04); }
.mx-dark .mx-pic::after { box-shadow: inset 0 0 0 1px rgba(247,241,230,.14); }
.mx-dark .mx-pic.is-ring::after { box-shadow: inset 0 0 0 1px var(--gold); }
.mx-dark .mx-person-row > .mx-ic, .mx-dark a.mx-tl-row > .mx-ic { color: rgba(247,241,230,.4); }
@media (hover: hover) { .mx-dark :is(a.mx-fact, a.mx-tl-row, a.mx-person-row):hover { background: rgba(247,241,230,.05); color: var(--cream); } }

/* ---- sheets on phones: a sheet title in the calm scale, and the modal head/body at the floor or above ---- */
.mx-sheet-pic { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px; }

/* ---- phones: breadcrumbs go (the top bar's back arrow, the large title and the tab bar already say it) ---- */
@media (max-width: 500px) {
  body[data-layout="portal"] .mx-crumbs { display: none !important; }
}

/* the kit's own links carry 44px targets themselves: the invisible ::after hit layer (the 44px tap-target block above)
   excludes them by class, so a stretched card link keeps its own ::after and nothing gets position:relative behind its back */

/* ---- entrances: the kit's grids, shelves and hero copy cascade in like the artboard grids ---- */
@media (prefers-reduced-motion: no-preference) {
  #view.mx-enter :is(.mx-grid2, .mx-shelf, .mx-tiles) > * { animation: mx-lift-in var(--t-reveal) var(--ease) backwards; }
  #view.mx-enter :is(.mx-grid2, .mx-shelf, .mx-tiles) > :nth-child(2) { animation-delay: 35ms; }
  #view.mx-enter :is(.mx-grid2, .mx-shelf, .mx-tiles) > :nth-child(3) { animation-delay: 70ms; }
  #view.mx-enter :is(.mx-grid2, .mx-shelf, .mx-tiles) > :nth-child(n+4) { animation-delay: 105ms; }
  #view.mx-enter .mx-hero-body > * { animation: mx-lift-in var(--t-reveal) var(--ease) backwards; }
  #view.mx-enter .mx-hero-body > :nth-child(2) { animation-delay: 40ms; }
  #view.mx-enter .mx-hero-body > :nth-child(3) { animation-delay: 80ms; }
  #view.mx-enter .mx-hero-body > :nth-child(n+4) { animation-delay: 115ms; }
}
#view.mx-vt.mx-enter :is(.mx-grid2, .mx-shelf, .mx-tiles, .mx-hero-body) > * { animation: none; }

/* ============================================================================
   PHONE CALM CHROME (DESIGN-RULES §9 · 2026-09-25): the phone top bar, the email line, the tab bar, the
   SEARCH / ALERTS rows and the sheets. Ids and data-act hooks are unchanged (the iOS layer styles
   #mx-tabbar > a and #mx-mobile-top; medx-native.css adds its own safe-area padding on top of these).
   ========================================================================== */
/* the bar itself carries no background and no filter (a filter here would become the containing block of the fixed SEARCH
   sheet inside it and shrink its scrim to the bar's own box): its glass is a ::before layer (LIQUID GLASS › top bar) */
#mx-mobile-top.mx-mt { display: flex; align-items: center; gap: 0; position: relative; isolation: isolate; min-height: 56px; padding: 6px 8px 6px; box-sizing: border-box;
  background: transparent; border-bottom: 0; }
/* the vector wordmark (D6, map item 9): 28 px tall at rest, scaled from its left edge to 22 px folded on --bar-p, inside a
   44 px target. The colour on dark twin shows over dark glass. Until Alen sends the official master these are the reel's
   SVGs (assets/logo-color-on-light.svg and logo-color-on-dark.svg) */
.mx-mt-brand { position: relative; margin-left: 12px; display: flex; align-items: center; height: 44px; flex: none; }
.mx-mt-brand .mx-wm { display: block; width: auto; height: 28px; transform-origin: 0 50%; transform: scale(calc(1 - var(--bar-p, 0) * .2142857)); }
.mx-mt-brand .mx-wm--dark { position: absolute; left: 0; top: 8px; }
/* the two colourings cross-fade on the bar's tone, --bar-t (chrome.js): colour on light at 0, colour on dark at 1 */
.mx-mt-brand .mx-wm:not(.mx-wm--dark) { opacity: calc(1 - var(--bar-t, 0)); }
.mx-mt-brand .mx-wm--dark { opacity: var(--bar-t, 0); }
.mx-mt-fill { flex: 1 1 auto; }
.mx-mt-btn { flex: none; position: relative; width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; color: var(--ink); cursor: pointer; }
.mx-mt-back { color: var(--crimson); }
.mx-mt-title { flex: 1 1 auto; min-width: 0; text-align: center; font: 600 16px/22px var(--font-ui); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 8px; }
/* a root's small title: the page's large title folds into it from --bar-p .5 to 1 (the Apple Mail bar, D6). State, not
   motion, so Reduce Motion keeps it (ROUND3-RULES §5.3) */
.mx-mt-fold { opacity: clamp(0, calc((var(--bar-p, 0) - .5) * 2), 1); pointer-events: none; }
.mx-mt-spacer { cursor: default; }
.mx-mt-banner { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 0 12px 0 20px; box-sizing: border-box; background: var(--banner); border-bottom: 1px solid var(--hair-soft); }
.mx-mt-banner-t { flex: 1 1 auto; min-width: 0; font: 400 14px/20px var(--font-ui); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-mt-banner-a { flex: none; min-height: 44px; padding: 0 8px; display: inline-flex; align-items: center; font: 600 12px/16px var(--font-ui); letter-spacing: .12em; color: var(--crimson); cursor: pointer; }

/* #mx-tabbar: see LIQUID GLASS › the floating tab bar */

/* SEARCH / ALERTS rows at the calm scale: title 16, detail 14 (one line), date 12, close × a 44 target */
.mx-pop-head { min-height: 52px; box-sizing: border-box; padding-top: 4px !important; padding-bottom: 4px !important; padding-right: 6px !important; }
/* the popover's head reads like a sheet title (sentence case, Glass Quiet), its action a quiet crimson link */
.mx-pop-h { font: 600 17px/22px var(--font-ui); letter-spacing: 0; color: var(--ink); }
.mx-pop-a { font: 500 14px/20px var(--font-ui); letter-spacing: 0; color: var(--crimson); cursor: pointer; min-height: 44px; display: inline-flex; align-items: center; padding: 0 8px; }
.mx-pop-x { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; color: var(--soft); cursor: pointer; flex: none; border-radius: 50%; }
/* the title holds focus while ALERTS opens (chrome.js › focusAlertsTitle): read out, never ringed. A keyboard ring on the ×
   follows its circle */
.mx-pop-h:focus, .mx-pop-h:focus-visible { outline: none; }
.mx-pop-row { padding: 12px 20px !important; align-items: center !important; min-height: 56px; box-sizing: border-box; }
.mx-pop-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--crimson); align-self: flex-start; margin-top: 8px; }
.mx-pop-dot.is-read { background: transparent; box-shadow: inset 0 0 0 1px rgba(25,21,18,.25); }
.mx-pop-dot.is-gold { background: var(--gold); align-self: center; margin-top: 0; }
.mx-pop-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mx-pop-t { font: 600 16px/22px var(--font-ui); color: var(--ink); }
.mx-pop-t.is-serif { font: 600 17px/22px var(--font-ui); letter-spacing: var(--ls-title3); }
.mx-pop-s { font: 400 14px/20px var(--font-ui); color: var(--soft); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mx-pop-d { flex: none; align-self: flex-start; margin-top: 3px; font: 500 12px/16px var(--font-ui); color: var(--muted); white-space: nowrap; }
.mx-pop-go { flex: none; font: 500 14px/20px var(--font-ui); color: var(--crimson); white-space: nowrap; }
.mx-pop-chev { color: rgba(25,21,18,.3); }
.mx-pop-hint { padding: 16px 20px; font: 400 14px/20px var(--font-ui); color: var(--soft); }
.mx-pop-hint.is-error { color: var(--crimson); }

/* phones: a sheet rises from the bottom edge, full width, clear of the home indicator (the photo viewer keeps its
   centred frame). Same motion tokens as before: it settles up as the scrim fades in, and sinks as it leaves */
@media (max-width: 500px) {
  .mx-modal:not(.is-wide) { align-items: flex-end; padding: 0 8px calc(8px + env(safe-area-inset-bottom)); }
  .mx-modal:not(.is-wide) .mx-modal-sheet { width: 100%; max-width: 100%; border-radius: var(--r-xl);
    max-height: calc(100vh - 60px); max-height: calc(100dvh - 60px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); box-shadow: 0 -6px 40px rgba(25,21,18,.22); }
  /* the grabber: a 36 × 5 capsule centred 8px from the top */
  .mx-modal:not(.is-wide) .mx-modal-sheet::after { content: ""; position: absolute; z-index: 3; top: 8px; left: 50%; width: 36px; height: 5px; margin-left: -18px; border-radius: var(--r-capsule);
    background: rgba(25,21,18,.22); pointer-events: none; }
  .mx-modal-head { padding: 14px 10px 2px 20px; min-height: 62px; }
  .mx-modal-foot { padding: 4px 20px 20px; }
  .mx-modal-foot > * { flex: 1 1 0; min-height: 48px; display: inline-flex !important; align-items: center; justify-content: center; }
  .mx-modal-body { padding: 4px 20px 20px; }
}

/* ============================================================================
   HOME + PROJECTS (phone calm pass 2026-09-25) — CORE screens with no stylesheet of their own
   ========================================================================== */
a.mx-pcard { color: var(--ink); text-decoration: none; }
@media (hover: hover) { a.mx-pcard:hover { color: var(--ink); } }
@media (hover: none) { a.mx-pcard:active, a.mx-pcard.is-pressed { opacity: .86; } }
.mx-pcard-body .mx-pcard-cta { margin-top: 2px; }
.mx-proj-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 701px) { .mx-proj-list { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 24px; } }

.mx-home-head { padding-top: 4px; }
.mx-home-date { display: block; margin-top: 18px; font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--gold-dark); }
.mx-home-head .mx-lt { margin-top: 6px; }
.mx-home-top { margin-top: var(--sp-24); display: flex; flex-direction: column; gap: 12px; }
.mx-next { background: var(--card); border: 1px solid var(--hair-soft); border-radius: var(--r-lg); display: flex; flex-direction: column; min-width: 0; }
.mx-next > .mx-media { border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0; }
.mx-next-media { color: var(--cream); text-decoration: none; }
a.mx-next-media:hover { color: var(--cream); }
.mx-next-media > .mx-tag { position: absolute; top: 14px; left: 14px; z-index: 1; }
.mx-next-over { position: absolute; left: 16px; right: 16px; bottom: 14px; z-index: 1; display: flex; flex-direction: column; gap: 2px; }
.mx-next-title { font: var(--fw-title2) 26px/30px var(--font-display); letter-spacing: var(--ls-title2); color: var(--cream); text-wrap: balance; }
.mx-next-title i { font-style: italic; color: var(--gold); }
.mx-next-date { font: 400 var(--fs-2nd)/20px var(--font-ui); color: rgba(247,241,230,.88); }
.mx-next-body { display: flex; flex-direction: column; gap: 14px; padding: 16px 16px 6px; }
.mx-next-link { align-self: center; min-height: 44px; display: inline-flex; align-items: center; font: 500 var(--fs-2nd)/20px var(--font-ui); color: var(--crimson); text-decoration: none; }
.mx-next .mx-media > img { transition: transform var(--t-drift) var(--ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) { .mx-next-media:hover > img { transform: scale(1.03); } }
@media (min-width: 901px) {
  .mx-next { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }
  .mx-next-media { height: 100%; aspect-ratio: auto !important; min-height: 320px; }
  .mx-next > .mx-media { border-radius: calc(var(--r-lg) - 1px) 0 0 calc(var(--r-lg) - 1px); }
  .mx-next-title { font-size: 34px; line-height: 38px; }
  .mx-next-body { padding: 28px 28px 16px; justify-content: center; gap: 18px; }
  .mx-next-body .btn-block { max-width: 360px; }
  .mx-next-link { align-self: flex-start; }
}
/* the profile nudge: one row with a thin progress bar, dismissible */
.mx-start { position: relative; background: var(--card); border: 1px solid var(--hair-soft); border-radius: var(--r-lg); max-width: 100%; }
.mx-start:empty { display: none; }
.mx-start-row { display: flex; align-items: center; gap: 14px; min-height: 68px; padding: 12px 52px 12px 16px; box-sizing: border-box; color: var(--ink); text-decoration: none; }
.mx-start-row + .mx-start-row { border-top: 1px solid var(--hair-soft); }
a.mx-start-row:hover { color: var(--ink); }
.mx-start-row > .mx-ic:last-child { color: rgba(25,21,18,.32); }
.mx-start-ic { flex: none; color: var(--gold-dark); display: inline-flex; }
.mx-start-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.mx-start-t { font: 500 var(--fs-body)/22px var(--font-ui); }
.mx-start-s { font: 400 var(--fs-2nd)/18px var(--font-ui); color: var(--soft); }
.mx-start-bar { display: block; height: 3px; background: rgba(25,21,18,.1); max-width: 260px; }
.mx-start-bar > i { display: block; height: 100%; background: var(--crimson); }
.mx-start-go { flex: none; min-height: 44px; display: inline-flex; align-items: center; font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--crimson); cursor: pointer; }
.mx-start-x { position: absolute; top: 50%; right: 4px; transform: translateY(-50%); color: var(--soft); }
.mx-start:has(.mx-start-row + .mx-start-row) .mx-start-x { top: 12px; transform: none; }
@media (min-width: 901px) { .mx-start { max-width: 640px; } }
/* projects shelf: a status chip on each photo */
.mx-home-proj .mx-media > .mx-tag { position: absolute; top: 10px; left: 10px; z-index: 1; max-width: calc(100% - 20px); overflow: hidden; text-overflow: ellipsis; }
.mx-home-proj .mx-media > img { transition: transform var(--t-drift) var(--ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) { .mx-home-proj:hover .mx-media > img { transform: scale(1.04); } }
a.mx-home-proj:hover { color: var(--ink); }
/* news rows: the headline as a title3 row (the UI face, 600), date on the sub-line */
.mx-news { min-height: 64px; }
.mx-news-t { font: 600 var(--fs-title3)/24px var(--font-ui); letter-spacing: var(--ls-title3); color: var(--ink); }
.mx-news .mx-row-s { margin-top: 2px; }
@media (min-width: 901px) {
  .mx-home-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 56px; align-items: start; }
}
.mx-home-net { margin-top: 16px; }
@media (min-width: 701px) { .mx-home-net { display: inline-flex !important; width: auto; min-width: 260px; } }
/* the newsletter sheet */
.mx-nl-sheet { display: flex; flex-direction: column; gap: 12px; }
.mx-nl-sheet .mx-nl-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.mx-nl-sheet .label { margin-top: 4px; }
.mx-nl-done { display: flex; align-items: center; gap: 10px; margin: 4px 0 0; font: 400 var(--fs-body)/24px var(--font-ui); color: var(--ink); }
.mx-nl-done .mx-ic { color: var(--gold-dark); }
/* wide screens carry today's date in the stats strip already */
@media (min-width: 501px) { .mx-home-date { display: none; } .mx-home-head .mx-lt { margin-top: 32px; } }
@media (min-width: 901px) { .mx-home-head .mx-lt { margin-top: 44px; } }
/* the small "coming soon" screens (views/_stub.js): a label, a large title, one line, one ghost action */
.mx-stub-eyebrow { display: block; margin-top: 24px; font: 600 var(--fs-label)/16px var(--font-ui); letter-spacing: .12em; text-transform: uppercase; color: var(--crimson); }
.mx-stub-cta { margin-top: 24px; }
@media (min-width: 901px) { .mx-stub-eyebrow { margin-top: 48px; } }
/* the one coloured italic word of a title (the stubs' "mentor", Profile's "Settings", the system pages): crimson on paper,
   gold on a photo or ink */
.mx-em { color: var(--crimson); }
.mx-em--gold { color: var(--gold); }

/* ---- SYSTEM PAGES (views/notfound.js and views/maintenance.js, bare layout, System Pages.dc.html). Round 3 Phase 1d moved
   their inline styles here. 404: an ink bar with the logo over a centred cream page. Maintenance: the ballroom photo
   under a deep scrim, the copy centred on it ---- */
.mx-sys { font-family: var(--font-ui); color: var(--ink); min-height: 100vh; }
.mx-sys--paper { background: var(--cream); display: flex; flex-direction: column; }
.mx-sys-page { min-height: 100vh; background: var(--cream); display: flex; flex-direction: column; overflow: hidden; }
.mx-sys-bar { background: var(--ink); padding: 16px 32px; display: flex; align-items: center; }
.mx-sys-logo { height: 18px; display: block; }
.mx-sys-body { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 30px; }
/* the 404 is a drawn mark, not a figure that changes or carries money, so it keeps the display face (ROUND3-RULES §3.1) */
.mx-sys-code { font-family: var(--font-display); font-weight: var(--fw-display); font-style: italic; font-size: 90px; line-height: 1; color: rgba(25,21,18,.14); }
.mx-sys-rule { width: 28px; height: 1px; background: var(--gold); margin: 18px 0 14px; }
.mx-sys-h { font-family: var(--font-display); font-weight: var(--fw-title1); letter-spacing: var(--ls-title1); font-size: 30px; line-height: 1.15; }
.mx-sys-why { font-size: 16px; color: var(--soft); line-height: 1.5; max-width: 420px; margin-top: 12px; }
.mx-sys-acts { display: flex; gap: 12px; margin-top: 24px; flex-wrap: wrap; justify-content: center; }
.mx-sys-acts > .btn-primary { padding: 16px 26px; }   /* 48 tall at every width, as drawn */
.mx-sys-acts > .btn-ghost { padding: 15px 26px; }
.mx-sys-stage { min-height: 100vh; position: relative; overflow: hidden; display: flex; flex-direction: column; }
.mx-sys-photo { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; }
.mx-sys-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(25,21,18,.78) 0%, rgba(25,21,18,.9) 100%); }
.mx-sys-body.is-photo { position: relative; color: var(--cream); }
.mx-sys-mark { height: 26px; display: block; }
.mx-sys-kicker { font: 600 12px var(--font-ui); letter-spacing: var(--ls-caps); color: var(--gold); margin-top: 16px; }
.mx-sys-h.is-photo { font-weight: var(--fw-display); letter-spacing: var(--ls-display); font-size: 34px; margin-top: 14px; max-width: 560px; }
.mx-sys-why.is-photo { color: rgba(247,241,230,.82); max-width: 440px; }

/* ============================================================================
   LIQUID GLASS (GLASS-RULES.md §1 · Glass Quiet 2026-09-25)
   Glass is for what FLOATS over content and must stay out of its way: the tab bar, the phone top bar once content
   runs under it and its buttons, sheets, popovers, the drawer, chips and buttons on photos, segmented controls,
   toasts. What IS content (cards, rows, facts, photos, the member card, tickets, the in-page action buttons) stays
   cream paper, rounded on the radius scale (ROUND3-RULES §2, A1). At most three glass surfaces on screen at once.
   The glass lives on a ::before layer, never on the element: a backdrop-filter (or a transform, a filter) on the element
   would make it the containing block of every fixed descendant (the top bar hosts the fixed SEARCH sheet). A glass
   element never animates its own opacity (below 1 it becomes a backdrop root and the blur goes blind): it moves with
   transform and fades its ::before and its contents. The blur radius is never animated.
   Kit (views code against these names, §1.11): .mx-glass (+ .is-dark) · .mx-glass--sheet · .mx-glass--chip ·
   .mx-tag--glass · .mx-gbtn (+ --dark) · [data-glass-dark] · the tall .mx-hero ·
   the .mx-seg restyle · the -fill tab icons (js/icons.js) · the tokens (tokens.css).
   ========================================================================== */
:where(.mx-glass, .mx-tag--glass, .mx-gbtn) { position: relative; }
.mx-glass, .mx-tag--glass, .mx-gbtn { isolation: isolate; }
.mx-glass { box-shadow: var(--glass-shadow); }
.mx-glass::before, .mx-tag--glass::before, .mx-gbtn::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: var(--glass-light); box-shadow: var(--glass-edge-light);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  transition: background-color var(--t-quick) var(--ease), filter 120ms var(--ease); }
.mx-glass.is-dark { box-shadow: var(--glass-shadow-dark); }
.mx-glass.is-dark::before { background: var(--glass-dark); box-shadow: var(--glass-edge-dark); }
.mx-glass--sheet::before { background: var(--glass-light-strong);
  -webkit-backdrop-filter: blur(var(--glass-blur-sheet)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur-sheet)) saturate(var(--glass-sat)); }
.mx-glass--chip::before, .mx-tag--glass::before, .mx-gbtn--dark::before { background: var(--glass-dark-chip); box-shadow: var(--glass-edge-dark);
  -webkit-backdrop-filter: blur(var(--glass-blur-chip)) saturate(150%); backdrop-filter: blur(var(--glass-blur-chip)) saturate(150%); }
/* pressed: the control gives a little and its glass brightens (never on the top bar or a host of a fixed layer) */
/* glass presses to .96 in 100 ms on the ease and comes back on the control spring (smooth-member 3.1: .is-pressed from
   js/ui.js installPress shows it in the first frame) */
.mx-glass:is(a, button, [role="button"], [data-act]), .mx-gbtn { transition: transform var(--spring-control-dur) var(--spring-control); }
.mx-glass:is(a, button, [role="button"], [data-act]):active, .mx-gbtn:active,
.mx-glass:is(a, button, [role="button"], [data-act]).is-pressed, .mx-gbtn.is-pressed { transform: scale(var(--glass-press)); transition: transform var(--t-press) var(--ease); }
.mx-glass:is(a, button, [role="button"], [data-act]):active::before, .mx-gbtn:active::before,
.mx-glass:is(a, button, [role="button"], [data-act]).is-pressed::before, .mx-gbtn.is-pressed::before { filter: brightness(1.06); }

/* ---- chips and buttons on photos (§1.9.5) ---- */
/* a status tag ON a photo: a dark glass capsule, 28 tall, 12px caps. A tag on cream stays paper at --r-xs (.mx-tag--gold …) */
.mx-tag--glass { min-height: 28px; padding: 0 12px; border-radius: var(--r-capsule); color: var(--cream); letter-spacing: .08em; background: none; border: 0;
  box-shadow: 0 2px 10px rgba(0,0,0,.14); text-shadow: 0 1px 2px rgba(0,0,0,.18); }
/* a 44px round icon button: light glass on cream, --dark (chip glass, cream icon) on a photo */
.mx-gbtn { flex: none; width: 44px; height: 44px; padding: 0; box-sizing: border-box; border: 0; border-radius: 50%; background: none; display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink); cursor: pointer; text-decoration: none; box-shadow: 0 2px 10px rgba(25,21,18,.10); -webkit-tap-highlight-color: transparent; }
.mx-gbtn--dark { color: var(--cream); box-shadow: 0 2px 10px rgba(0,0,0,.18); }
@media (hover: hover) { a.mx-gbtn:hover { color: var(--ink); } a.mx-gbtn--dark:hover { color: var(--cream); } }

/* ---- the hero on phones (§1.9.3): a photo hero fills the first screen, only the first block below it peeks. A top scrim
   joins the bottom one, so the clear bar's controls and the status bar read on any photo.
   The height puts the first block's top --mx-hero-peek above the tab bar's top edge: the bar top sits (--mx-tabbar-h − 12px)
   over the bottom of the screen (the token carries 12px of air above the bar, web and native alike), and the first block
   under every photo hero is a .mx-sec--tight, 32px down. The peek (tokens.css, 52px, 46 under 375) shows the Plexus and
   Accelerator tabs whole, the first Gala and Forum fact row and the Bridges tile numbers, and cuts no line of text or
   control from 320 to 440 wide (checked against the capsule's round ends). min-height 300 keeps that peek on a 320 × 568
   screen, the email line included (the hero is 416 there, 315 with the line, and the title, one line and the action need
   under 250). max-height 800 (760 in §1.9.3) keeps
   the same peek on the tallest phone, 440 × 956 (789 in the app, 798 in Safari), where 760 cut the second Gala fact row in
   half; it still stops a tall narrow window from growing an endless photo. While the email line shows, the bar stays in the
   flow above the photo and chrome.js › detectHero puts its height in --mx-hero-top, so the same peek holds */
@media (max-width: 500px) {
  .mx-hero:not(.mx-hero--ink):not(.mx-hero--cream) { aspect-ratio: auto; min-height: 300px; max-height: 800px;
    height: calc(100vh - var(--mx-tabbar-h) + 12px - var(--sp-32) - var(--mx-hero-peek) - var(--mx-hero-top, 0px));
    height: calc(100svh - var(--mx-tabbar-h) + 12px - var(--sp-32) - var(--mx-hero-peek) - var(--mx-hero-top, 0px)); }
  .mx-hero:not(.mx-hero--ink):not(.mx-hero--cream) > .mx-scrim {
    background: linear-gradient(180deg, rgba(25,21,18,.42) 0, rgba(25,21,18,0) 140px),
                linear-gradient(180deg, rgba(25,21,18,.15) 0%, rgba(25,21,18,.35) 45%, rgba(25,21,18,.88) 100%); }
}

/* ---- the floating tab bar (§1.9.1: in browsers, and in the iOS app below iOS 26) ----
   A glass capsule 62 tall, 21px in from both edges (12 on a phone under 375), at most 440 wide, 21px over the home
   indicator (12 without one). Five equal columns: a 24px icon (the line icon idle, the filled one selected) over an
   11px label, the one exception to the 12px floor (Apple's tab labels are 10 to 11pt). The selected lens is a 54px
   capsule that glides to a new tab on the ui spring from the tap frame (ROUND3-RULES §4.2, the tab switch line). Light glass by default, dark over a dark region (chrome.js
   tone switch). The keys, the five > a children, their hrefs, aria-selected and the Inbox badge are the iOS contract */
#mx-tabbar { position: fixed; z-index: 30; left: 21px; right: 21px; bottom: max(12px, calc(env(safe-area-inset-bottom) - 13px)); max-width: 440px; margin: 0 auto;
  height: 62px; padding: 4px; box-sizing: border-box; flex-direction: row; align-items: stretch; border-radius: var(--r-capsule); --i: 0;
  transition: transform 280ms var(--ease);
  /* the bar's own tints (§1.7 ceilings, tokens.css › --glass-bar-*), set as the tokens its .mx-glass layer reads, so the
     solid fallbacks (no blur, Reduce Transparency, Increase Contrast) still replace them */
  --glass-light: var(--glass-bar-light); --glass-dark: var(--glass-bar-dark); }
@media (max-width: 374px) { #mx-tabbar { left: 12px; right: 12px; } }
#mx-tabbar > .mx-tb-lens { position: absolute; z-index: 0; top: 4px; left: 4px; width: calc((100% - 8px) / 5); height: 54px; border-radius: var(--r-capsule);
  background: var(--glass-bar-lens-light); pointer-events: none; transform: translateX(calc(var(--i) * 100%));
  /* its slide is chrome.js › moveLens, on the compositor (as a transition on the linear() spring WebKit held it on the page's thread) */
  transition: background-color var(--t-quick) var(--ease), opacity var(--t-quick) var(--ease); }
#mx-tabbar.is-dark > .mx-tb-lens { background: var(--glass-lens-dark); }
#mx-tabbar.no-lens > .mx-tb-lens { opacity: 0; }
#mx-tabbar > a { position: relative; z-index: 1; flex: 1 1 0; min-width: 0; min-height: 0; height: 54px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 0 2px; box-sizing: border-box; border-radius: var(--r-capsule); color: #4a4239; text-decoration: none; cursor: pointer;
  transition: color var(--t-quick) var(--ease); }
#mx-tabbar .mx-tb-ic { position: relative; width: 28px; height: 26px; display: flex; align-items: center; justify-content: center; }
/* the two glyphs of a tab, one over the other: the line one idle, the filled one selected. The press (the glyph to .92 and
   back on the control spring) and the filled glyph's settle are chrome.js › tabSwap and installTabPress, keyframes the
   compositor plays (tab bar feel, 5 Oct 2026). The label and the badge never scale */
#mx-tabbar .mx-tb-g { position: relative; display: block; flex: none; width: 24px; height: 24px; }
#mx-tabbar .mx-tb-g > svg { position: absolute; left: 0; top: 0; }
#mx-tabbar > a[aria-selected="true"] .mx-tb-off, #mx-tabbar > a:not([aria-selected="true"]) .mx-tb-on { opacity: 0; }
#mx-tabbar .mx-tb-l { font: 600 11px/13px var(--font-ui); letter-spacing: 0; white-space: nowrap; }
#mx-tabbar > a[aria-selected="true"] { color: var(--crimson); }
#mx-tabbar.is-dark > a { color: rgba(247,241,230,.82); }
#mx-tabbar.is-dark > a[aria-selected="true"] { color: var(--gold); }
@media (hover: hover) { #mx-tabbar > a:hover { color: var(--ink); } #mx-tabbar > a[aria-selected="true"]:hover { color: var(--crimson); }
  #mx-tabbar.is-dark > a:hover { color: var(--cream); } #mx-tabbar.is-dark > a[aria-selected="true"]:hover { color: var(--gold); } }
@media (max-width: 340px) { #mx-tabbar .mx-tb-l { letter-spacing: -.01em; } }
.mx-tb-badge { position: absolute; top: -4px; left: 16px; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: var(--r-capsule);
  background: var(--crimson); color: var(--cream); font: 600 12px/18px var(--font-ui); text-align: center; font-variant-numeric: tabular-nums; box-shadow: 0 0 0 2px var(--glass-solid-light); }
#mx-tabbar.is-dark .mx-tb-badge { box-shadow: 0 0 0 2px #3b332c; }
/* the keyboard is up (chrome.js › html.mx-vkb, the visual viewport shrank by more than 150px): the bar steps down out of the way */
html.mx-vkb #mx-tabbar { transform: translateY(calc(100% + 40px)); }
/* the iOS 26 app draws its own native glass bar (medx-native.js sets html.mx-native-tabbar and --mx-tabbar-h inline) */
:root.mx-native-tabbar body[data-layout] #mx-tabbar { display: none !important; }
/* while the web bar is the one showing it keeps its own space free: 62 + its gap to the screen edge + 12 over it (95px on a
   Face ID iPhone, 86 in Safari). html.mx-webbar is set by chrome.js before any view draws (the tall hero reads it) */
html.mx-webbar:not(.mx-native-tabbar) { --mx-tabbar-h: calc(62px + max(12px, calc(env(safe-area-inset-bottom) - 13px)) + 12px); }
html.mx-webbar.mx-vkb:not(.mx-native-tabbar) { --mx-tabbar-h: 0px; }

/* ---- the phone top bar (§1.9.2): three modes, set by chrome.js on #mx-mobile-top and mirrored as html[data-mx-bar] ----
   flat: the page is at its top, nothing under the bar: no layer, no hairline, the bar is part of the page.
   glass: content runs under it: a light glass layer over the bar and the status bar that runs on 40px past the bar and fades
   out over the 60px BELOW the bar (the iOS 26 soft scroll edge), so the bar's own row is fully covered and nothing ghosts behind the logo or the title. A line of text passing
   under the edge then dims evenly: across one 20px line the layer changes by under a third (the 12px feather changed by
   all of it and cut the line in half, its lower half crisp, and a 40px fade still changed by half). Dark glass over a photo
   hero or a dark region (--bar-t, below). With the email line under the bar (.has-banner), without backdrop-filter, under
   Reduce Transparency and under Increase Contrast the layer ends crisply at the bar's edge.
   clear: a pushed screen that opens on a photo hero, at its top: no layer, no title, the controls on dark chip glass. */
#mx-mobile-top.mx-mt::before { content: ""; position: absolute; inset: 0 0 calc(-1 * var(--mt-box, 60px)); z-index: -1; pointer-events: none; opacity: 0;
  background: var(--glass-light); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - var(--mt-box, 60px)), rgba(0,0,0,.84) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .2), rgba(0,0,0,.6) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .4), rgba(0,0,0,.36) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .6), rgba(0,0,0,.14) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .8), transparent calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px)));
  mask-image: linear-gradient(180deg, #000 calc(100% - var(--mt-box, 60px)), rgba(0,0,0,.84) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .2), rgba(0,0,0,.6) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .4), rgba(0,0,0,.36) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .6), rgba(0,0,0,.14) calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px) * .8), transparent calc(100% - var(--mt-box, 60px) + var(--mt-edge, 60px))); }
/* round 3 (Phase 2A, ROUND3-RULES §6.2): the bar moves on two values chrome.js writes once per frame, with no css transition.
   --bar-p, the progress: the layer's opacity, and its soft edge growing from 0 to its full length. --bar-t, the tone (0 light
   glass, 1 dark glass, eased in chrome.js › TONE_MS toward what lies under the bar, never a class flip): the layer's tint, the edge's
   length (60 px on light glass, 24 px on dark, so the hand-off from a photo never lays a deep brown gradient over cream
   content), the chevron's two pairs, the pushed title's colour, the search capsule and the wordmark. The layer's box keeps the full 60 px (a blurred box that resized on every
   frame cost WebKit a new backdrop each frame): only the mask's feather moves. The rules say a 0 to 12 px feather: the Glass
   Quiet pass measured 12 px cutting a passing line of text in half, so the tuned length stays and grows from 0 (named in the
   Phase 2A commit and its open items). An engine with no color-mix() (iOS below 16.2) takes the tint with .is-dark, which
   chrome.js sets on the frame the tone's goal changes */
#mx-mobile-top.mx-mt { --mt-box: 60px; --mt-edge: calc(var(--bar-p, 0) * (60px - 36px * var(--bar-t, 0)));
  --mt-l: var(--glass-light); --mt-d: var(--glass-dark); --mt-cl: var(--glass-light); --mt-cd: var(--glass-dark-chip); }
#mx-mobile-top.mx-mt::before { opacity: var(--bar-p, 0); background: var(--mt-l); }
#mx-mobile-top.mx-mt.has-banner::before { bottom: 0; -webkit-mask-image: none; mask-image: none; }
#mx-mobile-top.mx-mt.is-dark::before { background: var(--mt-d); }
@supports (background: color-mix(in srgb, red calc(.5 * 100%), blue)) {
  #mx-mobile-top.mx-mt::before, #mx-mobile-top.mx-mt.is-dark::before { background: color-mix(in srgb, var(--mt-d) calc(var(--bar-t, 0) * 100%), var(--mt-l)); }
}
/* the pushed title over a photo hero comes in over the hero's last 36 px, from p .4 to 1 (ROUND3-RULES §6.2, at least .5
   to 1, the motion inventory's MI-26: from .85 it took 9 px, a step of .83 in one frame at a calm 12 px a frame, and from .5
   still .4 a frame). The hero's action passes under the bar's row from about p .3 to .85, so the title is still faint while
   the label crosses it */
body.mx-over-hero #mx-mobile-top.is-pushed .mx-mt-title { opacity: clamp(0, calc((var(--bar-p, 0) - .4) / .6), 1); }
#mx-mobile-top.is-dark .mx-mt-title { color: var(--cream); }
/* the veil (walk 30 Sept, Alen: scrolling Home the top "all of a sudden becomes white in a slightly unnatural way"). Over a root's
   photo top (.is-veil, chrome.js: Home's Today card) the layer is the light glass from the start, clear at rest, and blends in
   on the scroll alone: its opacity and its soft edge follow --bar-q, one smooth curve tied to the hero's bottom edge, never
   the tone's turn in time. The tone (--bar-t) still turns the chip and the wordmark where the clock turns, over a veil about
   half in, so both of their pairs read there. The wordmark folds on the same long blend. The folded title needs ink on a
   light ground, so it comes in after the turn (--bar-f). A crossing draws the same veil solid. A pushed screen on Home's top
   (a [data-hx] hero, 5 Oct 2026) gets it too. Any other pushed photo hero, the Plexus band, Reduce Transparency and
   Increase Contrast never get .is-veil: their layer turns with the tone as before */
#mx-mobile-top.mx-mt.is-veil { --mt-edge: calc(var(--bar-q, 0) * 60px); }
#mx-mobile-top.mx-mt.is-veil::before, #mx-mobile-top.mx-mt.is-veil.is-dark::before { opacity: var(--bar-q, 0); background: var(--mt-l); }
html[data-mx-nav] #mx-mobile-top.mx-mt.is-veil::before, html[data-mx-nav] #mx-mobile-top.mx-mt.is-veil.is-dark::before { background: var(--glass-solid-light); }
#mx-mobile-top.is-veil .mx-mt-brand .mx-wm { transform: scale(calc(1 - var(--bar-q, 0) * .2142857)); }
#mx-mobile-top.is-veil .mx-mt-fold { opacity: var(--bar-f, 0); }
/* a pushed screen on Home's top (chrome.js: a [data-hx] hero) takes the same veil: its title is ink on the light layer, so
   it comes in as the root's folded title does, once the photo has passed under its line (--bar-f, after the tone's turn) */
body.mx-over-hero #mx-mobile-top.is-pushed.is-veil .mx-mt-title { opacity: var(--bar-f, 0); }
/* the logo in both top bars answers a long press (js/eggs.js, the X): no link preview, callout or drag comes up on it */
.mx-brand, .mx-brand img { -webkit-touch-callout: none; -webkit-user-drag: none; }
/* the controls: the back chevron in a 44px glass circle, search in a 44px glass circle too (no bell, D10), the logo plain.
   The chevron's light pair (the chip's ::before, crimson on light glass, and its first icon) and its dark pair (its ::after,
   dark chip glass, and .mx-mt-back-dk in cream) cross-fade on --bar-t: dark over a photo hero and over a dark region */
#mx-mobile-top .mx-mt-back { color: var(--crimson); }
#mx-mobile-top .mx-mt-back::after { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: var(--glass-dark-chip); box-shadow: var(--glass-edge-dark);
  -webkit-backdrop-filter: blur(var(--glass-blur-chip)) saturate(150%); backdrop-filter: blur(var(--glass-blur-chip)) saturate(150%); }
#mx-mobile-top .mx-mt-back-dk { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--cream); pointer-events: none; }
#mx-mobile-top .mx-mt-back::before, #mx-mobile-top .mx-mt-back > .mx-ic { opacity: calc(1 - var(--bar-t, 0)); transition: none; }
#mx-mobile-top .mx-mt-back::after, #mx-mobile-top .mx-mt-back-dk { opacity: var(--bar-t, 0); }
#mx-mobile-top .mx-mt-caps::before { transition: none; background: var(--mt-cl); }
#mx-mobile-top.is-dark .mx-mt-caps::before { background: var(--mt-cd); box-shadow: var(--glass-edge-dark); }
#mx-mobile-top.is-dark .mx-mt-caps .mx-mt-btn { color: var(--cream); }
@supports (background: color-mix(in srgb, red calc(.5 * 100%), blue)) {
  #mx-mobile-top .mx-mt-caps::before, #mx-mobile-top.is-dark .mx-mt-caps::before { background: color-mix(in srgb, var(--mt-cd) calc(var(--bar-t, 0) * 100%), var(--mt-cl)); }
  #mx-mobile-top .mx-mt-caps .mx-mt-btn, #mx-mobile-top.is-dark .mx-mt-caps .mx-mt-btn,
  #mx-mobile-top .mx-mt-title, #mx-mobile-top.is-dark .mx-mt-title { color: color-mix(in srgb, var(--cream) calc(var(--bar-t, 0) * 100%), var(--ink)); }
}
.mx-mt-caps { flex: none; display: inline-flex; align-items: center; height: 44px; border-radius: var(--r-capsule); box-shadow: 0 2px 10px rgba(25,21,18,.10); margin-right: 4px; }
.mx-mt-caps .mx-mt-btn { width: 44px; height: 44px; border-radius: 50%; }
#mx-mobile-top .mx-mt-caps .mx-mt-btn:active, #mx-mobile-top .mx-mt-back:active,
#mx-mobile-top .mx-mt-caps .mx-mt-btn.is-pressed, #mx-mobile-top .mx-mt-back.is-pressed { opacity: 1; }
.mx-mt-caps .mx-mt-btn:active .mx-ic, .mx-mt-caps .mx-mt-btn.is-pressed .mx-ic { transform: scale(.88); }
.mx-mt-caps .mx-ic { transition: transform 120ms var(--ease); }
#mx-mobile-top .mx-mt-back { margin-left: 4px; }
#mx-mobile-top .mx-mt-spacer { margin-right: 4px; }
/* a root's bar over a photo (is-root + is-clear, set by chrome.js while a root's photo hero, Home's Today card, is under it):
   the logo in cream and search on the dark chip glass, as a pushed screen's back button is over a hero. Chrome, so it holds
   from the bar's first frame, before a view's own stylesheet has loaded (moved from css/views/home.css) */
#mx-mobile-top.is-root.is-clear .mx-mt-caps::before { box-shadow: var(--glass-edge-dark);
  -webkit-backdrop-filter: blur(var(--glass-blur-chip)) saturate(150%); backdrop-filter: blur(var(--glass-blur-chip)) saturate(150%); }
/* the chip's tint, its glyph and the two wordmarks cross-fade on the bar's tone (--bar-t, chrome.js eases it), never in one
   frame: the dark chip and the on-dark wordmark come in as the tone turns (the motion inventory's MI-04). Without
   color-mix() the chip takes the dark tint with .is-dark */
#mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: var(--glass-dark-chip); }
#mx-mobile-top.is-root.is-clear .mx-mt-caps .mx-mt-btn { color: var(--cream); }
@supports (background: color-mix(in srgb, red calc(.5 * 100%), blue)) {
  #mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: color-mix(in srgb, var(--glass-dark-chip) calc(var(--bar-t, 0) * 100%), var(--mt-cl)); }
  #mx-mobile-top.is-root.is-clear .mx-mt-caps .mx-mt-btn { color: color-mix(in srgb, var(--cream) calc(var(--bar-t, 0) * 100%), var(--ink)); }
}
#mx-mobile-top.is-root.is-clear .mx-mt-caps { box-shadow: 0 2px 10px rgba(0, 0, 0, calc(.10 + var(--bar-t, 0) * .08)); }
/* the logo: today's bitmap turns to its white twin (no vector pair), the vector wordmark pair (Phase 2A) keeps its tone
   cross-fade (.mx-mt-brand above) */
#mx-mobile-top.is-root.is-clear .mx-mt-brand > img:not(.mx-wm) { content: url("/assets/logo-white.png"); }
/* fallbacks (GLASS §1.6): no blur, Reduce Transparency, Increase Contrast take the solid dark chip */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  #mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: var(--glass-solid-dark); }
}
@media (prefers-reduced-transparency: reduce) {
  #mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: var(--glass-solid-dark); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
html.mx-rt #mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: var(--glass-solid-dark); -webkit-backdrop-filter: none; backdrop-filter: none; }
@media (prefers-contrast: more) {
  #mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: var(--glass-solid-dark); box-shadow: inset 0 0 0 1px rgba(247, 241, 230, .55); }
}
html.mx-hc #mx-mobile-top.is-root.is-clear .mx-mt-caps::before { background: var(--glass-solid-dark); box-shadow: inset 0 0 0 1px rgba(247, 241, 230, .55); }
/* over a photo hero the bar floats: #chrome leaves the flow (fixed), so the photo starts at the very top of the screen,
   under the status bar (chrome.js › body.mx-over-hero, never while the email line shows) */
@media (max-width: 500px) {
  body.mx-over-hero[data-layout="portal"] #chrome { position: fixed; top: 0; left: 0; right: 0; }
  /* SEARCH or ALERTS open: the bar and its sheet rise above the tab bar (the native layer does this with :has) */
  body.mx-pop-open[data-layout="portal"] #chrome { z-index: 40; }
}

/* ---- sheets, popovers and search on phones (§1.9.4): they float 8px off the edges ---- */
@media (max-width: 500px) {
  .mx-search { padding: calc(8px + env(safe-area-inset-top)) 8px 0; }
  .mx-search-panel { width: 100%; }
}
/* A phone sheet rises on the calm spring and goes down on the control spring (both critically damped: it never goes past
   its place, motion pass 1 Oct 2026, where the settle curve took the person peek 5 px and the Zagreb place 8 px past and
   back). Each spring is sampled into the keyframes below and played on a linear easing, which WebKit keeps on the
   compositor (a linear() easing it plays on the page's own thread). The calm rise moves at most 7.7 percent of the way in
   a 60 fps frame, the control fall 9.1 percent. Regenerate with springCurve and springAt (js/ui.js), never hand-edit */
@media (max-width: 500px) and (prefers-reduced-motion: no-preference) {
  .mx-modal:not(.is-wide) .mx-modal-sheet { animation: mx-sheet-up var(--spring-calm-dur) linear backwards; }
  .mx-modal.is-leaving:not(.is-wide) .mx-modal-sheet { animation: mx-sheet-down var(--spring-control-dur) linear forwards; }
  /* the dim goes on the fall's own clock: on --t-settle it was gone 100 ms before the sheet, which fell over a bright page */
  .mx-modal.is-leaving:not(.is-wide):not(.is-handed) { animation-duration: var(--spring-control-dur); }
  .mx-modal:not(.is-wide) .mx-modal-sheet::before, .mx-modal:not(.is-wide) .mx-modal-sheet > * { animation: none; }
  .mx-modal.is-leaving:not(.is-wide) .mx-modal-sheet::before, .mx-modal.is-leaving:not(.is-wide) .mx-modal-sheet > * { animation: none; }
}
@keyframes mx-sheet-up {
  0% { transform: translateY(calc(1.0000 * (100% + 24px))); }
  3.125% { transform: translateY(calc(0.9685 * (100% + 24px))); }
  6.25% { transform: translateY(calc(0.8943 * (100% + 24px))); }
  9.375% { transform: translateY(calc(0.7999 * (100% + 24px))); }
  12.5% { transform: translateY(calc(0.6992 * (100% + 24px))); }
  15.625% { transform: translateY(calc(0.6007 * (100% + 24px))); }
  18.75% { transform: translateY(calc(0.5091 * (100% + 24px))); }
  21.875% { transform: translateY(calc(0.4269 * (100% + 24px))); }
  25% { transform: translateY(calc(0.3548 * (100% + 24px))); }
  28.125% { transform: translateY(calc(0.2927 * (100% + 24px))); }
  31.25% { transform: translateY(calc(0.2399 * (100% + 24px))); }
  34.375% { transform: translateY(calc(0.1956 * (100% + 24px))); }
  37.5% { transform: translateY(calc(0.1588 * (100% + 24px))); }
  40.625% { transform: translateY(calc(0.1283 * (100% + 24px))); }
  43.75% { transform: translateY(calc(0.1033 * (100% + 24px))); }
  46.875% { transform: translateY(calc(0.0829 * (100% + 24px))); }
  50% { transform: translateY(calc(0.0664 * (100% + 24px))); }
  53.125% { transform: translateY(calc(0.0530 * (100% + 24px))); }
  56.25% { transform: translateY(calc(0.0422 * (100% + 24px))); }
  59.375% { transform: translateY(calc(0.0336 * (100% + 24px))); }
  62.5% { transform: translateY(calc(0.0266 * (100% + 24px))); }
  65.625% { transform: translateY(calc(0.0211 * (100% + 24px))); }
  68.75% { transform: translateY(calc(0.0167 * (100% + 24px))); }
  71.875% { transform: translateY(calc(0.0131 * (100% + 24px))); }
  75% { transform: translateY(calc(0.0104 * (100% + 24px))); }
  78.125% { transform: translateY(calc(0.0082 * (100% + 24px))); }
  81.25% { transform: translateY(calc(0.0064 * (100% + 24px))); }
  84.375% { transform: translateY(calc(0.0050 * (100% + 24px))); }
  87.5% { transform: translateY(calc(0.0040 * (100% + 24px))); }
  90.625% { transform: translateY(calc(0.0031 * (100% + 24px))); }
  93.75% { transform: translateY(calc(0.0024 * (100% + 24px))); }
  96.875% { transform: translateY(calc(0.0019 * (100% + 24px))); }
  100% { transform: translateY(calc(0.0000 * (100% + 24px))); }
}
@keyframes mx-sheet-down {
  0% { transform: translateY(calc(0.0000 * (100% + 24px))); }
  3.125% { transform: translateY(calc(0.0314 * (100% + 24px))); }
  6.25% { transform: translateY(calc(0.1054 * (100% + 24px))); }
  9.375% { transform: translateY(calc(0.1996 * (100% + 24px))); }
  12.5% { transform: translateY(calc(0.3001 * (100% + 24px))); }
  15.625% { transform: translateY(calc(0.3985 * (100% + 24px))); }
  18.75% { transform: translateY(calc(0.4900 * (100% + 24px))); }
  21.875% { transform: translateY(calc(0.5722 * (100% + 24px))); }
  25% { transform: translateY(calc(0.6443 * (100% + 24px))); }
  28.125% { transform: translateY(calc(0.7064 * (100% + 24px))); }
  31.25% { transform: translateY(calc(0.7593 * (100% + 24px))); }
  34.375% { transform: translateY(calc(0.8036 * (100% + 24px))); }
  37.5% { transform: translateY(calc(0.8406 * (100% + 24px))); }
  40.625% { transform: translateY(calc(0.8711 * (100% + 24px))); }
  43.75% { transform: translateY(calc(0.8961 * (100% + 24px))); }
  46.875% { transform: translateY(calc(0.9166 * (100% + 24px))); }
  50% { transform: translateY(calc(0.9332 * (100% + 24px))); }
  53.125% { transform: translateY(calc(0.9466 * (100% + 24px))); }
  56.25% { transform: translateY(calc(0.9575 * (100% + 24px))); }
  59.375% { transform: translateY(calc(0.9662 * (100% + 24px))); }
  62.5% { transform: translateY(calc(0.9732 * (100% + 24px))); }
  65.625% { transform: translateY(calc(0.9788 * (100% + 24px))); }
  68.75% { transform: translateY(calc(0.9832 * (100% + 24px))); }
  71.875% { transform: translateY(calc(0.9867 * (100% + 24px))); }
  75% { transform: translateY(calc(0.9895 * (100% + 24px))); }
  78.125% { transform: translateY(calc(0.9918 * (100% + 24px))); }
  81.25% { transform: translateY(calc(0.9935 * (100% + 24px))); }
  84.375% { transform: translateY(calc(0.9949 * (100% + 24px))); }
  87.5% { transform: translateY(calc(0.9960 * (100% + 24px))); }
  90.625% { transform: translateY(calc(0.9969 * (100% + 24px))); }
  93.75% { transform: translateY(calc(0.9975 * (100% + 24px))); }
  96.875% { transform: translateY(calc(0.9981 * (100% + 24px))); }
  100% { transform: translateY(calc(1.0000 * (100% + 24px))); }
}

/* ---- fallbacks (§1.6): no backdrop-filter, Reduce Transparency (the media query, and html.mx-rt from the iOS app),
   Increase Contrast (the media query, and html.mx-hc from the iOS app) ---- */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .mx-glass::before, .mx-gbtn::before, .mx-seg { background-color: var(--glass-solid-light); }
  #mx-mobile-top.mx-mt { --mt-l: var(--glass-solid-light); --mt-d: var(--glass-solid-dark); --mt-cl: var(--glass-solid-light); --mt-cd: var(--glass-solid-dark); }
  #mx-mobile-top.mx-mt::before { bottom: 0; -webkit-mask-image: none; mask-image: none; }   /* solid, so it ends at the bar's edge */
  .mx-glass.is-dark::before, .mx-glass--chip::before, .mx-tag--glass::before, .mx-gbtn--dark::before, .mx-toast::before, #mx-drawer::before,
  #mx-mobile-top .mx-mt-back::after { background: var(--glass-solid-dark); }
}
@media (prefers-reduced-transparency: reduce) {
  .mx-glass::before, .mx-gbtn::before, #mx-mobile-top.mx-mt::before, .mx-glass--chip::before, .mx-tag--glass::before, .mx-toast::before, #mx-drawer::before,
  #mx-mobile-top .mx-mt-back::before, #mx-mobile-top .mx-mt-back::after, #mx-mobile-top .mx-mt-caps::before { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
  .mx-glass::before, .mx-gbtn::before { background: var(--glass-solid-light); }
  #mx-mobile-top.mx-mt { --mt-l: var(--glass-solid-light); --mt-d: var(--glass-solid-dark); --mt-cl: var(--glass-solid-light); --mt-cd: var(--glass-solid-dark); }
  #mx-mobile-top.mx-mt::before { bottom: 0; -webkit-mask-image: none; mask-image: none; }
  .mx-glass.is-dark::before, .mx-glass--chip::before, .mx-tag--glass::before, .mx-gbtn--dark::before, .mx-toast::before, #mx-drawer::before,
  #mx-mobile-top .mx-mt-back::after { background: var(--glass-solid-dark); }
}
html.mx-rt .mx-glass::before, html.mx-rt .mx-gbtn::before, html.mx-rt #mx-mobile-top.mx-mt::before, html.mx-rt .mx-glass--chip::before, html.mx-rt .mx-tag--glass::before,
html.mx-rt .mx-toast::before, html.mx-rt #mx-drawer::before, html.mx-rt #mx-mobile-top .mx-mt-back::before, html.mx-rt #mx-mobile-top .mx-mt-back::after, html.mx-rt #mx-mobile-top .mx-mt-caps::before {
  -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
html.mx-rt .mx-glass::before, html.mx-rt .mx-gbtn::before { background: var(--glass-solid-light); }
html.mx-rt #mx-mobile-top.mx-mt { --mt-l: var(--glass-solid-light); --mt-d: var(--glass-solid-dark); --mt-cl: var(--glass-solid-light); --mt-cd: var(--glass-solid-dark); }
html.mx-rt #mx-mobile-top.mx-mt::before { bottom: 0; -webkit-mask-image: none; mask-image: none; }
html.mx-rt .mx-glass.is-dark::before, html.mx-rt .mx-glass--chip::before, html.mx-rt .mx-tag--glass::before, html.mx-rt .mx-gbtn--dark::before,
html.mx-rt .mx-toast::before, html.mx-rt #mx-drawer::before, html.mx-rt #mx-mobile-top .mx-mt-back::after { background: var(--glass-solid-dark); }
@media (prefers-contrast: more) {
  .mx-glass::before, .mx-gbtn::before { background: var(--glass-solid-light); box-shadow: inset 0 0 0 1px rgba(25,21,18,.55); }
  .mx-glass.is-dark::before, .mx-glass--chip::before, .mx-tag--glass::before, .mx-gbtn--dark::before, .mx-toast::before, #mx-drawer::before,
  #mx-mobile-top .mx-mt-back::after { background: var(--glass-solid-dark); box-shadow: inset 0 0 0 1px rgba(247,241,230,.55); }
  #mx-mobile-top.mx-mt { --mt-l: var(--glass-solid-light); --mt-d: var(--glass-solid-dark); --mt-cl: var(--glass-solid-light); --mt-cd: var(--glass-solid-dark); }
  #mx-mobile-top.mx-mt::before, #mx-mobile-top .mx-mt-caps::before { box-shadow: inset 0 0 0 1px rgba(25,21,18,.55); }
  #mx-mobile-top.mx-mt.is-dark::before, #mx-mobile-top.is-dark .mx-mt-caps::before { box-shadow: inset 0 0 0 1px rgba(247,241,230,.55); }
  #mx-tabbar > a:not([aria-selected="true"]) { color: var(--ink); }
  #mx-tabbar.is-dark > a:not([aria-selected="true"]) { color: var(--cream); }
  #mx-mobile-top.mx-mt::before { bottom: 0; -webkit-mask-image: none; mask-image: none; }
}
html.mx-hc .mx-glass::before, html.mx-hc .mx-gbtn::before { background: var(--glass-solid-light); box-shadow: inset 0 0 0 1px rgba(25,21,18,.55); }
html.mx-hc .mx-glass.is-dark::before, html.mx-hc .mx-glass--chip::before, html.mx-hc .mx-tag--glass::before, html.mx-hc .mx-gbtn--dark::before,
html.mx-hc .mx-toast::before, html.mx-hc #mx-drawer::before, html.mx-hc #mx-mobile-top .mx-mt-back::after {
  background: var(--glass-solid-dark); box-shadow: inset 0 0 0 1px rgba(247,241,230,.55); }
html.mx-hc #mx-mobile-top.mx-mt { --mt-l: var(--glass-solid-light); --mt-d: var(--glass-solid-dark); --mt-cl: var(--glass-solid-light); --mt-cd: var(--glass-solid-dark); }
html.mx-hc #mx-mobile-top.mx-mt::before, html.mx-hc #mx-mobile-top .mx-mt-caps::before { box-shadow: inset 0 0 0 1px rgba(25,21,18,.55); }
html.mx-hc #mx-mobile-top.mx-mt.is-dark::before, html.mx-hc #mx-mobile-top.is-dark .mx-mt-caps::before { box-shadow: inset 0 0 0 1px rgba(247,241,230,.55); }
/* Increase Contrast: the layer's and the capsule's hairline turn with the tone too */
@supports (background: color-mix(in srgb, red calc(.5 * 100%), blue)) {
  #mx-mobile-top.mx-mt::before, #mx-mobile-top.mx-mt.is-dark::before, #mx-mobile-top .mx-mt-caps::before, #mx-mobile-top.is-dark .mx-mt-caps::before {
    --mt-line: color-mix(in srgb, rgba(247,241,230,.55) calc(var(--bar-t, 0) * 100%), rgba(25,21,18,.55)); }
  html.mx-hc #mx-mobile-top.mx-mt::before, html.mx-hc #mx-mobile-top.mx-mt.is-dark::before, html.mx-hc #mx-mobile-top .mx-mt-caps::before,
  html.mx-hc #mx-mobile-top.is-dark .mx-mt-caps::before { box-shadow: inset 0 0 0 1px var(--mt-line); }
}
@media (prefers-contrast: more) {
  @supports (background: color-mix(in srgb, red calc(.5 * 100%), blue)) {
    #mx-mobile-top.mx-mt::before, #mx-mobile-top.mx-mt.is-dark::before, #mx-mobile-top .mx-mt-caps::before, #mx-mobile-top.is-dark .mx-mt-caps::before { box-shadow: inset 0 0 0 1px var(--mt-line); }
  }
}
html.mx-hc #mx-tabbar > a:not([aria-selected="true"]) { color: var(--ink); }
html.mx-hc #mx-mobile-top.mx-mt::before { bottom: 0; -webkit-mask-image: none; mask-image: none; }
html.mx-hc #mx-tabbar.is-dark > a:not([aria-selected="true"]) { color: var(--cream); }

/* ---- reduced motion (§1.4): no press scale, no lens slide, no capsule slide; a 120ms colour change instead ---- */
@media (prefers-reduced-motion: reduce) {
  .mx-glass:is(a, button, [role="button"], [data-act]):active, .mx-gbtn:active, #mx-tabbar > a:active { transform: none; }
  #mx-tabbar > .mx-tb-lens { transition: none !important; }
  #mx-tabbar > a:active { color: var(--ink); }
  .mx-glass:is(a, button, [role="button"], [data-act]).is-pressed, .mx-gbtn.is-pressed { transform: none; }
}

/* ============================================================================
   DIRECTION C, "HOUSE LIGHTS" (Alen picked C for everything, 1 Oct 2026): the top bar's logo slot, its seat and the wide
   bar. Design: round3/design-opening-2026-09-29/C (proto/css/proto.css › the bar). ONE variant on every ground: the logo
   is the wordmark (js/wordmark.js, the ink word, the gold, the crimson) in a cream glass seat, over the photo as over the
   paper (the crimson about 5 to 1 on it, the ink word over 12), and the controls beside it share that light glass, so the
   row reads the same at rest on a photo top and on paper and nothing in it changes tone on scroll. The bar's own glass
   layer still comes in over the paper only. Transform and opacity only, nothing here has a transition of its own.
   ========================================================================== */
.mx-cb-seat { position: absolute; top: 0; height: 44px; border-radius: 22px; pointer-events: none;
  background: rgba(250, 246, 238, .80); -webkit-backdrop-filter: blur(var(--glass-blur-chip)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur-chip)) saturate(var(--glass-sat));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .70), inset 0 0 0 .5px rgba(255, 255, 255, .50), inset 0 0 0 .5px rgba(25, 21, 18, .12); }
.mx-cb-wm { position: relative; display: block; flex: none; overflow: visible; color: #15161A; }
/* the phone's root bar: the ink on the page's 20 px gutter (8 px of bar padding and 12 of margin), its optical centre (.5703
   of the ink down, between the ink's middle and the lowercase band's) on the controls' centre line, y 28 of the 56 px row,
   so the ink's top sits 7.75 px into the 44 px box. The seat is the ink grown by 12 px of air each side */
#mx-mobile-top .mx-mt-brand.mx-cb { align-items: flex-start; margin-left: 12px; }
#mx-mobile-top .mx-mt-brand.mx-cb .mx-cb-seat { left: -12px; right: -12px; }
#mx-mobile-top .mx-mt-brand.mx-cb .mx-cb-wm { margin-top: 7.75px; }
/* the search circle shares the seat's light glass on every ground (over the photo too), its glyph in ink */
#mx-mobile-top.mx-cbar.is-root .mx-mt-caps::before { background: rgba(250, 246, 238, .80);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .70), inset 0 0 0 .5px rgba(255, 255, 255, .50), inset 0 0 0 .5px rgba(25, 21, 18, .12); }
#mx-mobile-top.mx-cbar.is-root .mx-mt-caps .mx-mt-btn { color: var(--ink); }
#mx-mobile-top.mx-cbar.is-root .mx-mt-caps { box-shadow: 0 2px 10px rgba(25, 21, 18, .10); }

/* the wide bar (from 501 px): the phone's bar grown. A 64 px row, every control a 44 px glass circle or capsule centred on
   y 32, the logo's seat between the menu and the flex, the content on the Home column's edge (--wb-g) */
#mx-desktop-chrome { --wb-g: 36px; }
@media (min-width: 1181px) { #mx-desktop-chrome { --wb-g: max(36px, calc((100vw - 1108px) / 2)); } }
.mx-wbar { position: relative; display: flex; align-items: center; gap: 10px; height: 64px; padding: 0 var(--wb-g); box-sizing: border-box; color: var(--ink); }
.mx-wb-gc, .mx-wb-gcap { position: relative; flex: none; height: 44px; display: inline-flex; align-items: center; justify-content: center; color: var(--ink); text-decoration: none;
  background: rgba(250, 246, 238, .80); -webkit-backdrop-filter: blur(var(--glass-blur-chip)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur-chip)) saturate(var(--glass-sat));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .70), inset 0 0 0 .5px rgba(255, 255, 255, .50), inset 0 0 0 .5px rgba(25, 21, 18, .12);
  transition: scale var(--spring-snappy-dur) var(--spring-snappy); }
.mx-wb-gc { width: 44px; border-radius: 50%; }
.mx-wb-gcap { gap: 8px; min-width: 168px; padding: 0 18px 0 13px; border-radius: var(--r-capsule); justify-content: flex-start; }
.mx-wb-gc:active, .mx-wb-gcap:active { scale: .96; transition-duration: var(--t-press, 100ms); transition-timing-function: var(--ease); }
.mx-wb-find { font: 400 var(--fs-body)/1 var(--font-ui); letter-spacing: 0; }
.mx-wb-gcap .mx-ic { opacity: .9; }
.mx-wb-dot { position: absolute; top: 11px; right: 12px; width: 7px; height: 7px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 1.5px rgba(25, 21, 18, .45); }
.mx-wb-av { width: 34px; height: 34px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--ink); color: var(--cream);
  font: 600 var(--fs-body)/1 var(--font-ui); letter-spacing: 0; }
.mx-wb-brand { position: relative; display: flex; align-items: center; height: 44px; padding: 0 14px; text-decoration: none; }
.mx-wb-brand .mx-cb-seat { left: 0; right: 0; }
.mx-wb-flex { flex: 1 1 auto; }
.mx-wbar .mx-pop { top: 64px; right: var(--wb-g); }
@media (prefers-reduced-motion: reduce) { .mx-wb-gc:active, .mx-wb-gcap:active { scale: none; opacity: .72; } }
/* over Home's photo top (chrome.js › body.mx-wfloat): the chrome floats clear over the photo, the page starts under it. Its
   glass layer runs 28 px past the row and fades out (the iOS soft edge), at --bar-p, which follows the photo melting into
   the paper under the row's centre line, so it only ever comes in over a ground that is already light. The date strip
   steps aside there (the greeting carries the day) */
body.mx-wfloat[data-layout="portal"] #mx-desktop-chrome { position: fixed; z-index: 20; top: 0; left: 0; right: 0; }
body.mx-wfloat #mx-desktop-chrome .mx-stats { display: none !important; }
#mx-desktop-chrome { isolation: isolate; }
body.mx-wfloat #mx-desktop-chrome::before { content: ""; position: absolute; z-index: -1; left: 0; right: 0; top: 0; height: calc(100% + 28px); pointer-events: none; opacity: var(--bar-p, 0);
  background: rgba(247, 241, 230, .80); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 28px), rgba(0,0,0,.84) calc(100% - 21px), rgba(0,0,0,.5) calc(100% - 14px), rgba(0,0,0,.16) calc(100% - 7px), rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 28px), rgba(0,0,0,.84) calc(100% - 21px), rgba(0,0,0,.5) calc(100% - 14px), rgba(0,0,0,.16) calc(100% - 7px), rgba(0,0,0,0) 100%); }
/* the old bar's hairline row is gone with it: the strip and the banner under the row keep theirs */
/* fallbacks (GLASS §1.6): no backdrop filter, Reduce Transparency, Increase Contrast. Solid light glass, the layer ends at the row */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .mx-cb-seat, .mx-wb-gc, .mx-wb-gcap, #mx-mobile-top.mx-cbar.is-root .mx-mt-caps::before, body.mx-wfloat #mx-desktop-chrome::before { background: var(--glass-solid-light); }
}
@media (prefers-reduced-transparency: reduce) {
  .mx-cb-seat, .mx-wb-gc, .mx-wb-gcap, #mx-mobile-top.mx-cbar.is-root .mx-mt-caps::before, body.mx-wfloat #mx-desktop-chrome::before { background: var(--glass-solid-light); -webkit-backdrop-filter: none; backdrop-filter: none; }
  body.mx-wfloat #mx-desktop-chrome::before { height: 100%; -webkit-mask-image: none; mask-image: none; }
}
html.mx-rt .mx-cb-seat, html.mx-rt .mx-wb-gc, html.mx-rt .mx-wb-gcap, html.mx-rt #mx-mobile-top.mx-cbar.is-root .mx-mt-caps::before, html.mx-rt body.mx-wfloat #mx-desktop-chrome::before {
  background: var(--glass-solid-light); -webkit-backdrop-filter: none; backdrop-filter: none; }
@media (prefers-contrast: more) {
  .mx-cb-seat, .mx-wb-gc, .mx-wb-gcap, #mx-mobile-top.mx-cbar.is-root .mx-mt-caps::before { background: var(--glass-solid-light); box-shadow: inset 0 0 0 1px rgba(25, 21, 18, .55); }
}
html.mx-hc .mx-cb-seat, html.mx-hc .mx-wb-gc, html.mx-hc .mx-wb-gcap, html.mx-hc #mx-mobile-top.mx-cbar.is-root .mx-mt-caps::before { background: var(--glass-solid-light); box-shadow: inset 0 0 0 1px rgba(25, 21, 18, .55); }
