/* NALOXONE, the components the four concepts share.
 *
 * This sheet is LOADED AFTER /appts-shell.css and adds nothing to the token
 * layer. Every colour, radius, shadow, easing and font here is a token from
 * the shell, so these components cannot drift from the client app when the
 * app's own palette moves. If you find yourself typing a hex value into this
 * file, you are building beside the site again.
 *
 * Colour discipline, as the app uses it:
 *   magenta  the emotional accent and the primary action
 *   teal     live or positive system state, and a confirmed safe thing
 *   gold     a soft warning (a kit running out, a dose window opening)
 *   red      999 and nothing else
 */

/* ---- the 999 bar. Red is reserved for this. ---------------------------- */
.nx-999{display:flex;align-items:center;gap:20px;padding:20px 24px;border-radius:var(--r-lg);
  background:rgba(180,35,24,.12);border:1px solid rgba(180,35,24,.34);flex-wrap:wrap}
html[data-theme="light"] .nx-999{background:#FDECEA;border-color:#F3C6C1}
.nx-999-ic{width:46px;height:46px;border-radius:14px;flex-shrink:0;display:grid;place-items:center;
  background:var(--system-error);color:#fff}
.nx-999-tx{flex:1;min-width:220px}
.nx-999-tx h2{font-family:var(--display);font-size:18px;font-weight:700;letter-spacing:-.02em;
  color:#FF9C93;margin-bottom:4px}
html[data-theme="light"] .nx-999-tx h2{color:#8E1A11}
.nx-999-tx p{font-size:14px;color:var(--ink-2);line-height:1.45}
.nx-call{display:inline-flex;align-items:center;gap:9px;padding:13px 24px;border-radius:var(--r-sm);
  background:var(--system-error);color:#fff;font-size:15px;font-weight:700;white-space:nowrap;
  box-shadow:0 8px 22px rgba(180,35,24,.36);
  transition:transform .18s var(--bounce),filter .2s var(--ease)}
.nx-call:hover{filter:brightness(1.1)}
.nx-call:active{transform:scale(.97)}

/* ---- small link-buttons inside a service card -------------------------- */
.nx-acts{display:flex;flex-wrap:wrap;gap:8px}
.nx-mini{display:inline-flex;align-items:center;gap:7px;padding:9px 15px;border-radius:999px;
  border:1px solid var(--hair);background:var(--raise-2);color:var(--ink-2);font-size:13px;
  font-weight:600;transition:background .2s var(--ease),color .2s var(--ease),transform .18s var(--bounce)}
.nx-mini:hover{background:var(--hair);color:var(--ink)}
.nx-mini:active{transform:scale(.96)}
.nx-mini-go{background:var(--secondary);border-color:var(--secondary);color:#fff}
.nx-mini-go:hover{background:var(--secondary);color:#fff;filter:brightness(1.1)}

/* ---- a service, wherever it appears ------------------------------------ */
.nx-svc{display:flex;gap:14px;align-items:flex-start;width:100%;text-align:left;padding:16px 18px;
  border:1px solid var(--hair);border-radius:var(--r-md);background:var(--raise);
  transition:transform .2s var(--spring),border-color .2s var(--ease),background .2s var(--ease)}
.nx-svc:hover{transform:translateY(-2px);border-color:var(--hair-2);background:var(--raise-2)}
/* The list pin mirrors the map pin: magenta for a Forward Trust hub, navy for
   another local service, a hollow ring for something that is posted. Navy at
   full strength vanishes on the dark canvas (measured: it read as an empty
   ring), so the dark theme lightens the SAME token rather than introducing a
   second blue that would collide with the postal ring. */
.nx-svc-pin{width:11px;height:11px;border-radius:50%;flex-shrink:0;margin-top:6px;
  background:color-mix(in srgb,var(--primary-container) 52%,#FFFFFF);
  box-shadow:0 0 0 1px var(--hair-2)}
/* :not() on the modifiers, deliberately. Written as a bare
   `html[data-theme="light"] .nx-svc-pin` this sits at the same specificity as
   `.nx-svc-pin.ft` but LATER in the file, so it quietly repainted every
   Forward Trust hub navy in the light theme. Measured, not guessed. */
html[data-theme="light"] .nx-svc-pin:not(.ft):not(.post){background:var(--primary-container)}
.nx-svc-pin.ft{background:var(--secondary)}
.nx-svc-pin.post{background:transparent;box-shadow:inset 0 0 0 2px var(--cyan-soft)}
.nx-svc-tx{flex:1;min-width:0}
.nx-svc-n{display:block;font-size:15px;font-weight:600;line-height:1.3;margin-bottom:3px}
.nx-svc-a{display:block;font-size:13px;color:var(--ink-3)}
.nx-svc-d{flex:none;font-size:12.5px;font-weight:700;color:var(--ink-2);
  font-variant-numeric:tabular-nums;white-space:nowrap;padding-top:2px}
.nx-tag{display:inline-block;margin-top:7px;padding:3px 9px;border-radius:999px;font-size:10px;
  font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  background:rgba(181,37,85,.18);color:var(--secondary-soft)}
html[data-theme="light"] .nx-tag{background:#F8E4EC;color:var(--secondary)}
.nx-tag.post{background:rgba(0,119,200,.18);color:var(--cyan-soft)}
html[data-theme="light"] .nx-tag.post{background:#E6F2FA;color:var(--cyan)}

/* ---- a plain fact list with ticks --------------------------------------- */
.nx-facts{display:flex;flex-direction:column;gap:13px}
.nx-facts li{display:flex;gap:12px;align-items:flex-start;font-size:14.5px;line-height:1.5;
  color:var(--ink-2);list-style:none}
.nx-facts .t{width:22px;height:22px;border-radius:7px;flex-shrink:0;margin-top:1px;display:grid;
  place-items:center;background:rgba(0,164,153,.18);color:var(--teal-soft)}
html[data-theme="light"] .nx-facts .t{background:#DFF3F0;color:#0B7A6F}

/* ---- the search row (town or postcode, no geocoding service) ------------ */
.nx-find{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.nx-input{flex:1;min-width:190px;padding:13px 17px;border-radius:var(--r-sm);
  border:1px solid var(--hair-2);background:var(--raise);color:var(--ink);font:inherit;font-size:15px;
  transition:border-color .2s var(--ease)}
.nx-input::placeholder{color:var(--ink-3)}
.nx-input:focus{outline:none;border-color:var(--secondary)}
.nx-said{font-size:13px;color:var(--ink-3);margin-top:10px;min-height:1.3em}
.nx-said b{color:var(--ink-2)}
/* the retry, inline in the sentence that explains why it is there: a dead end
   is what "we could not get your location" used to be */
.nx-said-go{display:inline-block;margin-left:7px;padding:3px 11px;border-radius:999px;font-size:12px;
  font-weight:700;color:var(--ink);background:var(--raise-2);border:1px solid var(--hair-2);
  vertical-align:baseline;transition:background .16s var(--ease)}
.nx-said-go:hover{background:var(--raise)}

/* ---- the town picker ----------------------------------------------------
   A branded listbox, never <datalist> and never the browser's own autofill,
   for the same reason nothing here uses a native select. The wrapper exists
   because .nx-find is a flex row and the list needs a positioned parent; it
   takes over the input's own flex sizing. */
.nx-acw{position:relative;flex:1;min-width:190px;display:block}
.nx-acw>.nx-input{width:100%;min-width:0}
/* The picker switches its input to type=search to keep the browser's own
   autofill list off the top of ours (see nx-core.js). That type brings native
   decorations with it, and this app renders no browser UI: the clear cross,
   the results dropdown marker and the iOS inner shadow all go.
   ONE PER RULE, not a comma list. Chrome has dropped some of these pseudo
   elements, and a selector list containing a single unrecognised one throws
   the WHOLE rule away: grouped, the cancel cross stayed on screen and
   measured inline-block. */
.nx-acw>.nx-input[type="search"]{-webkit-appearance:none;appearance:none}
.nx-acw>.nx-input[type="search"]::-webkit-search-cancel-button{
  -webkit-appearance:none;appearance:none;display:none}
.nx-acw>.nx-input[type="search"]::-webkit-search-decoration{
  -webkit-appearance:none;appearance:none;display:none}
.nx-acw>.nx-input[type="search"]::-webkit-search-results-button{
  -webkit-appearance:none;appearance:none;display:none}
.nx-acw>.nx-input[type="search"]::-webkit-search-results-decoration{
  -webkit-appearance:none;appearance:none;display:none}
/* THE LIST'S OWN z-index IS NOT ENOUGH, and this cost an hour. In the
   pop-out, .nx-find carries a transform for the whole life of the sheet
   (the entrance animation's fill), and a transform makes an element a
   stacking context: the list's z-index then only orders it against its own
   siblings, so the results underneath painted straight over the top of it
   and swallowed every click. Lifting the ROW is what puts the list in
   front. Measured with elementFromPoint, not reasoned about. */
.nx-ac-lift{position:relative;z-index:20}
.nx-ac{position:absolute;left:0;right:0;top:calc(100% + 8px);z-index:30;margin:0;padding:6px;
  /* tall enough that the seven the picker offers all fit: a list clipped
     mid-row reads as broken rather than as scrollable */
  list-style:none;max-height:322px;overflow-y:auto;overscroll-behavior:contain;
  border-radius:var(--r-md);border:1px solid var(--hair-2);
  /* OPAQUE, not glass. A list that reads the page through itself is a list
     you cannot read: at --glass the "or" divider and the location button
     underneath came straight through the town names. Depth comes from the
     --raise wash and the shadow instead. */
  background:var(--canvas);
  background-image:linear-gradient(var(--raise-2),var(--raise-2));
  box-shadow:0 18px 44px rgba(0,0,0,.4),inset 0 1px 0 var(--glass-hi);
  opacity:0;transform:translateY(-6px);pointer-events:none;visibility:hidden;
  transition:opacity .16s var(--ease),transform .16s var(--ease),visibility 0s linear .16s}
/* .on carries the resting, visible style, so a blocked transition still
   shows the list rather than an invisible one that swallows clicks.
   visibility, not opacity alone: the list lives in the DOM the whole time and
   a screen reader would otherwise read a closed one. */
.nx-ac.on{opacity:1;transform:none;pointer-events:auto;visibility:visible;
  transition:opacity .16s var(--ease),transform .16s var(--ease),visibility 0s}
.nx-ac-o{display:flex;align-items:center;gap:12px;width:100%;padding:10px 12px;
  border-radius:10px;color:var(--ink);transition:background .14s var(--ease)}
.nx-ac-o:hover,.nx-ac-o.on{background:var(--raise-2)}
.nx-ac-o .pin{width:8px;height:8px;border-radius:50%;flex:none;background:var(--secondary);
  opacity:.7}
.nx-ac-o .n{flex:1;min-width:0;font-size:14.5px;font-weight:600;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.nx-ac-o .pc{flex:none;font-size:11.5px;font-weight:700;letter-spacing:.05em;color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.nx-ac mark{background:none;color:var(--secondary-soft);font-weight:800}
html[data-theme="light"] .nx-ac mark{color:var(--secondary)}
@media(prefers-reduced-motion:reduce){.nx-ac{transition:none;transform:none}}

/* ---- the map stage ------------------------------------------------------ */
.nx-stage{position:relative;border-radius:var(--r-xl);overflow:hidden;border:1px solid var(--hair);
  background:var(--raise);min-height:460px}
.nx-stage .gmap{position:absolute;inset:0}
.nx-stage-fb{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:11px;text-align:center;padding:30px;color:var(--ink-3)}
.nx-stage-fb b{font-family:var(--display);font-size:17px;color:var(--ink-2);font-weight:650}
.nx-stage-fb p{font-size:13.5px;max-width:290px}
.nx-legend{position:absolute;right:14px;bottom:14px;z-index:4;display:flex;flex-direction:column;
  gap:7px;padding:11px 14px;border-radius:var(--r-md);background:var(--glass);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);border:1px solid var(--hair-2);
  box-shadow:var(--shadow);font-size:12px;color:var(--ink-2)}
.nx-legend span{display:flex;align-items:center;gap:8px}
.nx-legend i{width:9px;height:9px;border-radius:50%;background:var(--primary-container);
  box-shadow:0 0 0 1px var(--hair-2)}
.nx-legend i.ft{background:var(--secondary);box-shadow:none}

/* ---- signs of an overdose ---------------------------------------------- */
.nx-signs{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px}
.nx-sign{padding:18px;border-radius:var(--r-md);background:var(--raise);border:1px solid var(--hair)}
.nx-sign b{display:block;font-size:15px;font-weight:650;margin-bottom:6px;line-height:1.3}
.nx-sign span{font-size:13.5px;color:var(--ink-2);line-height:1.5}
.nx-sign .k{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:9px;
  background:rgba(185,138,47,.2);color:#E7C476;font-size:12px;font-weight:700;margin-bottom:11px}
html[data-theme="light"] .nx-sign .k{background:#F8EED8;color:var(--amber)}

/* ---- the rescue clock, used by more than one concept ------------------- */
.nx-clock{display:flex;align-items:center;gap:16px;padding:16px 20px;border-radius:var(--r-md);
  background:var(--raise-2);border:1px solid var(--hair)}
.nx-clock b{font-family:var(--display);font-size:30px;font-weight:700;letter-spacing:-.04em;
  font-variant-numeric:tabular-nums;line-height:1}
.nx-clock span{font-size:12.5px;color:var(--ink-3);display:block;margin-top:3px}
.nx-clock .dose{margin-left:auto;text-align:right}
.nx-clock .dose b{font-size:22px;color:var(--ink-2)}
.nx-clock.due{border-color:rgba(185,138,47,.5);background:rgba(185,138,47,.14)}
.nx-clock.due .dose b{color:#E7C476}
html[data-theme="light"] .nx-clock.due .dose b{color:var(--amber)}
.nx-clock.over{border-color:rgba(180,35,24,.5);background:rgba(180,35,24,.14)}
.nx-clock.over .dose b{color:#FF9C93}
html[data-theme="light"] .nx-clock.over .dose b{color:#8E1A11}

.nx-steps{display:flex;flex-direction:column;gap:10px;list-style:none}
.nx-step{display:flex;gap:15px;align-items:flex-start;padding:16px 18px;border-radius:var(--r-md);
  background:var(--raise);border:1px solid var(--hair);
  transition:border-color .2s var(--ease),background .2s var(--ease)}
.nx-step .n{width:30px;height:30px;border-radius:50%;flex-shrink:0;display:grid;place-items:center;
  font-family:var(--display);font-size:14px;font-weight:700;background:var(--raise-2);
  color:var(--ink-3);box-shadow:0 0 0 1px var(--hair)}
.nx-step b{display:block;font-size:15.5px;font-weight:650;margin-bottom:4px}
.nx-step p{font-size:13.5px;color:var(--ink-2);line-height:1.5}
.nx-step.on{border-color:var(--secondary);background:rgba(181,37,85,.13)}
.nx-step.on .n{background:var(--secondary);color:#fff;box-shadow:none}
.nx-step.was{opacity:.55}
.nx-step.was .n{background:var(--teal);color:#fff;box-shadow:none}

/* ---- forms of naloxone -------------------------------------------------- */
.nx-forms{display:flex;gap:10px;flex-wrap:wrap;margin-top:12px}
.nx-form{display:inline-flex;align-items:center;gap:9px;padding:9px 14px;border-radius:999px;
  background:var(--raise-2);border:1px solid var(--hair);font-size:13px;font-weight:600;
  color:var(--ink-2)}
.nx-form .i{color:var(--cyan-soft);display:grid;place-items:center}
html[data-theme="light"] .nx-form .i{color:var(--cyan)}

/* ---- a quiet note under a section --------------------------------------- */
.nx-note{display:flex;gap:9px;align-items:flex-start;margin-top:16px;font-size:12.5px;
  color:var(--ink-3);line-height:1.5}
.nx-note svg{flex-shrink:0;margin-top:1px}
.nx-note a{color:var(--secondary-soft);font-weight:600}
html[data-theme="light"] .nx-note a{color:var(--secondary)}

/* ---- sheet internals shared by the concepts ----------------------------- */
.nx-sheet-wide{width:min(820px,100%)}
.sheet-body .nx-svc{background:var(--raise-2)}
.nx-sheet-h{font-family:var(--display);font-size:16px;font-weight:650;letter-spacing:-.015em;
  margin:22px 0 12px}
.sheet-body>.nx-sheet-h:first-child{margin-top:0}
.nx-kv{display:flex;flex-direction:column;gap:10px;margin-bottom:6px}
.nx-kv label{display:block;font-size:11.5px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-3);margin-bottom:7px}
.nx-kv .nx-input{width:100%}

/* Branded choice pills. NEVER a native select: the app does not use system UI. */
.nx-pick{display:flex;gap:8px;flex-wrap:wrap}
.nx-pick button{padding:11px 17px;border-radius:999px;background:var(--raise-2);
  border:1px solid var(--hair);font-size:14px;font-weight:600;color:var(--ink-2);
  transition:all .2s var(--bounce)}
.nx-pick button:hover{background:var(--hair);color:var(--ink)}
.nx-pick button[aria-pressed="true"]{background:rgba(0,164,153,.2);border-color:var(--teal);
  color:var(--teal-soft)}
html[data-theme="light"] .nx-pick button[aria-pressed="true"]{background:#DFF3F0;color:#0B7A6F}

/* ---- honest empty state -------------------------------------------------- */
.nx-empty{border:1px dashed var(--hair);border-radius:var(--r-lg);padding:34px;text-align:center;
  color:var(--ink-3);font-size:14px}

/* ---- the footer every concept ends on ------------------------------------ */
.nx-foot{margin-top:var(--section-gap);padding-top:26px;border-top:1px solid var(--hair);
  display:flex;flex-direction:column;gap:8px}
.nx-foot p{font-size:13px;color:var(--ink-3);line-height:1.5}
.nx-foot .lock{display:flex;align-items:center;gap:9px;font-size:14px;font-weight:600;
  color:var(--ink-2)}
.nx-foot a{color:var(--secondary-soft);font-weight:600}
html[data-theme="light"] .nx-foot a{color:var(--secondary)}

/* ==========================================================================
   THE RESCUE RAIL, and the widget that pulls it up
   A left-edge companion, deliberately NOT the house sheet. A sheet is a thing
   you opened and will close; this is a thing that stays open beside the page
   while you use it, which is what walking somebody through six steps actually
   needs. It lives on the LEFT because Rivo owns bottom-right and the tab bar
   owns bottom-centre.
   ========================================================================== */

/* the widget. It reads as a quiet pill until it is needed, and it says what
   it is FOR rather than what it is called. */
.nx-hail{position:fixed;left:20px;bottom:22px;z-index:57;display:flex;align-items:center;gap:12px;
  padding:12px 20px 12px 14px;border-radius:999px;background:var(--glass);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);border:1px solid var(--hair-2);
  box-shadow:var(--shadow-lg),inset 0 1px 0 var(--glass-hi);color:var(--ink);max-width:min(310px,72vw);
  transform-origin:0 100%;
  transition:transform .34s var(--bounce),opacity .24s var(--ease),background .22s var(--ease)}
.nx-hail:hover{background:var(--raise-2);transform:translateY(-2px)}
.nx-hail:active{transform:scale(.97)}
@media(max-width:900px){.nx-hail{left:12px;bottom:96px;padding:11px 16px 11px 12px}}
.nx-hail .pulse{width:34px;height:34px;border-radius:50%;flex-shrink:0;display:grid;place-items:center;
  background:var(--secondary);color:#fff;position:relative}
.nx-hail .pulse::after{content:'';position:absolute;inset:0;border-radius:50%;
  box-shadow:0 0 0 0 rgba(181,37,85,.55);animation:nxHail 3.4s var(--ease) infinite}
@keyframes nxHail{
  60%{box-shadow:0 0 0 12px rgba(181,37,85,0)}
  100%{box-shadow:0 0 0 0 rgba(181,37,85,0)}}
@media(prefers-reduced-motion:reduce){.nx-hail .pulse::after{animation:none}}
.nx-hail b{display:block;font-size:13.5px;font-weight:650;line-height:1.25}
.nx-hail span{display:block;font-size:11.5px;color:var(--ink-3);line-height:1.3;margin-top:2px}
.nx-hail .up{margin-left:4px;color:var(--ink-3);flex-shrink:0}
/* it does not compete with itself: while the rail is up, the widget is gone */
body.rail-open .nx-hail{opacity:0;pointer-events:none;transform:scale(.6) translateY(20px)}
body.sheet-open .nx-hail{opacity:0;pointer-events:none}

.nx-rail-scrim{position:fixed;inset:0;z-index:88;background:rgba(4,7,14,.5);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);opacity:0;pointer-events:none;
  transition:opacity .35s var(--ease)}
body.rail-open .nx-rail-scrim{opacity:1;pointer-events:auto}

.nx-rail{position:fixed;left:0;top:0;bottom:0;z-index:89;width:min(430px,100%);display:flex;
  flex-direction:column;transform:translateX(-101%);
  background:linear-gradient(178deg,#1B2440 0%,#141C31 46%,#0F1626 100%);
  -webkit-backdrop-filter:saturate(180%) blur(40px);backdrop-filter:saturate(180%) blur(40px);
  border-right:1px solid var(--hair-2);box-shadow:14px 0 52px rgba(0,0,0,.5);
  transition:transform .5s var(--spring);will-change:transform}
html[data-theme="light"] .nx-rail{background:linear-gradient(178deg,#FFFFFF,#F5F8FC)}
body.rail-open .nx-rail{transform:none}
/* The bar gives way to the rail, and the bottom-left "hail" widget gives way
   to the grown bar. Both rules live in nx-tabbar.css with the rest of the
   bar, so that what moves for what is decided in one place rather than in
   whichever stylesheet happened to be open. */

.nx-rail-head{padding:20px 22px 16px;border-bottom:1px solid var(--hair);flex-shrink:0}
.nx-rail-head .r{display:flex;align-items:flex-start;gap:14px}
.nx-rail-head h2{font-family:var(--display);font-size:20px;font-weight:700;letter-spacing:-.028em;
  line-height:1.2;flex:1;min-width:0}
.nx-rail-head p{font-size:12.5px;color:var(--ink-3);margin-top:5px;line-height:1.45}
/* THE STACK OWNS ITS OWN SPACING. Every block in here used to carry its own
   margin, and the clock carried none at all, so the 999 button, the clock and
   the current step sat welded together. A flex column with ONE gap cannot
   develop that gap-of-zero again as blocks are added or reordered.
   `display:flex` is not optional: `gap` does nothing on a block container,
   which is exactly how this went unnoticed. */
.nx-rail-body{flex:1;overflow-y:auto;padding:20px 22px 26px;
  display:flex;flex-direction:column;gap:18px}
/* the per-block margins the gap now replaces */
.nx-rail .nx-call,.nx-rail .nx-rail-now,.nx-rail .nx-rail-rest,.nx-rail .nx-note{margin:0}
.nx-rail-foot{padding:14px 22px calc(16px + env(safe-area-inset-bottom));
  border-top:1px solid var(--hair);display:flex;flex-wrap:wrap;gap:10px;flex-shrink:0}
/* 14px of inside padding, not the house 18px, and MEASURED rather than
   judged: "Is this an overdose?" is 135px of text, which needs 171px with
   18px sides and gets 168px here. Three pixels is why that label has been
   wrapping to two lines on a 390px phone since before there was a voice
   control to blame, and it is the only button on this host whose text is
   this close to its box. */
.nx-rail-foot .btn{flex:1;padding-left:14px;padding-right:14px}
.nx-rail .nx-call{width:100%;justify-content:center}

/* the current step gets the room; the rest collapse to a line you can jump to */
/* THE STEP CARD, and the voice control's host. The rail has no orb and no
   mover of its own, so the exercise IS this card, and position:relative is
   here, on the component, rather than in vx-voice.css reaching in to set it.
   The control took its own full width row in .nx-rail-foot before, because
   three items would not fit across a 430px rail; the foot is back to its two
   actions now.
   Top right clears everything the card can draw: .k is a short pill at the top
   LEFT, and h3 starts below it. Measured at 390px, where the rail is the full
   width of the screen and the card is at its narrowest. */
.nx-rail-now{position:relative;padding:20px;border-radius:var(--r-lg);background:var(--raise);
  border:1px solid var(--hair-2);margin-bottom:14px}
.nx-rail-now > .vx-orb{top:12px;right:12px}
.nx-rail-now .k{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;
  background:rgba(181,37,85,.2);color:var(--secondary-soft);font-size:10.5px;font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;margin-bottom:12px}
html[data-theme="light"] .nx-rail-now .k{background:#F8E4EC;color:var(--secondary)}
.nx-rail-now h3{font-family:var(--display);font-size:23px;font-weight:700;letter-spacing:-.03em;
  line-height:1.15;margin-bottom:9px}
.nx-rail-now p{font-size:14.5px;line-height:1.55;color:var(--ink-2);margin-bottom:16px}
.nx-rail-now .acts{display:flex;gap:9px;flex-wrap:wrap}
.nx-rail-rest{display:flex;flex-direction:column;gap:2px}
.nx-rail-rest button{display:flex;align-items:center;gap:12px;width:100%;padding:11px 12px;
  border-radius:var(--r-sm);font-size:13.5px;color:var(--ink-3);
  transition:background .2s var(--ease),color .2s var(--ease)}
.nx-rail-rest button:hover{background:var(--raise-2);color:var(--ink-2)}
.nx-rail-rest .n{width:22px;height:22px;border-radius:50%;flex-shrink:0;display:grid;
  place-items:center;font-size:11px;font-weight:700;background:var(--raise-2);
  box-shadow:0 0 0 1px var(--hair)}
.nx-rail-rest .was{color:var(--ink-2)}
.nx-rail-rest .was .n{background:var(--teal);color:#fff;box-shadow:none}

/* ---- printing ------------------------------------------------------------
   A "print it" button that prints a photographic hero, a floating tab bar and
   a design-concept banner has not printed anything useful. Chrome goes, dark
   surfaces go white so it does not drink a cartridge, and a page can opt to
   print ONE element by putting .nx-print-only on it. */
@media print{
  /* Re-point the TOKENS rather than overriding component by component, so
     anything built on the sheet prints light without a second stylesheet.
     Setting body{background:#fff} alone was not enough: .shell paints
     --canvas over it, so the page printed dark-on-dark. Measured. */
  /* :root, NOT html. `html` is a type selector at (0,0,1) and :root is a
     pseudo-class at (0,1,0), so an `html{...}` block here loses to the sheet's
     own :root and every token stayed at its dark value. */
  :root{--canvas:#FFFFFF;--raise:#FFFFFF;--raise-2:#F5F7FA;
    --hair:#D8DDE6;--hair-2:#C2CAD8;
    --ink:#111827;--ink-2:rgba(17,24,39,.72);--ink-3:rgba(17,24,39,.5);
    --glass:#FFFFFF;--hero-glass:#FFFFFF;--shadow:none;--shadow-lg:none}
  .topbar,.tabbar,.live-banner,.backdrop,.opener,.nx-999,.nx-note,.nx-foot,
  .nx-hail,.nx-rail,.nx-rail-scrim,.sec-head .show-all{
    display:none !important}
  .shell{transform:none !important;filter:none !important;background:#fff !important}
  body{background:#fff !important;color:#111827 !important}
  .page{padding:0 !important;max-width:none !important}
  .sheet{position:static !important;transform:none !important;max-height:none !important;
    width:100% !important;background:#fff !important;border:0 !important;box-shadow:none !important}
  .sheet-foot,.sheet-head .close-btn,.grabber{display:none !important}
  section+section{margin-top:0 !important}
  body.nx-print-card main>section:not(.nx-print-only){display:none !important}
}

/* Content must never depend on an animation to be seen: the resting style is
   visible and the hidden state lives in the `from` keyframe. */
@keyframes nxRise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.nx-rise{animation:nxRise .55s var(--spring) both}
@media(prefers-reduced-motion:reduce){.nx-rise{animation:none}}
