/* Attribution Lab - components
   topbar, hero, chips, segmented toggles, journey map, node cards,
   drawer (desktop) / sheet (mobile), tables, banner, tours */

/* ---------------------------------------------------------------- base */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* Notched iPhones (#22). The pages ask for viewport-fit=cover, so iOS reports
   real safe-area insets: the bottom inset keeps the sheet above the home
   indicator and the Safari toolbar, the side insets keep content off the notch
   in landscape. Everywhere else env() is 0 and --pad-x stays 32px / 16px
   (tokens.css), so desktop layout and the e2e measurements do not move. */
:root { --pad-x: max(32px, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); }
@media (max-width: 767px) {
  :root { --pad-x: max(16px, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--accent-text); text-decoration: none; }
a:hover { color: var(--accent); }
a.plain { color: inherit; }

h1, h2, h3, h4 { margin: 0; text-wrap: pretty; }
h1 { font-size: 32px; line-height: 1.15; font-weight: 600; letter-spacing: -0.015em; }
h2 { font-size: 18px; line-height: 1.3; font-weight: 600; letter-spacing: -0.01em; }
h3 { font-size: 15px; line-height: 1.3; font-weight: 600; }
p { margin: 0; }

button { font-family: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.mono { font-family: var(--font-mono); }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.nowrap { white-space: nowrap; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}

.sub {
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 640px;
  text-wrap: pretty;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
}

.sect-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.sect-head .hint { font-size: 12px; color: var(--muted); }

.ico { width: 16px; height: 16px; flex: none; }

/* --------------------------------------------------------------- chips */

.chip {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 1px solid;
  white-space: nowrap;
  transition: background-color var(--t-base) ease, color var(--t-base) ease, border-color var(--t-base) ease;
}
.chip.known { color: var(--known-text); background: var(--known-bg); border-color: var(--known-border); }
.chip.linked { color: var(--linked-text); background: var(--linked-bg); border-color: var(--linked-border); }
.chip.inferred { color: var(--inferred-text); background: var(--inferred-bg); border-color: var(--inferred-border); }
.chip.unknown { color: var(--unknown-text); background: var(--unknown-bg); border-color: var(--unknown-border); }
.chip.pending { color: var(--pending-text); background: var(--pending-bg); border-color: var(--pending-border); }

.legend { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
  background: var(--subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  padding: 4px 8px;
  white-space: nowrap;
}

.reason {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--subtle);
  font-size: 12.5px;
  color: var(--muted);
}

/* ------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: var(--h-ctl);
  padding: 0 14px;
  border-radius: var(--r-ctl);
  font-size: 13.5px;
  font-weight: 500;
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-fast) ease, border-color var(--t-fast) ease;
}
.btn:hover { background: var(--subtle); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #FFFFFF; }
.btn.primary:hover { background: var(--accent-text); border-color: var(--accent-text); }
.btn.sm { height: 30px; padding: 0 10px; font-size: 12.5px; }
.btn.ghost { border-color: transparent; background: transparent; color: var(--muted); }
.btn.ghost:hover { background: var(--subtle); color: var(--text); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-ctl);
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.iconbtn:hover { background: var(--subtle); color: var(--text); }

.chipbtn {
  height: var(--h-chip);
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-fast) ease, border-color var(--t-fast) ease, color var(--t-fast) ease;
}
.chipbtn:hover { background: var(--subtle); }
.chipbtn.on {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-text);
  font-weight: 500;
}

.chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.chips .chips-label { font-size: 13px; color: var(--muted); margin-right: 4px; }

.input {
  height: var(--h-ctl);
  width: 100%;
  min-width: 0;
  border: 1px solid var(--border-2);
  border-radius: var(--r-ctl);
  background: var(--surface);
  padding: 0 12px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text);
}
.input::placeholder { color: var(--faint); }
.input.sans { font-family: var(--font-sans); }

.field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.field > label { font-size: 12px; font-weight: 500; color: var(--muted); }

.formnote { font-size: 12px; line-height: 1.45; color: var(--muted); }
.formnote.warn { color: var(--inferred-text); }
.formnote.err { color: #B91C1C; }

/* -------------------------------------------------------------- topbar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: var(--h-topbar);
  padding: 0 var(--pad-x);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.topbar-left { display: flex; align-items: center; gap: 32px; min-width: 0; }
.topbar-right { display: flex; align-items: center; gap: 12px; }

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.01em;
  color: var(--text);
  white-space: nowrap;
}
.brand .mark {
  width: 22px; height: 22px;
  border-radius: var(--r-ctl);
  background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.brand .suffix { color: var(--faint); font-weight: 400; }

.nav { display: flex; gap: 22px; font-size: 13.5px; color: var(--muted); }
.nav a { color: var(--muted); }
.nav a.on { color: var(--text); font-weight: 500; }

.menubtn { display: none; }

/* ---------------------------------------------------------------- page */

.page {
  padding: 16px var(--pad-x) 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  /* the inset: the collapsed bar stands on it, see .wb.min */
  padding-bottom: calc(var(--drawer-h) + 28px + env(safe-area-inset-bottom, 0px));
}

.hero {
  display: flex;
  gap: 32px;
  align-items: flex-start;
}
.hero-main { display: flex; flex-direction: column; gap: 12px; min-width: 0; flex: 1; }
.hero-aside { width: 400px; flex: none; }

.controls {
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.seglabel {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 6px;
  display: flex;
  justify-content: space-between;
  gap: 10px;
}
.seglabel .mono { font-weight: 400; }
.seg {
  display: flex;
  background: var(--subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 3px;
}
.segbtn {
  flex: 1;
  height: 34px;
  border: 0;
  background: transparent;
  border-radius: var(--r-ctl);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--muted);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, color var(--t-fast) ease;
}
.segbtn.on { background: var(--surface); color: var(--text); box-shadow: var(--shadow-seg); }
/* where the regime came from, under its toggle: "EU · by IP (DE)" */
.regimebasis { margin-top: 6px; }
/* Where the two toggles sit side by side their blocks are bottom-aligned, and
   the extra line would lift the regime toggle out of line with the transport
   toggle, so there the blocks align by their tops. Stacked layouts keep
   stretching, and the booking-mode row is left as it is. */
@media (min-width: 768px) {
  .controls.wide:not(.bkmode) > .segblock { align-self: flex-start; }
}
@media (min-width: 768px) and (max-width: 1180px) {
  .controls:not(.wide) > .segblock { align-self: flex-start; }
}
/* two word options like "Redirect back" wrapped to a second line and broke the
   strip's height, which is what made the row overflow its container */
.segbtn { white-space: nowrap; }

/* toggles laid out in a row, used on Site B where vertical space is tight */
.controls.wide { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 16px 28px; }
.controls.wide > .segblock { flex: 0 1 280px; min-width: 220px; }
.controls.wide > .hint { flex: 1 1 240px; margin: 0; }

/* inline notice strip (US regime), never covers content */
.notice {
  display: none;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  font-size: 12.5px;
  color: var(--muted);
}
.notice.show { display: flex; }
.notice .spacer { margin-left: auto; }

.hide-sm { display: inline; }
.show-sm { display: none; }
.mobhead {
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 16px 0;
  font-size: 12.5px;
}

.utmform {
  display: none;
  gap: 8px;
  align-items: flex-end;
  flex-wrap: wrap;
  padding: 12px 14px;
  border: 1px dashed var(--border-2);
  border-radius: var(--r-card);
  background: var(--surface);
}
.utmform.open { display: flex; }
.utmform .field { width: 150px; }

/* --------------------------------------------------------- journey map */

.mapcard { padding: 14px 20px 16px; }
.maphead {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  /* The 14px that used to sit here moved into .jmap's padding-top, see below.
     On mobile the media query puts it back, because .jmap is not displayed there. */
  margin-bottom: 0;
  flex-wrap: wrap;
}

/* padding-top, issue #20: the pulse ring around the current node is drawn outside
   its dot (.jpulse is inset -6px and scales to 1.5), which puts its top edge about
   15px above the dot. .jmap needs overflow-x for the horizontal scroll, and CSS
   computes overflow-y to auto whenever overflow-x is not visible - so a container
   asked to scroll sideways also clipped the ring flat at the top. The row now
   carries the headroom the ring needs; the 14px taken off .maphead above keeps the
   map where it was on screen. The connectors keep their alignment because padding
   moves every child of the row, dots and lines alike. */
.jmap { display: flex; align-items: flex-start; overflow-x: auto; padding-top: 16px; padding-bottom: 4px; }
.jmap-v { display: none; }

.jnode {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 104px;
  flex: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  border-radius: var(--r-ctl);
}
.jnode:hover .jlabel { color: var(--accent-text); }

.jdot {
  width: 36px; height: 36px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--border-2);
  background: var(--surface);
  position: relative;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  transition: background-color var(--t-base) ease, border-color var(--t-base) ease;
}
.jnode.done .jdot { background: var(--known-text); border-color: var(--known-text); color: #FFFFFF; }
.jnode.current .jdot { background: var(--accent); border-color: var(--accent); color: #FFFFFF; }
.jnode.lost .jdot { background: var(--subtle); border-color: var(--border-2); color: var(--faint); }
.jnode.on .jlabel { color: var(--accent-text); text-decoration: underline; text-underline-offset: 3px; }

.jpulse {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0.5;
  animation: al-pulse 1.8s ease-out infinite;
  pointer-events: none;
}
@keyframes al-pulse {
  0% { transform: scale(0.8); opacity: 0.6; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* Issue #20, the mobile half (checklist B2). Rows of the vertical map sit flush
   against each other and the dot is pinned to the top of its own row, so a ring
   that grows outside the dot has nowhere to go but over the row above - it was
   painting across the Consent line. Nothing here is clipped, so the fix is not
   headroom but reach: on the vertical map the ring breathes inside the dot
   instead of outside it. Same element, same rhythm, no overlap. */
.vmap .jpulse {
  inset: 0;
  animation-name: al-pulse-in;
}
@keyframes al-pulse-in {
  0% { transform: scale(0.5); opacity: 0.75; }
  100% { transform: scale(1); opacity: 0; }
}

.jlabel { font-size: 13px; font-weight: 500; text-align: center; line-height: 1.2; }
.jsub { font-size: 11px; color: var(--muted); text-align: center; }

.jline {
  flex: 1;
  height: 2px;
  background: var(--border-2);
  margin-top: 17px;
  min-width: 18px;
  transition: background-color var(--t-slow) ease;
}
.jline.done { background: var(--known-text); }
.jline.dash { background: repeating-linear-gradient(90deg, var(--border-2) 0 6px, transparent 6px 12px); }

.jbranch { display: flex; flex-direction: column; gap: 8px; width: 120px; flex: none; }
.jmini {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 500;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  border-radius: var(--r-ctl);
}
.jmini:hover { color: var(--accent-text); }
.jmini { position: relative; }
.jmini .jmsub {
  position: absolute;
  left: 34px;
  top: 100%;
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
  white-space: nowrap;
  pointer-events: none;
}
.jmini .jdot { width: 26px; height: 26px; font-size: 10px; }

/* vertical map (mobile) */
.vmap { display: flex; flex-direction: column; }
.vrow {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
}
.vrail { width: 36px; display: flex; flex-direction: column; align-items: center; flex: none; align-self: stretch; }
.vrail .jdot { width: 28px; height: 28px; font-size: 11px; }
.vline { width: 2px; flex: 1; min-height: 8px; background: var(--border-2); }
.vline.done { background: var(--known-text); }
.vline.dash { background: repeating-linear-gradient(180deg, var(--border-2) 0 5px, transparent 5px 10px); }
.vtext { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vtext .t { font-size: 13.5px; font-weight: 500; }
.vtext .s { font-size: 11.5px; color: var(--muted); }
.vrow .chip { margin-left: auto; }

/* ----------------------------------------------------------- node card */

.ncard-wrap { display: none; }
.ncard-wrap.open { display: block; }

.ncard-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.ncard-head strong { font-size: 13.5px; }
.ncard-head .lede { font-size: 12.5px; color: var(--muted); }
.ncard-head .actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.ncard {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.ncol { padding: 14px 18px; border-right: 1px solid var(--border); }
.ncol:last-child { border-right: 0; }
.ncol h4 {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.ncol p { font-size: 13.5px; line-height: 1.5; }

/* the extra step under the three columns, only on the node that carries it */
.nroads { padding: 14px 18px; border-top: 1px solid var(--border); background: var(--subtle); }
.nroads h4 {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.nroads p { font-size: 13.5px; line-height: 1.5; max-width: 860px; }
.ncol .mono { font-size: 12.5px; }

/* ---------------------------------------------------- cross-site strip */

.crossbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  flex-wrap: wrap;
}
.crossbar .txt { font-size: 13.5px; color: var(--muted); min-width: 0; flex: 1; }
.crossbar .txt strong { color: var(--text); font-weight: 600; }

/* ----------------------------------------------------- top state (B) */

.topstate { padding: 14px 20px; border-color: var(--border-2); }
.topstate-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 28px;
  align-items: start;
}
.topstate-main { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.topstate-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.topstate p.body { font-size: 13.5px; line-height: 1.5; color: #57534E; max-width: 760px; text-wrap: pretty; }
.topstate-aside { display: flex; flex-direction: column; gap: 10px; }
.topstate-aside .lbl { font-size: 12.5px; font-weight: 500; }
.restore-row { display: flex; gap: 8px; }
.restore-row .input { flex: 1; text-transform: uppercase; }

.checklist { display: flex; flex-direction: column; gap: 5px; margin: 2px 0 0; padding: 0; list-style: none; }
.checklist li { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; line-height: 1.4; }

.factgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px 24px;
  margin-top: 2px;
}
.fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fact .k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); font-weight: 600; }
.fact .v { font-family: var(--font-mono); font-size: 12.5px; overflow-wrap: anywhere; }

/* --------------------------------------------------------------- tours */

.tourgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.tour { display: flex; flex-direction: column; overflow: hidden; }
.tour img {
  display: block;
  width: 100%;
  height: 148px;
  object-fit: cover;
  border-bottom: 1px solid var(--border);
  background: var(--subtle);
}
.tourbody { padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.tourrow { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.tourrow strong { font-size: 13.5px; }
.tourrow .price { font-family: var(--font-mono); font-size: 12.5px; }
.tourrow .meta { font-size: 12px; color: var(--muted); }
.tourbtns { display: flex; gap: 6px; }

/* -------------------------------------------------------------- banner */

.banner {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--drawer-h) + 14px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  width: min(880px, calc(100% - 24px - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)));
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  padding: 14px 18px;
  display: none;
  gap: 18px;
  align-items: center;
}
.banner.show { display: flex; }
.banner .btext { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 4px; }
.banner .btitle { font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.banner .bbody { font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.banner .bbtns { display: flex; gap: 8px; flex: none; }
/* the small US notice sits out of the way, bottom right */
.banner.slim {
  left: auto;
  right: 16px;
  transform: none;
  width: auto;
  max-width: min(560px, calc(100% - 32px));
  padding: 10px 14px;
}

/* -------------------------------------------------------------- drawer */

.wb {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  height: var(--drawer-h);
  background: var(--surface);
  border-top: 1px solid var(--border-2);
  box-shadow: var(--shadow-drawer);
  display: flex;
  flex-direction: column;
}
.wb.animate { transition: height var(--t-base) ease; }
/* landscape on a notched phone: tabs and panels stay off the notch */
.wb { padding-left: env(safe-area-inset-left, 0px); padding-right: env(safe-area-inset-right, 0px); }

/* Issue #22 (a). The whole header row is the drag zone (bindDrag in lab.js).
   A drag starts only after the pointer has moved 8 px up or down, so a tap on
   a tab or a button stays a tap. pan-x leaves the sideways scroll of the tab
   row to the browser and keeps a vertical swipe here from scrolling the page. */
.wbhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: var(--h-tabs);
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
  position: relative;
  flex: none;
  touch-action: pan-x;
  -webkit-user-select: none;
  user-select: none;
}
/* The handle is a layer under the tabs and buttons that fills the header, so
   its touch target is the full row height (44 px) and every free spot of the
   row, the whole collapsed bar included, while the controls on top keep their
   own taps. It used to be a 44x6 px strip over the top edge of the middle tab.
   The grip line is ::after, at the top centre where it was. */
.wbhandle {
  position: absolute;
  /* -1px: over the header's bottom border too, so the target is the full 44 px */
  top: 0; right: 0; bottom: -1px; left: 0;
  z-index: 0;
  width: auto; height: auto;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: ns-resize;
  touch-action: none;
}
.wbhandle::after {
  content: '';
  position: absolute;
  top: 4px;
  left: 50%;
  width: 44px; height: 4px;
  margin-left: -22px;
  border-radius: 2px;
  background: var(--border-2);
}
.wbhandle:hover::after { background: var(--faint); }
.wbtabs, .wbtask, .wbright { position: relative; z-index: 1; }

.wbtabs { display: flex; gap: 2px; align-items: center; height: 100%; overflow-x: auto; scrollbar-width: none; }
.wbtabs::-webkit-scrollbar { display: none; }
.wbtab {
  padding: 0 12px;
  height: var(--h-tabs);
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
}
.wbtab.on { color: var(--text); font-weight: 500; border-bottom-color: var(--accent); }
.tabcount {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: #FFFFFF;
  font-size: 11px;
  font-weight: 600;
}

.wbright { display: flex; align-items: center; gap: 8px; color: var(--muted); }
.wbright .lnk {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; color: var(--muted);
  background: none; border: 0; cursor: pointer; padding: 4px 6px; border-radius: var(--r-ctl);
}
.wbright .lnk:hover { background: var(--subtle); color: var(--text); }
/* "Show what was recorded": the collapsed drawer's one labelled way back in */
.wbright .wbopen { display: none; }
.wb.min .wbright .wbopen { display: inline-flex; }

.wbbody { flex: 1; min-height: 0; display: flex; }
.wbpanel { flex: 1; min-height: 0; min-width: 0; display: none; }
.wbpanel.on { display: flex; }

.wbcols {
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr) 430px;
  flex: 1;
  min-height: 0;
  width: 100%;
}
/* Issue #22 (b). The bottom padding of the scroll containers adds the
   safe-area inset, so the last row can be scrolled up past the home indicator,
   where the floating Safari address bar also sits. */
.wbcol { padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px)); border-right: 1px solid var(--border); overflow: auto; min-width: 0; }
.wbcol:last-child { border-right: 0; }
.wbfull { padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px)); overflow: auto; flex: 1; min-width: 0; }

.wbtitle {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}
.wbtitle .sub2 { text-transform: none; letter-spacing: 0; font-weight: 400; }

.sumrow { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; line-height: 1.35; padding: 5px 0; }
.sumrow .k { color: var(--muted); }
.sumrow .ico { margin-top: 1px; }

.kv {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  row-gap: 6px;
  column-gap: 12px;
  font-size: 12.5px;
  align-items: center;
}
.kv .k { color: var(--muted); }
.kv .v { font-family: var(--font-mono); font-size: 12px; overflow-wrap: anywhere; }
.kv .v.trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ev {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) 52px;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 5px 0;
  border-bottom: 1px solid var(--subtle);
  align-items: baseline;
}
.ev .t { color: var(--muted); }
.ev .n { overflow-wrap: anywhere; }
.ev .n .dot { color: var(--faint); }
.ev .s { text-align: right; color: var(--known-text); }
.ev .s.mut { color: var(--muted); }
.ev .s.err { color: #B91C1C; }
.ev.cli .t { color: var(--accent-text); }

.evfilter { display: flex; gap: 6px; align-items: center; }
.evfilter .chipbtn { height: 26px; font-size: 12px; padding: 0 10px; }

/* ------------------------------------- two roads per hit (stage v2) */

/* summary strip on top of the Events tab: direct road, server road, loader */
.hitsum { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 8px; }
.hitsum .sep { color: var(--faint); }
.sumchip {
  height: 24px;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  background: var(--subtle);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 11.5px;
  cursor: pointer;
  white-space: nowrap;
}
.sumchip:hover { border-color: var(--border-2); }
.sumchip.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); }
.whyline { margin-bottom: 8px; }
.roadnote { margin-top: 8px; }
.evtitle, .jsontitle { margin-top: 16px; }

.hit {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) auto;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 6px 0;
  border-bottom: 1px solid var(--subtle);
  align-items: baseline;
}
.hit .t { color: var(--accent-text); }
.hit .n { overflow-wrap: anywhere; }
.hit .paths { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.hit .why {
  grid-column: 1 / -1;
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
}

.chip.pathchip { margin: 0; cursor: pointer; }
.chip.pathchip.on { box-shadow: 0 0 0 1px var(--accent); }
.chip.pathchip.ok { color: var(--known-text); background: var(--known-bg); border-color: var(--known-border); }
.chip.pathchip.wait { color: var(--pending-text); background: var(--pending-bg); border-color: var(--pending-border); }
.chip.pathchip.na { color: var(--unknown-text); background: var(--unknown-bg); border-color: var(--unknown-border); }
.chip.pathchip.bad { color: #B91C1C; background: #FEF2F2; border-color: #FECACA; }

.emptystate {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px;
  border: 1px dashed var(--border-2);
  border-radius: var(--r-card);
  color: var(--muted);
  font-size: 13px;
  max-width: 620px;
}
.emptystate strong { color: var(--text); font-size: 13.5px; }

.json {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre;
  overflow: auto;
  background: var(--subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  padding: 12px;
}

table.tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.tbl th {
  text-align: left;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
  padding: 6px 10px 6px 0;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.tbl td {
  padding: 7px 10px 7px 0;
  border-bottom: 1px solid var(--subtle);
  vertical-align: top;
  line-height: 1.4;
}
table.tbl td.mono { font-family: var(--font-mono); font-size: 12px; }

.cmdlist { display: flex; flex-direction: column; gap: 4px; font-family: var(--font-mono); font-size: 11.5px; }
.cmdlist .cmd { background: var(--subtle); border: 1px solid var(--border); border-radius: 4px; padding: 5px 8px; overflow-wrap: anywhere; }

.stack { display: flex; flex-direction: column; gap: 14px; }
.stack.tight { gap: 8px; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* minimised drawer (taskbar) */
.wb.min .wbbody { display: none; }
.wb.min .wbhandle { cursor: pointer; }
.wb.min .wbhead { height: var(--drawer-min); border-bottom: 0; }
.wb.min .wbtabs { display: none; }
.wb.min .wbtask { display: flex; }
.wb.min #al-status-chip { display: none; }
/* The bar is the lowest thing on screen, so it stands on the safe-area inset
   instead of under it. env() is 0 where there is no inset, and on iOS until
   the page opts in with viewport-fit=cover. */
.wb.min {
  height: calc(var(--drawer-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.wbtask {
  display: none;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
  color: var(--muted);
  min-width: 0;
  overflow: hidden;
  /* nothing here is a control: a tap falls through to the handle and opens */
  pointer-events: none;
}
.wbtask .jid { font-family: var(--font-mono); font-size: 12px; color: var(--text); white-space: nowrap; }
.wbtask .tick {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--accent-text);
  animation: al-fade var(--t-slow) ease;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@keyframes al-fade { from { opacity: 0; } to { opacity: 1; } }

/* -------------------------------------------------------------- footer */

.pagefoot {
  display: flex;
  gap: 10px 24px;
  flex-wrap: wrap;
  align-items: center;
  padding: 8px 0 20px;
  font-size: 12px;
  color: var(--muted);
}

/* ------------------------------------------------------------- stub page */

.stub {
  max-width: 680px;
  margin: 0 auto;
  padding: 72px var(--pad-x) 64px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.stub .card { padding: 18px 20px; display: flex; flex-direction: column; gap: 10px; }

/* --------------------------------------------------------- responsive */

@media (max-width: 1180px) {
  .hero { flex-direction: column; gap: 16px; }
  .hero-aside { width: 100%; }
  .controls { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
  .controls > .segblock { flex: 1; min-width: 220px; }
  .controls > .hint { flex-basis: 100%; }
  .wbcols { grid-template-columns: 220px minmax(0, 1fr) 360px; }
  .topstate-grid { grid-template-columns: minmax(0, 1fr) 320px; gap: 20px; }
}

@media (max-width: 980px) {
  .wbcols { grid-template-columns: 240px minmax(0, 1fr); }
  .wbcols .wbcol.events { display: none; }
  .ncard { grid-template-columns: 1fr; }
  .ncol { border-right: 0; border-bottom: 1px solid var(--border); }
  .ncol:last-child { border-bottom: 0; }
  .tourgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .topstate-grid { grid-template-columns: 1fr; }
}

@media (max-width: 767px) {
  h1 { font-size: 22px; }
  h2 { font-size: 16px; }
  .sub { font-size: 14px; }
  .nav { display: none; }
  .hide-sm { display: none; }
  .show-sm { display: flex; }
  #al-status-chip { display: none; }
  .brand .suffix { display: none; }
  .topbar { padding: 0 12px; gap: 8px; }
  .topbar-left { gap: 0; min-width: 0; }
  .topbar-right { gap: 8px; min-width: 0; }
  .topbar-right .badge.tags { display: none; }
  .topbar-right .btn.reset { height: 34px; padding: 0 10px; font-size: 12.5px; }

  .controls, .controls.wide { flex-direction: column; align-items: stretch; gap: 10px; }
  .controls > .segblock, .controls.wide > .segblock { flex: 1 1 auto; min-width: 0; }
  .controls > .hint, .controls.wide > .hint { flex: 1 1 auto; min-width: 0; }

  .page { gap: 12px; }
  .hero-main { gap: 10px; }
  .chips .chips-label { flex-basis: 100%; margin: 0 0 -2px; }
  .chipbtn { height: 36px; }
  .utmform .field { width: 100%; }

  .jmap { display: none; }
  .jmap-v { display: block; }
  .mapcard { padding: 12px 14px; }
  .maphead { margin-bottom: 8px; }
  .maphead .legend { display: none; }

  .tourgrid { grid-template-columns: 1fr; }
  .tour img { height: 160px; }

  .banner { bottom: calc(var(--drawer-h) + 10px + env(safe-area-inset-bottom, 0px)); flex-direction: column; align-items: stretch; gap: 10px; }
  .banner.slim { left: 12px; right: 12px; max-width: none; }
  .banner .bbtns .btn { flex: 1; height: 44px; }

  .wb {
    border-radius: 14px 14px 0 0;
    border-top: 1px solid var(--border-2);
    box-shadow: var(--shadow-sheet);
  }
  .wbhead { padding: 0 8px; gap: 6px; }
  /* 6 px, a 4 px gap and a smaller count: at 390 px the five tabs, a two digit
     Events count, Copy link and minimise share one row without cutting Consent */
  .wbtab { padding: 0 6px; gap: 4px; font-size: 12.5px; }
  /* Russian tab names are 8 px wider in total: the row has to fit before the copy icon */
  html[lang="ru"] .wbtab { padding: 0 4px; }
  .tabcount { min-width: 16px; height: 16px; padding: 0 4px; font-size: 10.5px; }
  .wbright { gap: 4px; }
  /* Copy link in its compact form, the icon alone. The status chip stays off
     the header: at 390 px the five tabs and the Events count leave no room for
     it, and it is on the first row of the Journey tab and on the collapsed bar. */
  .wbright .lnk span { display: none; }
  /* the collapsed bar keeps the 44 px of the tab row, a full touch target */
  .wb.min { height: calc(var(--h-tabs) + env(safe-area-inset-bottom, 0px)); }
  .wb.min .wbhead { height: var(--h-tabs); }
  /* and holds the journey, its status, the labelled button and minimise: the
     event ticker and Copy link wait for the open drawer, and the grip line
     would sit under the button */
  .wb.min .wbtask .tick, .wb.min .wbright .lnk, .wb.min .wbhandle::after { display: none; }
  .wbcols { display: flex; flex-direction: column; grid-template-columns: none; overflow: auto; }
  .wbcol { border-right: 0; border-bottom: 1px solid var(--border); overflow: visible; }
  .wbcol:last-child { border-bottom: 0; }
  /* the columns stack in one scroll container, so only the last one needs the inset */
  .wbcols .wbcol { padding-bottom: 14px; }
  .wbcols .wbcol:last-child { padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  .wbcols .wbcol.events { display: block; }
  .kv { grid-template-columns: 104px minmax(0, 1fr); }
  .ev { grid-template-columns: 54px minmax(0, 1fr) 44px; }
  .hit { grid-template-columns: 54px minmax(0, 1fr); }
  .hit .paths { grid-column: 2; justify-content: flex-start; }
  .hitsum { gap: 5px; }
  .hitsum .sep { display: none; }
  .sumchip { white-space: normal; height: auto; min-height: 26px; padding: 4px 8px; text-align: left; }
  .crossbar .btn { width: 100%; }
  .restore-row .btn { height: 44px; }
  .btn { height: 40px; }
  .btn.sm { height: 34px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .jpulse { display: none; }
}

/* ------------------------------------------------ booking (stage 3) */

/* branch minis carry a status once a booking has been joined */
.jmini.done .jdot { background: var(--known-text); border-color: var(--known-text); color: #FFFFFF; }
.jmini.done .jdot .ico { width: 14px; height: 14px; }
.jmini .chip { height: 18px; padding: 0 5px; font-size: 10px; }
/* .jbranch is a fixed 120px column. Dot plus label plus a LINKED chip is wider
   than that, and the overflow painted straight over the dashed timeline to the
   right. Wrap the chip onto its own line, indented past the dot, so it reads the
   way the chips under the other nodes do. */
.jmini { flex-wrap: wrap; }
.jmini .chip { margin-left: 34px; }

/* platform behaviour selector, above the tour grid: five options, best first.
   The container is <div class="card controls wide bkmode">, so .controls.wide >
   .segblock (0,3,0) used to outrank a plain .bkmode > .segblock (0,2,0) even
   though the latter is declared later and aims at this exact block. The wrapper
   got 280px instead of 420px while .seg kept min-width 360px, so a five button
   strip sat 80px wider than its box and, with gap 28px, painted over the hint
   next to it. The fifth option, No signal, ended up unclickable. Repeating
   .controls.wide here raises this to (0,4,0) and settles it. */
.bkmode { padding: 10px 16px; }
.controls.wide.bkmode { gap: 16px 20px; }
.controls.wide.bkmode > .segblock { flex: 1 1 420px; min-width: 360px; }
.controls.wide.bkmode > .hint { flex: 1 1 220px; }
.bkmode .seg { min-width: 360px; }
.bkmode .segbtn { padding: 0 4px; font-size: 12.5px; }

/* the inline panel under the tours: the api form and the embed widget */
.bpanel { margin-top: 12px; overflow: hidden; padding: 0; }
.bphead {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--subtle);
}
.bphead .lbl {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.bphead .bpmode { font-size: 12px; color: var(--accent-text); }
.bphead .iconbtn { margin-left: auto; }
.bpbody { padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
.bpform {
  display: grid;
  grid-template-columns: minmax(0, 2fr) 90px 90px auto;
  gap: 12px;
  align-items: end;
}
.bpval {
  height: var(--h-ctl);
  display: flex;
  align-items: center;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  background: var(--subtle);
  font-family: var(--font-mono);
  font-size: 13px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.bpval.sans { font-family: var(--font-sans); }
.bpform select.input { font-family: var(--font-sans); }
.bpform .bpgo { justify-content: flex-end; }
.bprow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13.5px; }
.bprow .bpmeth { margin-left: auto; font-size: 12px; color: var(--muted); }
.bprule {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--faint);
  overflow-wrap: anywhere;
}
.bpframe {
  display: block;
  width: 100%;
  min-height: 520px;
  border: 0;
  background: var(--surface);
}

@media (max-width: 767px) {
  .bpform { grid-template-columns: minmax(0, 1fr); }
  .bpform .bpgo .btn { width: 100%; }
  .bprow .bpmeth { margin-left: 0; flex-basis: 100%; }
  /* The 420 px basis and the 360 px floor above are for a row with room
     beside it. On a phone the card stacks, the floor made the strip wider than
     the card (33 + 360 = 393 px at 390) and the page scrolled sideways by 3 px;
     the basis turned into a height in the column. The five buttons need about
     300 px. */
  .controls.wide.bkmode > .segblock { flex: 1 1 auto; min-width: 0; }
  .bkmode .seg { min-width: 0; }
  /* the hint's 220 px basis turned into empty height in the column as well */
  .controls.wide.bkmode > .hint { flex: 0 0 auto; }
  /* Russian mode names are longer ("Ссылка в брони", "Возврат на сайт"): on a
     phone they take two lines at one shared height, and the mono hint above
     them wraps, instead of pushing the card 21 px past the screen */
  html[lang="ru"] .bkmode .segbtn { white-space: normal; height: auto; min-height: 34px; min-width: 0; padding: 4px 2px; font-size: 12px; line-height: 1.2; }
  html[lang="ru"] .bkmode .seglabel { flex-wrap: wrap; gap: 2px 10px; }
  html[lang="ru"] .bkmode .seglabel .mono { white-space: normal; }
}

/* Conversions block in the Journey tab */
.convtitle { margin-top: 14px; }
.conv {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 0;
  border-bottom: 1px solid var(--subtle);
}
.conv:last-child { border-bottom: 0; }
.conv .crow {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12.5px;
}
.conv .cid { font-size: 12px; }
.conv .ctour { color: var(--muted); }
.conv .cprice, .conv .cmethod, .conv .cconf { font-size: 12px; color: var(--muted); }
.conv .cconf { color: var(--text); }
.conv .crule {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--faint);
  overflow-wrap: anywhere;
}

/* Webhooks tab */
.hook { border-bottom: 1px solid var(--subtle); }
.hook:last-child { border-bottom: 0; }
.hookhead {
  display: grid;
  grid-template-columns: 62px 96px minmax(0, 1fr) 72px 16px;
  gap: 10px;
  align-items: center;
  width: 100%;
  padding: 7px 0;
  background: none;
  border: 0;
  cursor: pointer;
  color: inherit;
  font-family: var(--font-mono);
  font-size: 11.5px;
  text-align: left;
}
.hookhead:hover { color: var(--accent-text); }
.hookhead .t { color: var(--muted); }
.hookhead .bid { overflow-wrap: anywhere; }
.hookhead .st { color: var(--known-text); text-align: right; }
.hookhead .ico { transition: transform var(--t-fast) ease; color: var(--faint); }
.hook.open .hookhead .ico { transform: rotate(180deg); }
.hook .json { margin: 0 0 10px; max-height: 220px; }

@media (max-width: 767px) {
  .hookhead { grid-template-columns: 54px minmax(0, 1fr) 16px; }
  .hookhead .src, .hookhead .st { display: none; }
}

/* --------------------------------- what we know about you (me.html) */

.mepage { display: flex; flex-direction: column; gap: 14px; }
.mesec { padding: 14px 20px; display: flex; flex-direction: column; gap: 10px; }
.mesec > .wbtitle { margin: 4px 0 0; }
.mesec p.body { font-size: 13.5px; line-height: 1.5; color: #57534E; max-width: 760px; }

.mehead-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 20px;
  align-items: start;
}
.mehead-id { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.mehead-id .factgrid { margin: 0; }
.mecode { display: flex; flex-direction: column; gap: 2px; }
.mecode .k {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
}
.mecode .code {
  font-family: var(--font-mono);
  font-size: 30px;
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1.15;
}
.mecode .sub3 { font-size: 12px; color: var(--muted); }
.melbl { font-size: 12px; font-weight: 500; color: var(--muted); }
.mehead-code .restore-row .input { text-transform: uppercase; }

.mecols2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 24px; }
.mepair { min-width: 0; display: flex; flex-direction: column; gap: 4px; }

/* Issue #22 (c). A table wider than its box scrolls inside this wrapper, not
   the page and not the whole panel. A soft shadow marks each edge that has more
   table behind it: the two white covers scroll with the table (local) and hide
   a shadow once its edge is reached, the shadows stay put (scroll). iOS shows
   no scrollbar until the table moves, so the shadow is what says it can. */
.tablewrap {
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--surface) 40%, rgba(255, 255, 255, 0)) left center / 32px 100% no-repeat local,
    linear-gradient(to left, var(--surface) 40%, rgba(255, 255, 255, 0)) right center / 32px 100% no-repeat local,
    linear-gradient(to right, rgba(28, 25, 23, 0.16), rgba(28, 25, 23, 0)) left center / 12px 100% no-repeat scroll,
    linear-gradient(to left, rgba(28, 25, 23, 0.16), rgba(28, 25, 23, 0)) right center / 12px 100% no-repeat scroll;
}
.tablewrap table.tbl { min-width: 520px; }

.melog { max-height: 420px; overflow: auto; }

.mehook { border-bottom: 1px solid var(--subtle); }
.mehook:last-of-type { border-bottom: 0; }
.mehook > summary {
  display: grid;
  grid-template-columns: 150px 110px minmax(0, 1fr) 80px;
  gap: 10px;
  align-items: center;
  padding: 8px 0;
  font-size: 12.5px;
  cursor: pointer;
  list-style: none;
}
.mehook > summary::-webkit-details-marker { display: none; }
.mehook > summary:hover { color: var(--accent-text); }
.mehook > summary .t { color: var(--muted); }
.mehook > summary .st { text-align: right; color: var(--muted); }
.mehook > .json { margin-bottom: 10px; }

.meacts { gap: 10px 16px; }
.melink { color: var(--accent-text); font-size: 12px; margin-right: 10px; white-space: nowrap; }
.melink:hover { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 980px) {
  .mehead-grid { grid-template-columns: 1fr; }
  .mecols2 { grid-template-columns: 1fr; gap: 14px; }
}

@media (max-width: 767px) {
  .mesec { padding: 12px 14px; }
  .mecode .code { font-size: 24px; }
  .mehook > summary { grid-template-columns: minmax(0, 1fr) 70px; }
  .mehook > summary .t { grid-column: 1 / -1; }
}

/* ------------------------------------------ reset panel (issue #21)

   Reset journey no longer reloads the page, because that reload was what spent
   the fresh journey on a bare address before the next link could be read. What
   is left behind is a page describing a record that has been deleted, so this
   panel covers it: it is deliberately not dismissable, the way out is a new tab.
   z-index sits above the banner (60) and the drawer (50). */

.almodal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  overflow: auto;
  background: rgba(28, 25, 23, 0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.almodal-card {
  width: min(620px, 100%);
  max-height: 100%;
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.almodal-card h2 { font-size: 20px; }
.almodal-card .body { font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.almodal-url { display: flex; flex-direction: column; gap: 6px; }
.almodal-url .lbl {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--faint);
}
.almodal-url .json { margin: 0; max-height: 120px; overflow: auto; overflow-wrap: anywhere; white-space: pre-wrap; }
.almodal-acts { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

@media (max-width: 767px) {
  .almodal { padding: 12px; align-items: flex-start; }
  .almodal-card { padding: 16px; }
  .almodal-card h2 { font-size: 18px; }
  .almodal-acts .btn { width: 100%; }
}
