/* ══════════════════════════════════════════
   WHAT'S ON: whats-on.css
   PinPint dark green theme
══════════════════════════════════════════ */

/* ── BUS / ROUTE STOPS ── */
.wo-route-stops {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
}
.wo-stop-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size:14px;
}
.wo-stop-time {
  width: 46px;
  font-weight: 700;
  color: var(--app-green);
  flex-shrink: 0;
  font-size:13px;
}
.wo-stop-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--app-green);
  flex-shrink: 0;
  box-shadow: 0 0 6px rgba(var(--brand-rgb),0.5);
}
.wo-stop-line {
  width: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
}
.wo-stop-connector {
  width: 2px;
  height: 16px;
  background: var(--app-border);
  margin: 2px 0;
}
.wo-stop-name { color: var(--app-text); font-weight: 600; }

/* ── CREATE EVENT DRAWER ── */
.wo-drawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.75);
  /* This page carries the shared bottom nav, and a drawer the nav can render
     on top of is not a drawer. */
  z-index: var(--z-sheet);
  backdrop-filter: blur(6px);
  display: none;
  align-items: flex-end;
}
.wo-drawer-overlay.open { display: flex; }
.wo-drawer {
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
  background: var(--app-surface);
  border-radius: 20px 20px 0 0;
  border-top: 1px solid var(--app-border);
  padding: 0 0 max(12px, env(safe-area-inset-bottom));
  max-height: 92dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: drawerSlideUp 0.3s cubic-bezier(0.32,0.72,0,1);
}
@media (prefers-reduced-motion: reduce){
  .wo-drawer{animation:none}
}
@keyframes drawerSlideUp {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
/* The pill is drawn by ::before now; the element itself is the touch target.
   It used to BE the pill, 36 by 4 CSS pixels, which is not a hit area any
   thumb can find, so the drag-to-dismiss makeDismissable() has been wiring to
   this handle was unreachable on the only device type it exists for. */
.wo-drawer-handle {
  width: 100%;
  padding: 12px 0 4px;
  cursor: grab;
  /* Non-negotiable on a sheet whose body scrolls. Without it the browser
     claims a downward drag for scrolling before the first pointermove is
     delivered, and the handle does nothing at all. */
  touch-action: none;
}
.wo-drawer-handle::before {
  content: "";
  display: block;
  width: 36px;
  height: 4px;
  margin: 0 auto;
  background: rgba(255,255,255,0.15);
  border-radius: 2px;
}
.wo-drawer-handle:active { cursor: grabbing; }

/* Title and the × on one line. The row is also the rest of the drag surface:
   makeDismissable() accepts a drag anywhere in the top 96px of the sheet, and
   touch-action has to say so here too or the scrolling body underneath wins
   the gesture before the handler ever sees it. */
.wo-drawer-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 16px 14px 0 20px;
  touch-action: none;
}
.wo-drawer-title {
  flex: 1;
  min-width: 0;
  font-size: 18px;
  font-weight: 800;
  color: var(--app-text);
  margin: 0;
}
/* Past 900px the drawer is a centred modal with no handle on it, so this is
   the only visible way out other than the backdrop. */
.wo-drawer-close {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  margin-top: -3px;
  border-radius: 50%;
  border: 1px solid var(--app-border);
  background: transparent;
  color: var(--app-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.wo-drawer-close:hover { background: var(--hover); color: var(--app-text); }
.wo-drawer-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wo-drawer-sub {
  font-size:14px;
  color: var(--app-muted);
  padding: 4px 20px 16px;
  border-bottom: 1px solid var(--app-border);
  touch-action: none;
}
.wo-form { padding: 16px 20px; }

/* ── FORM ELEMENTS ── */
.wo-form-group { margin-bottom: 14px; }
.wo-form-label {
  display: block;
  font-size:13px;
  font-weight: 700;
  color: var(--app-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}
.wo-form-input,
.wo-form-textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 11px 14px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--app-border);
  border-radius: 10px;
  color: var(--app-text);
  /* Never below 16px: iOS zooms the viewport when a smaller field takes
     focus, and the page never zooms back. Same rule as .input in shared.css. */
  font-size:16px;
  font-family: var(--font-sans);
  outline: none;
  transition: border-color 0.2s, background 0.2s;
}
.wo-form-input:focus,
.wo-form-textarea:focus {
  border-color: rgba(var(--brand-rgb),0.45);
  background: rgba(var(--brand-rgb),0.04);
}
.wo-form-textarea { resize: vertical; min-height: 80px; }
.wo-form-row { display: flex; gap: 10px; }
.wo-form-row .wo-form-group { flex: 1; }

/* ── TYPE PICKER GRID ── */
.wo-type-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.wo-type-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 6px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--app-border);
  border-radius: 10px;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size:13px;
  font-weight: 600;
  color: var(--app-muted);
  transition: all 0.18s;
}
.wo-type-btn span:first-child { font-size: 22px; }
.wo-type-btn.selected {
  background: rgba(var(--brand-rgb),0.12);
  border-color: var(--app-green);
  color: var(--app-green);
}

/* ── BUS STOPS BUILDER ── */
.wo-stops-builder { display: flex; flex-direction: column; gap: 8px; }
.wo-stop-input-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.wo-stop-input-row .wo-form-input { flex: 1; }
.wo-stop-time-input { width: 90px; flex-shrink: 0; }
.wo-stop-del {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--app-danger-bg);
  border: 1px solid rgba(var(--danger-rgb),0.2);
  color: var(--app-danger);
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.wo-add-stop-btn {
  padding: 8px 16px;
  background: rgba(var(--brand-rgb),0.06);
  border: 1px dashed rgba(var(--brand-rgb),0.3);
  border-radius: 10px;
  color: var(--app-green);
  font-size:14px;
  font-weight: 600;
  font-family: var(--font-sans);
  cursor: pointer;
  text-align: center;
  width: 100%;
  box-sizing: border-box;
}

/* ── PRIVACY ROW ── */
.wo-privacy-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--app-border);
  border-radius: 10px;
}
.wo-privacy-info { flex: 1; }
.wo-privacy-label { font-size:15px; font-weight: 600; color: var(--app-text); }
.wo-privacy-sub   { font-size:13px; color: var(--app-muted); margin-top: 2px; }

/* ── PAYMENT STRIP ── */
.wo-payment-strip {
  background: rgba(var(--brand-rgb),0.06);
  border: 1px solid rgba(var(--brand-rgb),0.2);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}
.wo-payment-icon  { font-size: 28px; flex-shrink: 0; }
.wo-payment-info  { flex: 1; }
.wo-payment-title { font-size:15px; font-weight: 700; color: var(--app-text); }
.wo-payment-sub   { font-size:13px; color: var(--app-muted); margin-top: 2px; }
.wo-payment-price { font-size: 20px; font-weight: 800; color: var(--app-green); flex-shrink: 0; }

/* ── SUBMIT BUTTON ── */
.wo-submit-btn {
  width: 100%;
  padding: 14px;
  background: linear-gradient(135deg, var(--brand-600), var(--accent-solid));
  border: none;
  border-radius: 12px;
  color: var(--on-accent);
  font-size: 15px;
  font-weight: 800;
  font-family: var(--font-sans);
  cursor: pointer;
  transition: opacity 0.2s, transform 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  box-shadow: 0 4px 16px rgba(22,163,74,0.25);
}
.wo-submit-btn:active   { transform: scale(0.98); opacity: 0.9; }
.wo-submit-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── SHARE MODAL ── */
.wo-share-modal {
  background: var(--app-card);
  border-radius: 20px 20px 0 0;
  border-top: 1px solid var(--app-border);
  padding: 20px 20px env(safe-area-inset-bottom);
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
  animation: drawerSlideUp 0.25s ease;
}
.wo-share-title {
  font-size: 16px;
  font-weight: 800;
  color: var(--app-text);
  margin: 0 0 4px;
}
.wo-share-sub { font-size:13px; color: var(--app-muted); margin: 0 0 16px; }
.wo-share-link-row {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}
.wo-share-link-input {
  flex: 1;
  padding: 10px 12px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--app-border);
  border-radius: 10px;
  color: var(--app-muted);
  font-size:14px;
  font-family: var(--font-sans);
  outline: none;
}
.wo-copy-btn {
  padding: 10px 16px;
  background: rgba(var(--brand-rgb),0.15);
  border: 1px solid rgba(var(--brand-rgb),0.35);
  border-radius: 10px;
  color: var(--app-green);
  font-size:14px;
  font-weight: 700;
  font-family: var(--font-sans);
  cursor: pointer;
}
.wo-share-options {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 14px;
}
.wo-share-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 6px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--app-border);
  border-radius: 12px;
  cursor: pointer;
  font-size:13px;
  font-weight: 600;
  color: var(--app-muted);
  font-family: var(--font-sans);
  transition: all 0.18s;
}
.wo-share-option span:first-child { font-size: 22px; }
.wo-share-option:hover { border-color: rgba(var(--brand-rgb),0.3); color: var(--app-text); }
.wo-share-cancel {
  width: 100%;
  padding: 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--app-border);
  border-radius: 10px;
  color: var(--app-muted);
  font-size:15px;
  font-weight: 600;
  font-family: var(--font-sans);
  cursor: pointer;
}

.wo-login-prompt {
  text-align: center;
  padding: 20px 16px 28px;
  background: var(--app-card);
  border: 1px solid var(--app-border);
  border-radius: var(--app-radius);
  margin-top: -4px;
}
.wo-login-prompt-icon { font-size: 32px; margin-bottom: 8px; }
.wo-login-prompt-text { font-size:15px; color: var(--app-muted); margin-bottom: 14px; line-height: 1.5; }
.wo-login-prompt-btn {
  display: inline-block;
  padding: 11px 28px;
  background: var(--app-green);
  color: var(--on-accent);
  border-radius: 99px;
  font-weight: 800;
  font-size:15px;
  text-decoration: none;
  cursor: pointer;
  border: none;
  font-family: var(--font-sans);
}

/* ══════════════════════════════════════════════════════════════
   VENUE PICKER: binds a free-text venue to a real pub
   ══════════════════════════════════════════════════════════════ */
.wo-venue-wrap{position:relative}
.wo-venue-results{
  position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:40;
  background:var(--app-panel,var(--panel));border:1px solid var(--app-border,var(--border));
  border-radius:10px;overflow:hidden;display:none;
  box-shadow:0 8px 24px rgba(0,0,0,.45);max-height:230px;overflow-y:auto;
}
.wo-venue-results.open{display:block}
.wo-venue-hit{
  display:flex;flex-direction:column;gap:1px;width:100%;padding:9px 12px;
  background:none;border:none;border-bottom:1px solid rgba(255,255,255,.05);
  cursor:pointer;text-align:left;font-family:var(--font-sans);
}
.wo-venue-hit:last-child{border-bottom:none}
.wo-venue-hit:hover{background:rgba(var(--brand-rgb),.09)}
.wo-venue-hit-name{font-size:14px;font-weight:600;color:var(--app-text,var(--text))}
.wo-venue-hit-addr{font-size:13px;color:var(--app-muted,var(--text-2))}
.wo-venue-none{padding:10px 12px;font-size:13px;color:var(--app-muted,var(--text-2))}

.wo-venue-chip{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:7px;
  padding:8px 11px;border-radius:8px;font-size:13px;
  background:rgba(var(--brand-rgb),.1);border:1px solid rgba(var(--brand-rgb),.28);
  color:var(--app-green,var(--accent));
}
.wo-venue-chip strong{font-weight:700}
.wo-venue-unlink{
  margin-left:auto;background:none;border:none;color:var(--app-muted,var(--text-2));
  font-size:13px;text-decoration:underline;cursor:pointer;
  font-family:var(--font-sans);
}
.wo-venue-unlink:hover{color:var(--danger)}

/* Free-to-post strip replaces the old paid one */
.wo-free-strip{border-color:rgba(var(--brand-rgb),.3)!important;background:rgba(var(--brand-rgb),.07)!important}
.wo-free-strip .wo-payment-price{color:var(--app-green,var(--accent))!important}

.wo-pill-dist{background:rgba(var(--brand-rgb),.1)!important;color:var(--app-green,var(--accent))!important}

/* ── Venue deep-link banner ─────────────────────────────────────────────────
   Shown when you arrive from a pub on the map. Without it the feed silently
   hides most of its content and looks empty rather than filtered. */
.wo-venue-filter{
  display:flex;align-items:center;gap:10px;
  padding:10px 13px;margin-bottom:12px;
  background:var(--brand-ghost,rgba(22,163,74,.08));
  border:1px solid var(--border);
  border-left:3px solid var(--accent);
  border-radius:var(--r-md,12px);
  font-size:var(--t-sm,13px);color:var(--text-2);
}
.wo-venue-filter[hidden]{display:none}
.wo-venue-filter-ico{font-size:15px;flex-shrink:0}
.wo-venue-filter-txt{flex:1;min-width:0}
.wo-venue-filter-name{color:var(--text);font-weight:700}
.wo-venue-filter-clear{
  flex-shrink:0;padding:6px 12px;min-height:34px;
  background:transparent;border:1px solid var(--border-strong,var(--border));
  border-radius:999px;color:var(--text-2);
  font-family:inherit;font-size:var(--t-xs,12px);font-weight:600;cursor:pointer;
  transition:background .15s ease,color .15s ease;
}
.wo-venue-filter-clear:hover{background:var(--hover);color:var(--text)}

/* Empty states offer the way out of whatever filter caused them. */
.app-empty-action{
  margin-top:12px;padding:9px 16px;min-height:40px;
  background:var(--accent-solid);border:1px solid var(--accent-solid);
  border-radius:999px;color:var(--on-accent);
  font-family:inherit;font-size:var(--t-sm,13px);font-weight:700;cursor:pointer;
}
.app-empty-action:hover{background:var(--brand-500,var(--accent-solid))}

.wo-venue-filter-clear:focus-visible,
.app-empty-action:focus-visible{outline:2px solid var(--accent);outline-offset:2px}


/* ── REPEATS ───────────────────────────────────────────────────────────────
   Same four-across grid as the type picker, because it is the same kind of
   choice: pick exactly one, and the one already picked is a sensible default. */
.wo-repeat-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:8px;
}
.wo-repeat-btn{
  padding:10px 4px;min-height:44px;
  background:rgba(255,255,255,0.04);
  border:1px solid var(--app-border);border-radius:10px;
  color:var(--text-2);
  font-family:var(--font-sans);font-size:13px;font-weight:600;
  cursor:pointer;transition:all .15s;
}
.wo-repeat-btn:hover{border-color:var(--border-strong);color:var(--text)}
.wo-repeat-btn.active{
  background:rgba(var(--brand-rgb),0.12);
  border-color:var(--app-green);color:var(--app-green);
}
.wo-repeat-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.wo-repeat-until[hidden]{display:none}
/* Says in words what the buttons chose, so nobody has to work out from a
   dropdown that "weekly" starting on a Tuesday means every Tuesday. */
.wo-repeat-note{
  margin-top:8px;font-size:13px;line-height:1.45;color:var(--app-muted);
}
@media (max-width:420px){
  .wo-repeat-grid{grid-template-columns:repeat(2,1fr)}
}


/* ── TICKET LINK ───────────────────────────────────────────────────────────
   The only outbound link on a card, so it is the only filled button on one.
   Brass rather than brand green: it leaves PinPint, and the green is what
   keeps you here. */
.wo-ticket-btn{
  display:inline-flex;align-items:center;gap:5px;
  padding:8px 15px;min-height:38px;
  background:var(--brass-500);border:1px solid var(--brass-500);
  border-radius:999px;
  /* Was a hardcoded #1D1710, the old dark-theme panel colour, which is now a
     grey and was never a token in the first place. */
  color:var(--on-warn);
  font-family:var(--font-sans);font-size:14px;font-weight:700;
  text-decoration:none;white-space:nowrap;
  transition:background .15s,border-color .15s;
}
.wo-ticket-btn:hover{background:var(--brass-400);border-color:var(--brass-400)}
.wo-ticket-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.wo-ticket-hint{
  margin-top:7px;font-size:13px;line-height:1.45;color:var(--app-muted);
}
.wo-ticket-hint.is-bad{color:var(--danger);font-weight:600}


/* ══════════════════════════════════════════════════════════════════════════
   DESKTOP: the dialogs
   The layout of the listings themselves moved into the DISCOVERY block below.
   What is left here is what desktop does to the *forms*: a bottom sheet on a
   laptop is the single clearest tell that a page was only ever designed for a
   phone.
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width:900px){
  /* There is room for every chip, so stop scrolling and stop fading. */
  .wo-filter-bar{
    flex-wrap:wrap;overflow:visible;
    -webkit-mask-image:none;mask-image:none;
  }

  .wo-drawer-overlay{align-items:center;justify-content:center}
  .wo-drawer{
    border-radius:18px;border:1px solid var(--app-border);
    max-height:86vh;overflow-y:auto;
    max-width:620px;
    animation:none;
  }
  .wo-drawer-handle{display:none}   /* nothing to drag on a mouse */
}


/* ══════════════════════════════════════════════════════════════════════════
   DISCOVERY
   ══════════════════════════════════════════════════════════════════════════

   The listings, the day rail, the row, and Build My Night.

   The shape is a fixture list. Time in a fixed left column, the thing and the
   pub in the middle, the price on the right, so eight of them scan in the
   time the old cards took to show two, and comparing this one with that one
   is a glance down a column rather than a scroll between posters.

   Colour is spent on exactly two things, because they are the two facts this
   app has that nothing else does: what is on right now, and what a pint costs.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   THE SHELL

   The page does not scroll. It is exactly one viewport tall, split into fixed
   chrome and two panels that scroll inside themselves, so the day rail and
   the kind filters are still there after forty listings, and the second panel
   is one glance away rather than one long scroll away.

   The maths, once: <body> is 100dvh with the tab bar's height as padding
   (shared.css does that for every page carrying the bar), so the body's
   content box is already "the screen minus the nav". .wo-main then takes that
   minus the fixed header, and everything inside is flex with min-height:0,
   the one declaration without which a flex child refuses to shrink below its
   content and the scroll silently moves back to the page.
   ══════════════════════════════════════════════════════════════════════════ */
body.wo-page{
  height:100vh;
  height:100dvh;
  overflow:hidden;
}
/* app.css caps .app-main at 900px, which is right for a list of pubs and
   wrong for a page whose whole job is showing a lot at once. */
body.app-page .wo-main{
  max-width:none;
  width:100%;
  margin-top:var(--header-h);
  /* Measured from the viewport, not inherited as a percentage of <body>.
     A percentage resolves against the parent's content box, which is 100dvh
     minus the tab bar's padding on this page, so `100% - header` came out a
     tab bar too tall the moment <body> stopped being a flex container, and
     the foot of the second panel went under the nav. This says what it
     means: the screen, less the header, less the bar. */
  height:calc(100vh - var(--header-h) - var(--tabbar-h));
  height:calc(100dvh - var(--header-h) - var(--tabbar-h));
  min-height:0;
  padding:0;
  display:flex;
  flex-direction:column;
  overflow:hidden;
}

/* ── FIXED HEAD ── */
.wo-top{
  flex:0 0 auto;
  padding:12px 16px 10px;
  background:var(--app-bg);
  border-bottom:1px solid var(--app-border);
}

/* ── THE PANELS ── */
.wo-panels{
  flex:1 1 auto;
  min-height:0;
  display:grid;
  grid-template-columns:minmax(0,1fr);
}
.wo-panel{
  display:flex;
  flex-direction:column;
  min-height:0;
  min-width:0;
}
/* One at a time until there is room for both. Classes rather than ids, so the
   rule that shows both on a laptop can out-rank this one without !important. */
.wo-panels[data-panel="day"]  .wo-panel--next{display:none}
.wo-panels[data-panel="next"] .wo-panel--day {display:none}

.wo-panel-head{
  flex:0 0 auto;
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding:12px 16px 8px;
}
.wo-panel-title{
  margin:0;
  font-size:var(--t-2xs);font-weight:800;
  letter-spacing:.09em;text-transform:uppercase;
  color:var(--app-muted);
}
.wo-panel-count{
  font-size:var(--t-2xs);font-weight:700;color:var(--app-muted);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}

/* The scroll areas themselves. overscroll-behavior is what stops a flick at
   the end of a list handing the gesture to whatever is behind it. */
.wo-panel-scroll{
  flex:1 1 auto;
  min-height:0;
  overflow-y:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  padding:0 16px 24px;
  scrollbar-width:thin;
  scrollbar-color:var(--border-strong) transparent;
}
.wo-panel-scroll::-webkit-scrollbar{width:9px}
.wo-panel-scroll::-webkit-scrollbar-track{background:transparent}
.wo-panel-scroll::-webkit-scrollbar-thumb{
  background:var(--border-strong);
  border:3px solid transparent;background-clip:padding-box;
  border-radius:99px;
}
.wo-panel-scroll:hover::-webkit-scrollbar-thumb{background:var(--text-3);background-clip:padding-box}
/* A scrollbar on a touch screen is a scrollbar nobody can grab. */
@media (pointer:coarse){
  .wo-panel-scroll{scrollbar-width:none}
  .wo-panel-scroll::-webkit-scrollbar{display:none}
}

/* ── SEGMENTED CONTROL (phone and tablet) ──
   Two panels, one screen. Tabs rather than a swipe: a swipe is invisible, and
   this row also has to report how much is in each side. */
.wo-switch{
  display:grid;grid-template-columns:1fr 1fr;gap:4px;
  margin-top:12px;padding:3px;
  background:var(--app-card);
  border:1px solid var(--app-border);
  border-radius:var(--r-md);
}
.wo-switch-btn{
  display:flex;align-items:center;justify-content:center;gap:6px;
  min-height:38px;padding:0 10px;
  border:none;border-radius:calc(var(--r-md) - 3px);
  background:transparent;color:var(--app-muted);
  font-family:var(--font-sans);font-size:var(--t-xs);font-weight:700;
  cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease;
}
.wo-switch-btn.is-on{background:var(--accent-solid);color:var(--on-accent)}
.wo-switch-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.wo-switch-count{
  min-width:20px;padding:1px 6px;border-radius:var(--r-full);
  background:var(--app-border);color:var(--app-muted);
  font-size:var(--t-2xs);font-variant-numeric:tabular-nums;font-weight:800;
}
.wo-switch-btn.is-on .wo-switch-count{background:rgba(255,255,255,.22);color:var(--on-accent)}

/* Loading is ppSkeleton() from shared.js, at the height of a listing row,
   the same shimmer every other list in the app waits with. */
.wo-panel-scroll .pp-skel{padding-top:2px}

/* ── HERO ── */
.wo-hero{padding:0 0 10px}
.wo-hero-title{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(26px,6.4vw,34px);
  line-height:1.08;
  letter-spacing:-.02em;
}
.wo-hero-place{color:var(--app-green)}
.wo-hero-sub{
  margin:4px 0 0;font-size:var(--t-base);font-weight:500;color:var(--app-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* ── DAY RAIL ──
   Tabs, not cards.

   Eight bordered tiles with a count boxed under each was eight objects
   competing with the listings underneath them, and on a phone they ate a
   quarter of the screen before a single event was on it. This is the shape a
   dense sports app uses for the same job, a flat strip of days on the header
   ground, the selected one marked by a brand underline rather than a filled
   box, and a hairline under the whole row that says the strip is chrome and
   the listings below are the page.

   The count stays. It is what makes the rail worth reading rather than a row
   of buttons: the week is answered before anything is tapped. */
.wo-rail-wrap{
  margin:0 -16px;padding:0 16px;
  border-bottom:1px solid var(--app-border);
}
.wo-rail{
  display:flex;gap:0;overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;
}
.wo-rail::-webkit-scrollbar{display:none}
.wo-day{
  position:relative;
  flex:0 0 auto;scroll-snap-align:center;
  min-width:66px;min-height:52px;
  padding:7px 12px 9px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  background:none;border:none;border-radius:0;
  color:var(--app-muted);
  font-family:var(--font-sans);cursor:pointer;
  transition:color var(--dur-fast) ease;
}
.wo-day-label{font-size:var(--t-xs);font-weight:700;white-space:nowrap;color:inherit}
.wo-day-count{font-size:var(--t-2xs);font-weight:600;color:var(--app-muted);white-space:nowrap}
.wo-day:hover{color:var(--app-text)}
/* A week of blanks is most of this strip, so the days with nothing on recede
   rather than competing with the ones that have something. */
.wo-day.is-empty{opacity:.55}
.wo-day.active{color:var(--app-text);opacity:1}
.wo-day.active .wo-day-count{color:var(--app-green)}
.wo-day.active::after{
  content:"";position:absolute;left:10px;right:10px;bottom:0;height:3px;
  background:var(--accent);border-radius:3px 3px 0 0;
}
.wo-day:focus-visible{outline:2px solid var(--accent);outline-offset:-3px}

/* ── KIND CHIPS ──
   Pills, so the two controls are told apart at a glance: the days are tabs
   with an underline, the kinds are chips with a fill. Same active treatment as
   .chip.is-active in shared.css, solid brand, white ink, rather than the
   tinted-text version, which was the one thing on this page that disappeared
   on the light theme. */
.wo-filter-bar{
  display:flex;gap:6px;
  margin-top:10px;padding:0;
  overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;
  -webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 26px),transparent 100%);
  mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 26px),transparent 100%);
}
.wo-filter-bar::-webkit-scrollbar{display:none}
.wo-chip{
  flex:0 0 auto;scroll-snap-align:start;
  display:inline-flex;align-items:center;gap:5px;
  min-height:32px;padding:0 12px;
  border-radius:var(--r-full);
  background:var(--app-card);
  border:1px solid transparent;
  color:var(--app-muted);
  font-family:var(--font-sans);font-size:var(--t-xs);font-weight:600;
  white-space:nowrap;cursor:pointer;
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease;
}
.wo-chip:hover{color:var(--app-text);background:var(--hover)}
.wo-chip.active{
  background:var(--accent-solid);border-color:var(--accent-solid);color:var(--on-accent);
}
.wo-chip:active{transform:scale(.97)}
.wo-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ── BUILD MY NIGHT ── the header control ──
   It was a full-width gradient button under the filters. The filters are fixed
   chrome now and there is no page to put a banner across, so it is a header
   button: always there, never in the way of a listing. */
.wo-plan-btn{
  display:inline-flex;align-items:center;gap:7px;
  min-height:36px;padding:0 14px;
  border:1px solid var(--accent);border-radius:var(--r-full);
  background:var(--brand-ghost);color:var(--app-green);
  font-family:var(--font-sans);font-size:var(--t-xs);font-weight:700;
  cursor:pointer;white-space:nowrap;
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease;
}
.wo-plan-btn:hover{background:var(--accent-solid);border-color:var(--accent-solid);color:var(--on-accent)}
.wo-plan-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Under 560px the label is the first thing to go, not the button. */
@media (max-width:559px){
  .wo-plan-btn{padding:0 11px;font-size:var(--t-md)}
  .wo-plan-btn-txt{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap;
  }
}

/* ── SECTIONS ── */
.wo-section-divider{
  display:flex;align-items:center;gap:10px;margin:22px 0 8px;
}
.wo-section-divider:first-child{margin-top:4px}
.wo-divider-label{
  font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--app-muted);white-space:nowrap;
}
.wo-divider-line{flex:1;height:1px;background:var(--app-border)}
.wo-div-live .wo-divider-label{color:var(--live)}

/* ── COMING UP: the day headings ──
   A heading you can tap. It is the same list as the day panel, so its heading
   is also the way to move the whole page onto that day rather than a label
   that only sits there. */
.wo-up-day{
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  width:100%;margin:18px 0 8px;padding:4px 2px;
  background:none;border:none;cursor:pointer;text-align:left;
  font-family:var(--font-sans);
}
.wo-up-day:first-child{margin-top:2px}
.wo-up-day-name{font-size:var(--t-sm);font-weight:800;color:var(--app-text)}
.wo-up-day-count{font-size:var(--t-2xs);font-weight:600;color:var(--app-muted)}
.wo-up-day:hover .wo-up-day-name{color:var(--app-green)}
.wo-up-day:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--r-xs)}

/* ── THE LIST ──
   Hairlines between rows rather than a gap and a border each: the list reads
   as one object, which is what makes the left-hand time column line up down
   the whole thing. */
.wo-list{
  border:1px solid var(--app-border);
  border-radius:var(--app-radius);
  background:var(--app-card);
  overflow:hidden;
}
.wo-row-wrap + .wo-row-wrap{border-top:1px solid var(--app-border)}

.wo-row{
  display:grid;
  grid-template-columns:56px 26px minmax(0,1fr) auto 14px;
  align-items:center;
  gap:10px;
  width:100%;
  min-height:62px;
  padding:10px 12px;
  background:transparent;border:none;
  text-align:left;
  color:var(--app-text,var(--text-1));
  font-family:var(--font-sans);
  cursor:pointer;
  transition:background var(--dur-fast) ease;
}
.wo-row:hover{background:rgba(255,255,255,.035)}
.wo-row:focus-visible{outline:2px solid var(--app-green);outline-offset:-2px}
.wo-row.is-open{background:rgba(var(--brand-rgb),.06)}

.wo-row-time{
  font-size:14px;font-weight:800;
  font-variant-numeric:tabular-nums;
  color:var(--app-text,var(--text-1));
  white-space:nowrap;
}
.wo-row-ico{font-size:19px;text-align:center;line-height:1}
.wo-row-main{min-width:0;display:block}
/* Two lines before it truncates. On a 390px phone the middle column is about
   135px, which cut "Student night, €4 pints" down to "Student nigh…", and a
   listing whose title does not fit is not a listing. The pub underneath stays
   on one line, because that one does read fine truncated. */
.wo-row-title{
  display:flex;align-items:flex-start;gap:7px;flex-wrap:wrap;
  font-size:15px;font-weight:700;line-height:1.25;
}
.wo-row-title-txt{
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  overflow:hidden;
}
.wo-row-sub{
  display:block;margin-top:2px;
  font-size:var(--t-2xs);font-weight:500;color:var(--app-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.wo-row-right{
  display:flex;flex-direction:column;align-items:flex-end;
  line-height:1.15;white-space:nowrap;
}
.wo-row-price{font-size:15px;font-weight:800;color:var(--app-green);font-variant-numeric:tabular-nums}
.wo-row-price.is-stale{color:var(--warn)}
.wo-row-price-sub{font-size:var(--t-2xs);font-weight:600;color:var(--app-muted)}
.wo-row-chev{
  color:var(--app-muted);font-size:19px;line-height:1;
  transition:transform var(--dur-fast) var(--ease-out);
}
.wo-row.is-open .wo-row-chev{transform:rotate(90deg)}
.wo-row.is-live{box-shadow:inset 3px 0 0 var(--live)}

.wo-flag{
  flex-shrink:0;padding:1px 6px;border-radius:99px;
  font-size:var(--t-2xs);font-weight:800;letter-spacing:.05em;text-transform:uppercase;
}
.wo-flag-live{background:var(--live);color:#fff;animation:wo-pulse 2s ease-in-out infinite}
.wo-flag-soon{background:rgba(var(--warn-rgb),.18);color:var(--warn)}
@keyframes wo-pulse{0%,100%{opacity:1}50%{opacity:.5}}
@media (prefers-reduced-motion:reduce){.wo-flag-live{animation:none}}

/* ── THE ROW, OPENED ── */
.wo-row-detail{
  padding:0 12px 14px 12px;
  background:rgba(var(--brand-rgb),.045);
  animation:wo-open var(--dur-fast) var(--ease-out) both;
}
@keyframes wo-open{from{opacity:0;translate:0 -4px}to{opacity:1;translate:0 0}}
@media (prefers-reduced-motion:reduce){.wo-row-detail{animation:none}}

.wo-det-desc{margin:0 0 10px;font-size:14px;line-height:1.5;color:var(--app-muted)}
.wo-det-facts{display:flex;flex-wrap:wrap;gap:6px}
.wo-det-fact{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-2xs);font-weight:600;color:var(--app-muted);
  background:rgba(255,255,255,.05);
  border:1px solid var(--app-border);
  border-radius:99px;padding:3px 10px;
}
.wo-why{
  display:flex;flex-wrap:wrap;gap:4px 12px;
  margin-top:10px;padding-top:10px;
  border-top:1px dashed var(--app-border);
}
.wo-why-item{font-size:12px;font-weight:600;color:var(--app-green)}

.wo-det-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.wo-det-btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:40px;padding:0 15px;
  border-radius:10px;border:1px solid var(--app-border);
  background:transparent;color:var(--app-text,var(--text-1));
  font-family:var(--font-sans);font-size:var(--t-xs);font-weight:700;
  text-decoration:none;cursor:pointer;
  transition:border-color var(--dur-fast) ease,background var(--dur-fast) ease;
}
.wo-det-btn:hover{border-color:var(--app-green);background:rgba(var(--brand-rgb),.08)}
.wo-det-primary{
  border-color:transparent;
  background:linear-gradient(135deg,var(--brand-600),var(--accent-solid));
  color:#fff;
}
.wo-det-btn.joined{border-color:var(--app-green);color:var(--app-green)}

.wo-deeplinked .wo-row{background:rgba(var(--brand-rgb),.1)}

/* ── THE ASK, AFTER THE ANSWER ── */
.wo-contribute{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin-top:20px;padding:14px 16px;
  border-radius:var(--app-radius);
  border:1px dashed var(--app-border);
  background:var(--app-card);
}
.wo-contribute-txt{font-size:var(--t-base);font-weight:700}
.wo-contribute-btn{
  min-height:40px;padding:0 18px;border:none;border-radius:10px;
  background:linear-gradient(135deg,var(--brand-600),var(--accent-solid));
  color:#fff;font-family:var(--font-sans);font-weight:800;font-size:14px;
  cursor:pointer;
}

.wo-contribute-btn.ghost{
  background:transparent;border:1px solid var(--app-border);color:var(--app-muted);
}
.wo-contribute-actions{display:flex;gap:8px;flex-wrap:wrap}
/* The publican's version of the same strip. Solid rather than dashed: theirs
   is not an invitation to contribute, it is their own pub's controls. */
.wo-contribute.is-publican{
  border-style:solid;border-color:var(--brand-600);
  background:rgba(var(--brand-rgb),.06);
}


/* ── THE PUBLICAN'S DIARY ──────────────────────────────────────
   A fortnight of nights inside the drawer, one block per day, bare ones
   included, the empty nights are the ones worth doing something about and
   they only exist on screen if they are drawn. */
.wo-diary{
  max-height:min(58vh,520px);overflow-y:auto;-webkit-overflow-scrolling:touch;
  /* .wo-drawer has no horizontal padding of its own, every block inside it
     brings its own, the way .wo-form does. */
  margin:16px 20px 14px;
  display:flex;flex-direction:column;gap:8px;
}
.wo-diary-foot{padding:0 20px}
.wo-diary-day{
  border:1px solid var(--app-border);border-radius:12px;
  background:var(--app-card);padding:9px 11px;
}
/* Bare nights recede rather than shout. There are usually more of them than
   there are events, and fourteen loud empty boxes is not a diary. */
.wo-diary-day.is-bare{background:transparent;border-style:dashed}
.wo-diary-day-head{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
}
.wo-diary-day-name{font-size:14px;font-weight:800;color:var(--text)}
.wo-diary-add{
  min-height:30px;padding:0 11px;border-radius:8px;
  border:1px solid var(--app-border);background:transparent;
  color:var(--app-muted);font-family:var(--font-sans);
  font-size:13px;font-weight:700;cursor:pointer;
}
.wo-diary-add:hover{border-color:var(--brand-600);color:var(--text)}
.wo-diary-add:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.wo-diary-bare{margin-top:2px;font-size:13px;color:var(--app-muted)}

.wo-diary-row{
  display:flex;align-items:center;gap:9px;
  margin-top:8px;padding:7px 9px;border-radius:9px;
  background:rgba(255,255,255,.04);
}
/* Somebody else's listing at your pub is the row you opened this to find. */
.wo-diary-row.is-mine{background:rgba(var(--brand-rgb),.10)}
.wo-diary-ico{font-size:17px;line-height:1;flex:none}
.wo-diary-text{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.wo-diary-title{
  font-size:14px;font-weight:700;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.wo-diary-meta{font-size:var(--t-2xs);color:var(--app-muted)}
.wo-diary-tag{
  flex:none;font-size:var(--t-2xs);font-weight:700;color:var(--app-muted);
  border:1px solid var(--app-border);border-radius:99px;padding:2px 8px;
}
.wo-diary-offline{
  padding:18px 12px;text-align:center;
  font-size:14px;color:var(--app-muted);
}


/* ── EMPTY, BUT NOT USELESS ── */
.wo-nothing-head{text-align:center;padding:24px 16px 8px}
.wo-nothing-actions{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:14px}
/* Secondary to the "jump to the day that has something" button beside it, but
   secondary is not the same as colourless: transparent-on-grey read as a
   disabled control, and this is the one button on an empty page that has
   anything to offer. Tinted brand, so it is plainly the softer of the two and
   plainly still a button. */
.app-empty-action.ghost{
  background:rgba(var(--brand-rgb),.12);
  border:1px solid rgba(var(--brand-rgb),.45);
  color:var(--accent);
}
.app-empty-action.ghost:hover{background:rgba(var(--brand-rgb),.22)}
.wo-fallback{
  margin-top:20px;padding:16px;
  border-radius:var(--app-radius);
  border:1px solid var(--app-border);background:var(--app-card);
}
.wo-fallback-head{font-size:15px;font-weight:800}
.wo-fallback-sub{font-size:13px;color:var(--app-muted);margin:2px 0 12px}
.wo-fallback-list{display:grid;gap:6px}
.wo-fallback-row{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  width:100%;min-height:44px;padding:8px 12px;
  border-radius:10px;border:1px solid var(--app-border);background:transparent;
  color:var(--app-text,var(--text-1));
  font-family:var(--font-sans);font-size:14px;font-weight:600;
  text-align:left;cursor:pointer;
}
.wo-fallback-row:hover{border-color:var(--app-green)}
.wo-fb-meta{display:flex;align-items:center;gap:10px;flex-shrink:0}
.wo-fb-price{color:var(--app-green);font-weight:800}
.wo-fb-dist{color:var(--app-muted);font-size:13px}

/* ══════════════════════════════════════════════════════════════════════════
   BUILD MY NIGHT
   ══════════════════════════════════════════════════════════════════════════ */
.wo-night-overlay{
  position:fixed;inset:0;z-index:4200;
  background:rgba(0,0,0,.62);backdrop-filter:blur(3px);
  display:flex;align-items:flex-end;justify-content:center;
  opacity:0;pointer-events:none;visibility:hidden;
  transition:opacity var(--dur) ease,visibility 0s linear var(--dur);
}
.wo-night-overlay.open{
  opacity:1;pointer-events:auto;visibility:visible;
  transition:opacity var(--dur) ease,visibility 0s linear 0s;
}
.wo-night-sheet{
  width:100%;max-width:560px;max-height:90vh;overflow-y:auto;
  padding:10px 18px calc(24px + env(safe-area-inset-bottom));
  border-radius:22px 22px 0 0;
  background:var(--app-bg);border:1px solid var(--app-border);border-bottom:none;
  translate:0 24px;transition:translate var(--dur) var(--spring);
}
.wo-night-overlay.open .wo-night-sheet{translate:0 0}
/* Same reason as .wo-drawer-head above: the top row of a sheet whose body
   scrolls, sitting inside makeDismissable's drag zone. Without touch-action
   the scroll container wins the gesture before the handler sees it. */
.wo-night-head,.wo-place-head,.wo-share-title,.wo-share-sub{touch-action:none}
.wo-night-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.wo-night-title{margin:0;font-family:var(--font-display);font-size:24px}
.wo-night-close{
  width:36px;height:36px;border-radius:50%;
  border:1px solid var(--app-border);background:transparent;
  color:var(--app-muted);font-size:22px;line-height:1;cursor:pointer;flex-shrink:0;
}
.wo-night-lede{font-size:14px;color:var(--app-muted);margin:2px 0 18px}
.wo-night-q{margin-bottom:18px}
.wo-night-label{
  font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  color:var(--app-muted);margin-bottom:8px;
}
.wo-night-opts{display:flex;flex-wrap:wrap;gap:8px}
.wo-night-opt{
  display:inline-flex;align-items:center;gap:6px;
  min-height:44px;padding:0 14px;border-radius:12px;
  border:1px solid var(--app-border);background:var(--app-card);
  color:var(--app-text,var(--text-1));
  font-family:var(--font-sans);font-size:14px;font-weight:700;cursor:pointer;
  transition:border-color var(--dur-fast) ease,background var(--dur-fast) ease;
}
.wo-night-opt.active{border-color:var(--app-green);background:rgba(var(--brand-rgb),.14);color:var(--app-green)}
.wo-night-go{
  width:100%;min-height:52px;margin-top:6px;border:none;border-radius:14px;
  background:linear-gradient(135deg,var(--brand-600),var(--accent-solid));
  color:#fff;font-family:var(--font-sans);font-size:16px;font-weight:800;cursor:pointer;
}
.wo-night-second{
  min-height:44px;padding:0 16px;border-radius:12px;
  border:1px solid var(--app-border);background:transparent;color:var(--app-muted);
  font-family:var(--font-sans);font-size:14px;font-weight:700;cursor:pointer;
}
.wo-night-note{font-size:12px;color:var(--app-muted);text-align:center;margin:10px 0 0}
.wo-night-fail{text-align:center;padding:20px 0 10px}

.wo-plan-title{font-family:var(--font-display);font-size:22px}
.wo-plan-sum{
  display:flex;gap:14px;flex-wrap:wrap;
  font-size:13px;font-weight:700;color:var(--app-muted);margin-top:2px;
}
.wo-plan-note{font-size:var(--t-xs);color:var(--warn);margin:10px 0 0}
.wo-plan-list{list-style:none;margin:18px 0 0;padding:0}
.wo-plan-stop{display:grid;grid-template-columns:62px 18px 1fr;gap:10px}
.wo-plan-time{
  font-size:14px;font-weight:800;font-variant-numeric:tabular-nums;
  text-align:right;padding-top:1px;
}
.wo-plan-rail{display:flex;flex-direction:column;align-items:center}
.wo-plan-dot{width:12px;height:12px;border-radius:50%;background:var(--app-green);margin-top:4px;flex-shrink:0}
.wo-plan-line{flex:1;width:2px;background:var(--app-border);margin:4px 0}
.wo-plan-body{padding-bottom:20px}
.wo-plan-name{font-size:16px;font-weight:800}
.wo-plan-pills{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}
.wo-pill{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-2xs);font-weight:600;color:var(--app-muted);
  background:rgba(255,255,255,.05);border:1px solid var(--app-border);
  border-radius:99px;padding:3px 10px;
}
.wo-pill-price{
  background:rgba(var(--brand-rgb),.14);border-color:rgba(var(--brand-rgb),.4);
  color:var(--app-green);font-weight:800;
}
.wo-plan-total{
  padding:14px;border-radius:12px;
  background:rgba(var(--brand-rgb),.1);border:1px solid rgba(var(--brand-rgb),.3);
  font-size:15px;
}
.wo-plan-total strong{font-size:19px;color:var(--app-green)}
.wo-plan-total-note{color:var(--app-muted);font-size:13px}
.wo-plan-total-empty{background:transparent;border-style:dashed;border-color:var(--app-border);
  color:var(--app-muted);font-size:14px}
.wo-linkish{
  background:none;border:none;padding:0;cursor:pointer;
  color:var(--app-green);font-weight:800;font-family:inherit;font-size:inherit;
}
.wo-plan-actions{display:flex;flex-direction:column;gap:8px;margin-top:18px}

/* ══════════════════════════════════════════════════════════════════════════
   ACROSS DEVICES

   Not one design scaled.

   A phone is one panel at a time under a compact head, swapped with the
   segmented control. A laptop has room for both panels at once, so they sit
   side by side with a hairline between them and the segmented control goes
   away entirely. Nothing about the markup changes; only which of the two
   panels is on screen, and how much room the head takes off the top.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── PHONE AND TABLET ──
   The segmented control is the panel head at these widths: it names the panel
   and carries the count. Printing both was the same fact twice, nine pixels
   apart, using space the listings needed. */
@media (max-width:999px){
  .wo-panel-head{display:none}
  .wo-panel-scroll{padding-top:12px}
}

/* ── PHONES ──
   Every pixel the fixed columns give up goes to the title. */
@media (max-width:520px){
  .wo-rail-wrap{margin:0 -14px;padding:0 14px}
  .wo-row{grid-template-columns:48px 22px minmax(0,1fr) auto 10px;gap:8px;padding:10px 10px}
  .wo-row-time{font-size:var(--t-xs)}
  .wo-row-title{font-size:var(--t-base)}
  .wo-row-ico{font-size:17px}
  .wo-hero-title{font-size:clamp(21px,5.6vw,27px)}
  .wo-top{padding:10px 14px 9px}
  .wo-panel-scroll{padding:0 14px 20px}
  .wo-panel-head{padding:10px 14px 7px}
}
/* Short screens: an SE, a phone in landscape, a small window. The head is what
   gives way, on a 568px-tall screen the chrome was most of the viewport and
   the listings got three rows. */
@media (max-height:680px) and (max-width:999px){
  .wo-hero-sub{display:none}
  .wo-hero-title{font-size:20px}
  .wo-top{padding:8px 14px 8px}
  .wo-switch{margin-top:8px}
}
/* A laptop window this short is short whatever its width. */
@media (max-height:540px){
  .wo-hero-sub{display:none}
  .wo-top{padding-top:10px;padding-bottom:8px}
}
@media (max-width:360px){
  .wo-row{grid-template-columns:44px 20px minmax(0,1fr) auto 8px;gap:7px}
  .wo-row-title{font-size:var(--t-sm)}
  .wo-day{min-width:68px;padding:8px 10px}
  .wo-det-actions>*{flex:1}
}

/* ── TABLET ── */
@media (min-width:760px){
  .wo-top{padding:16px 24px 12px}
  .wo-rail-wrap{margin:0 -24px;padding:0 24px}
  .wo-panel-head{padding:14px 24px 8px}
  .wo-panel-scroll{padding:0 24px 28px}
  .wo-row{min-height:66px;padding:11px 16px;grid-template-columns:64px 28px minmax(0,1fr) auto 16px}
  .wo-row-detail{padding:0 16px 16px}
  .wo-night-overlay{align-items:center}
  .wo-night-sheet{border-radius:22px;border-bottom:1px solid var(--app-border)}
}

/* ── LAPTOP AND UP ──
   Both panels at once. This is the width the layout is for: the night you
   picked on the left, the rest of the fortnight on the right, each scrolling
   on its own, and the controls above both of them never moving. */
@media (min-width:1000px){
  .wo-top{padding:20px 32px 14px}
  .wo-hero{padding:0 0 12px}
  .wo-hero-title{font-size:clamp(30px,2.6vw,40px)}
  .wo-hero-sub{font-size:var(--t-md)}

  /* There is room for the week and every kind, so nothing scrolls sideways
     and nothing is faded off the end of a row. */
  .wo-rail{overflow:visible}
  .wo-rail-wrap{margin:0 -32px;padding:0 32px}
  .wo-filter-bar{flex-wrap:wrap;overflow:visible;-webkit-mask-image:none;mask-image:none}
  .wo-day{min-width:78px}

  .wo-switch{display:none}
  .wo-panels{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  /* Both visible, whichever one the segmented control last chose. Same
     specificity as the rule that hides one, and later in the file. */
  .wo-panels[data-panel="day"]  .wo-panel--next,
  .wo-panels[data-panel="next"] .wo-panel--day{display:flex}
  .wo-panel + .wo-panel{border-left:1px solid var(--app-border)}
  .wo-panel-head{padding:16px 28px 10px}
  .wo-panel-scroll{padding:0 28px 32px}
}

/* ── WIDE ──
   A fixture list a metre wide puts the price a foot from the pub it belongs
   to, so past this width the rows stop growing and the columns take the
   slack instead. */
@media (min-width:1500px){
  .wo-top{padding:24px 48px 16px}
  .wo-rail-wrap{margin:0 -48px;padding:0 48px}
  .wo-panel-head{padding:18px 44px 10px}
  .wo-panel-scroll{padding:0 44px 36px}
  .wo-row{grid-template-columns:76px 30px minmax(0,1fr) auto 16px;min-height:70px;padding:12px 20px}
  .wo-row-title{font-size:var(--t-md)}
  .wo-row-sub{font-size:var(--t-sm)}
  .wo-row-detail{padding:0 20px 18px}
  .wo-list,.wo-section-divider,.wo-contribute{max-width:1000px}
}

/* ── HOW FAR AWAY ────────────────────────────────────────────────────────────
   Sits between the day rail and the kind chips, because that is the order the
   three questions are actually asked in: which night, how far am I willing to
   go, what kind of thing.

   Deliberately quieter than the chips beside it. The radius is a setting
   somebody sets once and forgets, it is remembered across visits, whereas
   the day and the kind are pressed constantly, and a third row of loud pills
   would make the top of the page look like a form. */
.wo-near{
  display:flex;
  align-items:center;
  gap:8px;
  margin-top:10px;
  min-height:28px;
  flex-wrap:wrap;
}

.wo-near-lab{
  font-size:var(--t-xs);
  font-weight:600;
  color:var(--app-muted);
  letter-spacing:.2px;
}

.wo-near-sel{
  appearance:none;
  -webkit-appearance:none;
  font-family:var(--font-sans);
  font-size:var(--t-xs);
  font-weight:700;
  color:var(--app-text);
  background:var(--app-card);
  border:1px solid var(--border);
  border-radius:var(--r-full);
  /* Room on the right for the chevron drawn by the background image below,
     appearance:none takes the native one away on every platform that had one. */
  padding:5px 26px 5px 12px;
  cursor:pointer;
  background-image:
    linear-gradient(45deg,transparent 50%,currentColor 50%),
    linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 14px) 52%,calc(100% - 9px) 52%;
  background-size:5px 5px,5px 5px;
  background-repeat:no-repeat;
}
.wo-near-sel:hover{ border-color:var(--border-strong) }
.wo-near-sel:focus-visible{ outline:2px solid var(--accent); outline-offset:2px }

/* The count of what is being held back. Amber rather than grey: it is the one
   line on this page that exists to contradict what the list is showing. */
.wo-near-note{
  font-size:var(--t-xs);
  color:var(--warn);
  min-width:0;
}
.wo-near-note:empty{ display:none }

@media (max-width:400px){
  .wo-near-note{ flex-basis:100%; }
}

/* ── WHERE THE RADIUS IS MEASURED FROM ───────────────────────────────────────
   Two controls beside the distance, and they are two because they fix two
   different faults. The arrow re-asks the browser, which is the answer to a
   cold GPS fix or a prompt that was never raised. The chip opens the town
   list, which is the answer to a refused permission, where no amount of
   asking will ever work, and a lone Retry is a button guaranteed to fail. */

.wo-near-of{
  font-size:var(--t-xs);
  color:var(--app-muted);
}

.wo-place-chip{
  display:inline-flex;align-items:center;gap:4px;
  max-width:14rem;
  font-family:var(--font-sans);
  font-size:var(--t-xs);font-weight:700;
  color:var(--app-text);
  background:var(--app-card);
  border:1px solid var(--border);
  border-radius:var(--r-full);
  padding:5px 12px;
  cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.wo-place-chip:hover{ border-color:var(--border-strong) }
.wo-place-chip:focus-visible{ outline:2px solid var(--accent); outline-offset:2px }
/* Not an error, it is a state the page can be in perfectly legitimately on a
   desktop, but it is the thing to press, so it is the thing that is lit. */
.wo-place-chip.is-unset{
  color:var(--warn);
  border-color:var(--warn-soft);
  background:var(--warn-soft);
}
.wo-place-pin{ font-size:12px; line-height:1 }

.wo-loc-btn{
  width:30px;height:30px;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:50%;
  border:1px solid var(--border);
  background:var(--app-card);
  color:var(--app-text);
  font-size:15px;line-height:1;
  cursor:pointer;
}
.wo-loc-btn:hover:not(:disabled){ border-color:var(--accent); color:var(--accent) }
.wo-loc-btn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px }
.wo-loc-btn:disabled{ cursor:default; color:var(--accent) }
/* A fix takes seconds and sometimes tens of seconds. Without something moving,
   the button reads as broken and gets pressed again, which cancels nothing
   and starts nothing, because the first request is still outstanding. */
.wo-loc-btn.is-busy span{
  display:block;
  animation:wo-spin 1s linear infinite;
}
@keyframes wo-spin{ to{ transform:rotate(360deg) } }
@media (prefers-reduced-motion:reduce){
  .wo-loc-btn.is-busy span{ animation:none; opacity:.5 }
}

/* ── THE TOWN PICKER ─────────────────────────────────────────────────────── */

.wo-place-overlay{
  position:fixed;inset:0;z-index:4300;
  background:rgba(0,0,0,.62);backdrop-filter:blur(3px);
  display:flex;align-items:flex-end;justify-content:center;
  opacity:0;pointer-events:none;visibility:hidden;
  transition:opacity var(--dur) ease,visibility 0s linear var(--dur);
}
.wo-place-overlay.open{
  opacity:1;pointer-events:auto;visibility:visible;
  transition:opacity var(--dur) ease,visibility 0s linear 0s;
}
.wo-place-sheet{
  width:100%;max-width:480px;max-height:85vh;
  display:flex;flex-direction:column;
  padding:10px 18px calc(18px + env(safe-area-inset-bottom));
  border-radius:22px 22px 0 0;
  background:var(--app-bg);border:1px solid var(--app-border);border-bottom:none;
  translate:0 24px;transition:translate var(--dur) var(--spring);
}
.wo-place-overlay.open .wo-place-sheet{ translate:0 0 }

.wo-place-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.wo-place-title{margin:0;font-family:var(--font-display);font-size:22px}
.wo-place-lede{font-size:14px;color:var(--app-muted);margin:2px 0 14px}

.wo-place-acts{display:flex;gap:8px;margin-bottom:12px}
.wo-place-gps{
  flex:1;
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  min-height:42px;padding:0 14px;
  border-radius:var(--r-lg);
  background:var(--accent-solid);border:1px solid var(--accent-solid);
  color:var(--on-accent);
  font-family:var(--font-sans);font-size:var(--t-sm);font-weight:700;
  cursor:pointer;
}
.wo-place-gps:hover{ background:var(--brand-500);border-color:var(--brand-500) }
.wo-place-clear{
  min-height:42px;padding:0 16px;
  border-radius:var(--r-lg);
  background:transparent;border:1px solid var(--border);
  color:var(--app-muted);
  font-family:var(--font-sans);font-size:var(--t-sm);font-weight:600;
  cursor:pointer;
}
.wo-place-clear:hover{ color:var(--app-text);border-color:var(--border-strong) }

.wo-place-search{
  width:100%;
  min-height:42px;padding:0 14px;
  border-radius:var(--r-lg);
  background:var(--app-card);border:1px solid var(--border);
  color:var(--app-text);
  font-family:var(--font-sans);font-size:var(--t-sm);
  outline:none;
}
.wo-place-search:focus{ border-color:var(--accent) }

/* Its own scroll, so the search box and the two buttons stay put while a
   thousand towns move underneath them. */
.wo-place-list{
  flex:1;min-height:0;overflow-y:auto;
  margin-top:10px;
  -webkit-overflow-scrolling:touch;
}
.wo-place-row{
  width:100%;
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  min-height:44px;padding:0 12px;
  background:transparent;border:none;
  border-bottom:1px solid var(--app-border);
  color:var(--app-text);
  font-family:var(--font-sans);font-size:var(--t-sm);
  text-align:left;cursor:pointer;
}
.wo-place-row:hover{ background:var(--hover) }
.wo-place-row.is-on{ color:var(--accent);font-weight:700 }
/* The tick on the selected row. A pseudo-element cannot carry a class, so
   it borrows .ic's mask directly rather than printing the character: one
   check mark in this app, and it is the one in the set. */
.wo-place-row.is-on::after{
  content:'';
  width:1em;height:1em;flex-shrink:0;
  background-color:currentColor;
  -webkit-mask:var(--ic-check) center/contain no-repeat;mask:var(--ic-check) center/contain no-repeat;
}
.wo-place-name{ overflow:hidden;text-overflow:ellipsis;white-space:nowrap }
.wo-place-n{ font-size:var(--t-xs);color:var(--app-muted);flex-shrink:0 }
.wo-place-none{ font-size:var(--t-sm);color:var(--app-muted);padding:18px 4px }

@media (min-width:620px){
  .wo-place-overlay{align-items:center}
  .wo-place-sheet{border-radius:22px;border-bottom:1px solid var(--app-border)}
}
