/* purchase-o5.css — O5 skin for the purchase page.
   Loaded on /{lang}/purchase/** (excluding /purchase/cart) via master.html isPurchase.
   Depends on option5.css for the --o5-* design tokens and base .o5-top/.o5-nav/.o5-footer.
   Folded from the design's "Old Product Selection.css": the shared oh/sid header+drawer
   block (matching the convention in about-o5.css, services-o5.css, etc.), the st-tier
   hover-reveal pills, and the page-specific op-* rules. No second stylesheet. */
/* FIX 1 — the purchase route does not load oh-overrides.css, whose
   `.o5-brand-logo-img { height:30px }` constrains the O5 header logo on
   every other O5 page. Without it the logo renders at the PNG's intrinsic
   size. Replicate that exact rule here so /purchase/ matches the home page. */
.sid-overlay{position:fixed;inset:0;background:rgba(20,20,20,0.5);backdrop-filter:blur(2px);opacity:0;pointer-events:none;transition:opacity .3s ease;z-index:200}
.sid-overlay.is-open{opacity:1;pointer-events:auto}
.sid-drawer{position:fixed;top:0;right:0;bottom:0;width:min(460px,92vw);background:var(--o5-surface);box-shadow:-30px 0 70px -24px rgba(0,0,0,0.35);transform:translateX(100%);transition:transform .38s cubic-bezier(.22,.61,.36,1);z-index:201;display:flex;flex-direction:column}
.sid-drawer.is-open{transform:translateX(0)}
.sid-scroll{overflow-y:auto;flex:1}
.sid-close{position:absolute;top:20px;right:20px;width:38px;height:38px;border-radius:50%;border:1px solid rgba(255,255,255,0.35);background:rgba(255,255,255,0.16);color:#fff;display:inline-flex;align-items:center;justify-content:center;z-index:5;transition:background .15s;cursor:pointer}
.sid-close:hover{background:rgba(255,255,255,0.3)}
.sid-hero{background:#d62133;color:#fff;padding:56px 36px 30px;position:relative;overflow:hidden}
.sid-hero::before{content:'';position:absolute;width:260px;height:260px;right:-110px;top:-130px;background:radial-gradient(circle,rgba(255,255,255,0.22),transparent 70%);border-radius:50%;pointer-events:none}
.sid-hero>*:not(.sid-close){position:relative;z-index:1}
.sid-eyebrow{font-size:10px;font-weight:800;letter-spacing:0.2em;text-transform:uppercase;color:rgba(255,255,255,0.9);display:block}
.sid-hero h2{font-family:var(--o5-display);font-size:26px;font-weight:800;letter-spacing:-0.02em;line-height:1.1;margin:12px 0 10px;color:#fff}
.sid-hero p{font-size:13.5px;color:rgba(255,255,255,0.88);line-height:1.55;margin:0}
.sid-perks{list-style:none;margin:16px 0 0;padding:0;display:flex;flex-direction:column;gap:9px}
.sid-perks li{display:flex;align-items:flex-start;gap:9px;font-size:13px;color:#fff}
.sid-perks li svg{flex:none;margin-top:2px}
.sid-form{padding:28px 36px 36px;background:var(--o5-surface)}
.sid-intro{font-size:13.5px;color:var(--o5-ink2);line-height:1.5;margin:0 0 14px}
.sid-sso-list{display:flex;gap:8px}
.sid-sso{display:flex;align-items:center;justify-content:center;gap:6px;flex:1;min-width:0;padding:11px 14px;border:1px solid var(--o5-line);border-radius:999px;background:var(--o5-surface);font-size:13px;font-weight:700;color:var(--o5-ink);cursor:pointer;text-decoration:none;transition:border-color .15s}
.sid-sso.is-compact{flex:0 0 auto;width:46px;padding:0;gap:0;aspect-ratio:1/1}
.sid-sso.is-compact .lbl{display:none}
.sid-sso:hover{border-color:var(--o5-ink)}
.sid-sso .ico{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;flex:none}
.sid-lg-google{width:16px;height:16px;background:conic-gradient(from -45deg,#ea4335 0deg 90deg,#fbbc04 90deg 180deg,#34a853 180deg 270deg,#4285f4 270deg 360deg);border-radius:50%;mask:radial-gradient(circle,transparent 26%,#000 27%) center/contain no-repeat;-webkit-mask:radial-gradient(circle,transparent 26%,#000 27%) center/contain no-repeat}
.sid-lg-apple svg{width:14px;height:16px}
.sid-or{display:block;font-size:13px;color:var(--o5-ink2);line-height:1.5;margin:20px 0 16px}
.sid-fields{display:flex;flex-direction:column;gap:12px}
.sid-field{display:block;width:100%;padding:14px 20px;border:1px solid var(--o5-line);border-radius:999px;background:var(--o5-surface);font-family:var(--o5-display);font-size:14px;font-weight:600;color:var(--o5-ink);outline:none;transition:border-color .15s;box-sizing:border-box}
.sid-field:focus{border-color:var(--o5-ink)}
.sid-field::placeholder{color:var(--o5-ink3);font-weight:500}
.sid-pwd{position:relative}
.sid-pwd input{padding-right:48px}
.sid-pwd .eye{position:absolute;top:50%;right:16px;transform:translateY(-50%);background:transparent;border:0;padding:0;color:var(--o5-ink2);cursor:pointer}
.sid-forgot{align-self:flex-end;display:inline-block;margin-top:2px;font-size:11.5px;font-weight:700;color:#d62133;text-decoration:none}
.sid-forgot:hover{color:#b91c2c}
.sid-toggle{display:grid;grid-template-columns:1fr 1fr;gap:0;padding:6px;border-radius:999px;background:var(--o5-surface-2);margin-top:18px}
.sid-toggle-btn{padding:13px 18px;border:0;border-radius:999px;background:transparent;font-family:var(--o5-display);font-size:13.5px;font-weight:800;color:var(--o5-ink2);cursor:pointer;transition:background .18s,color .18s,box-shadow .18s}
.sid-toggle-btn:hover{color:var(--o5-ink)}
.sid-toggle-btn.is-on{background:#d62133;color:#fff;box-shadow:0 6px 14px -8px rgba(214,33,51,0.45)}
.sid-foot{margin:22px 0 0;font-size:13px;color:var(--o5-ink2);text-align:center}
.sid-foot a{color:#d62133;font-weight:800}
@media (max-width:520px){.sid-hero{padding:52px 26px 26px}.sid-form{padding:24px 26px 30px}}
/* ── Old Product Selection — page-specific ── */
.op-timer{display:flex;align-items:center;gap:12px;padding:14px 20px;border-radius:var(--o5-r);background:linear-gradient(95deg,#fff6f0,#ffe9de);margin-bottom:32px;font-family:var(--o5-display)}
.op-timer-ic{width:34px;height:34px;border-radius:50%;background:#d62133;color:#fff;display:inline-flex;align-items:center;justify-content:center;flex:none}
.op-timer-body{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap;font-size:13.5px;color:var(--o5-ink2)}
.op-timer b{color:#d62133;font-weight:800;font-variant-numeric:tabular-nums;font-size:15px}
.op-timer a{color:var(--o5-ink);text-decoration:underline;text-underline-offset:2px;margin-left:auto;font-weight:700;font-size:12.5px;flex:none}
.op-timer a:hover{color:#d62133}
.op-step-num{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:50%;background:var(--o5-ink);color:#fff;font-family:var(--o5-display);font-size:12.5px;font-weight:800;margin-right:10px;flex:none;vertical-align:middle}
.op-card{background:var(--o5-surface);border:1px solid var(--o5-line);border-radius:var(--o5-r);padding:28px;box-shadow:0 2px 14px -10px rgba(0,0,0,0.08)}
.op-dt-block+.op-dt-block{margin-top:24px}
.op-dt-sublabel{font-family:var(--o5-display);font-size:10.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--o5-ink2);margin:0 0 12px}
.op-date-strip{display:flex;gap:10px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none}
.op-date-strip::-webkit-scrollbar{display:none}
.op-date-pill{flex:none;display:flex;flex-direction:column;align-items:center;gap:2px;width:66px;padding:12px 8px;border:1.5px solid var(--o5-line);border-radius:16px;background:var(--o5-surface);cursor:pointer;transition:border-color .15s,transform .15s,box-shadow .15s;font-family:var(--o5-display)}
.op-date-pill:hover{border-color:var(--o5-ink2);transform:translateY(-2px)}
.op-date-pill .dow{font-size:10px;font-weight:700;letter-spacing:.06em;color:var(--o5-ink2)}
.op-date-pill .dom{font-size:19px;font-weight:800;color:var(--o5-ink);line-height:1.15}
.op-date-pill .mon{font-size:10px;font-weight:700;letter-spacing:.06em;color:var(--o5-ink3)}
.op-date-pill.is-on{background:#fff6f5;border-color:#d62133}
.op-date-pill.is-on .dow,.op-date-pill.is-on .dom,.op-date-pill.is-on .mon{color:var(--o5-ink)}
.op-time-strip{display:flex;gap:10px;flex-wrap:wrap}
.op-time-pill{display:inline-flex;align-items:center;gap:7px;padding:12px 20px;border:1.5px solid var(--o5-line);border-radius:999px;background:var(--o5-surface);font-family:var(--o5-display);font-size:14px;font-weight:700;color:var(--o5-ink);cursor:pointer;transition:border-color .15s,background .15s,color .15s}
.op-time-pill:hover{border-color:var(--o5-ink2)}
.op-time-pill.is-on{background:#fff6f5;border-color:#d62133;color:var(--o5-ink)}
.op-proceed{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:17px 24px;margin-top:20px;border:0;border-radius:999px;background:#d62133;color:#fff;font-family:var(--o5-display);font-size:15.5px;font-weight:800;cursor:pointer;box-shadow:0 16px 30px -14px rgba(214,33,51,0.5);transition:background .15s,transform .15s}
.op-proceed:hover{background:#b91c2c;transform:translateY(-1px)}
.op-pay-methods{display:flex;gap:12px;margin-bottom:22px}
.op-pay-pill{flex:1;display:flex;align-items:center;gap:10px;padding:15px 20px;border-radius:16px;border:1.5px solid var(--o5-line);background:var(--o5-surface);font-family:var(--o5-display);font-size:14px;font-weight:700;color:var(--o5-ink);cursor:pointer;transition:border-color .15s,background .15s,color .15s,transform .15s}
.op-pay-pill:hover{transform:translateY(-1px)}
.op-pay-pill .radio{width:18px;height:18px;border-radius:50%;border:1.5px solid var(--o5-line3,var(--o5-ink3));flex:none;position:relative;transition:border-color .15s}
.op-pay-pill.is-on{border-color:#d62133;background:#fff6f5}
.op-pay-pill.is-on .radio{border-color:#d62133}
.op-pay-pill.is-on .radio::after{content:'';position:absolute;inset:3px;border-radius:50%;background:#d62133}
.op-total-due{background:#fff6f5!important;border:1.5px solid #d62133;color:var(--o5-ink)!important;box-shadow:none!important}
.op-terms{display:flex;align-items:flex-start;gap:10px;font-family:var(--o5-display);font-size:13px;color:var(--o5-ink);line-height:1.5;cursor:pointer;user-select:none;margin-bottom:22px}
.op-terms input{margin-top:2px}
.op-terms a{color:#d62133;font-weight:700}
.op-confirm{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:17px 24px;border:0;border-radius:999px;background:var(--o5-ink3);color:#fff;font-family:var(--o5-display);font-size:15.5px;font-weight:800;cursor:not-allowed;transition:background .15s,transform .15s}
.op-confirm.is-ready{background:#d62133;cursor:pointer;box-shadow:0 16px 30px -14px rgba(214,33,51,0.5)}
.op-confirm.is-ready:hover{background:#b91c2c;transform:translateY(-1px)}
.op-secure-note{font-size:12.5px;color:var(--o5-ink2);margin:0 0 20px}
/* Part 3 — card-skin the existing ticket rows WITHOUT changing the DOM tree
   seat-selection.js traverses (.closest('td').siblings() / .parents('.table-row')).
   Pure styling on the existing containers; every JS binding is untouched. */
.op-ticket-card{display:block;background:var(--o5-surface);border:1px solid var(--o5-line);border-radius:var(--o5-r);padding:16px 20px;margin-bottom:14px;box-shadow:0 2px 14px -10px rgba(0,0,0,0.08);transition:border-color .15s,box-shadow .15s}
.op-ticket-card:hover{border-color:var(--o5-ink3);box-shadow:0 10px 26px -16px rgba(0,0,0,0.18)}
.op-ticket-card .form-table,.op-ticket-card .form-table>tbody,.op-ticket-card .form-table tr{width:100%;border:0;background:transparent}
.op-ticket-card .form-table td{border:0!important;background:transparent!important;vertical-align:middle;padding:6px 8px}
.op-ticket-card .ticket-td{font-family:var(--o5-display);font-weight:800;font-size:15px;color:var(--o5-ink)}
.op-ticket-card .currency-span,.op-ticket-card .price-span{font-family:var(--o5-display);font-weight:700;color:var(--o5-ink)}
.op-ticket-card .quantity-input-group{display:inline-flex;align-items:center;border:1px solid var(--o5-line);border-radius:999px;overflow:hidden}
.op-ticket-card .quantity-input-group .btn{border:0;background:transparent;color:var(--o5-ink)}
.op-ticket-card .choose-ticket-btn{border-radius:999px}
/* Part 4 — card-skin the cart rail + confirm button. Classes + CSS only; the
   basket interior is server- and JS-rendered, so no structure/selectors change.
   #buy-button keeps its own enable/disable logic — styled via :disabled, NOT the
   design's is-ready toggle (which came from the reference JS we do not port). */
.op-cart-rail{background:var(--o5-surface);border:1px solid var(--o5-line);border-radius:var(--o5-r);padding:22px;box-shadow:0 2px 18px -12px rgba(0,0,0,0.12)}
.op-cart-rail .title h2{font-family:var(--o5-display);font-weight:800;font-size:18px;color:var(--o5-ink);margin-top:0}
.op-cart-rail .basket-total-price,.op-cart-rail #totalBasketPrice{font-family:var(--o5-display);font-weight:800;color:#d62133}
.op-buy-btn{background:#d62133!important;color:#fff!important;border:0!important;border-radius:999px!important;font-family:var(--o5-display);font-weight:800;box-shadow:0 16px 30px -14px rgba(214,33,51,0.5);transition:background .15s}
.op-buy-btn:hover{background:#b91c2c!important}
.op-buy-btn:disabled,.op-buy-btn.disabled{background:var(--o5-ink3)!important;box-shadow:none!important;cursor:not-allowed}

/* ═══════════ select-ticket.css — mockup-used st-*/stv-* rules ═══════════
   Folded from claude/designs/select-ticket.css (596 rules): only the layout / tier /
   summary / edit rules the mockup actually renders. Skipped families the mockup never
   uses: .st-merch*, .st-conc*, .st-bundle*, .st-alloc*, the tier-list variants
   (--minimal-line/list/table, --default-split) and the style switcher. --o5-* tokens
   come from option5.css. */
.st { background: var(--o5-bg); min-height: 100vh; }
.st-wrap {
  max-width: 1280px;
  margin: 0 auto;
  padding: 24px 32px 64px;
}
.st-back {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
  padding: 16px 0 12px;
  flex-wrap: wrap;
}
.st-back-btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--o5-display);
  font-size: 13px; font-weight: 600;
  color: var(--o5-ink2);
  text-decoration: none;
  padding: 8px 0;
  border-radius: 0;
  border: 0;
  background: transparent;
  transition: gap .15s ease, color .15s;
}
.st-back-btn:hover { color: var(--o5-accent, #ff6f3c); gap: 11px; }
.st-back-btn svg { color: currentColor; }
.st-header {
  margin: 12px 0 28px;
  padding-bottom: 24px;
  /* Design drops the rule under the page title -- the .op-section-card shells
     below now carry the structure. Design expressed this as
     `.st-header,.st-section-head{border-bottom:0!important}`; set at source here
     instead, since this file owns the rule and needs no override. */
  border-bottom: 0;
}
.st-header h1 {
  font-family: var(--o5-display);
  font-size: 36px; font-weight: 800;
  letter-spacing: -0.03em;
  margin: 0 0 8px;
  color: var(--o5-ink);
}
.st-sub {
  font-family: var(--o5-display);
  font-size: 15px; font-weight: 500;
  color: var(--o5-ink2);
  margin: 0 0 18px;
}
.st-main {
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 36px;
  align-items: start;
}
/* Grid items default to min-width:auto, so the 1fr track cannot shrink below the
   min-content width of its widest descendant. The left column still hosts legacy
   bootstrap markup (the .row/.col-md-* grids and the 5-tab .nav-tabs strip in the
   boxoffice_new / standard_new payment partials), which sets a wide floor. Without
   this, the 1fr track inflates past its share, the whole grid overflows .st-wrap,
   the page gets a horizontal scrollbar and the 400px cart rail is pushed off the
   right edge. Remove only once no legacy markup remains in either column. */
.st-main-l {
  min-width: 0;
}
.st-main-r {
  position: sticky;
  top: 88px;
  min-width: 0;
}
.st-tier-list { display: flex; flex-direction: column; gap: 12px; }
.st-tier {
  position: relative;
  background: var(--o5-surface);
  border: 1px solid var(--o5-line);
  border-radius: 18px;
  overflow: hidden;
  font-family: var(--o5-display);
  transition: border-color .18s, box-shadow .28s, transform .22s ease;
  box-shadow: 0 1px 2px rgba(0,0,0,0.025);
}
.st-tier.is-on {
  border-color: var(--o5-ink);
  border-width: 1.5px;
  box-shadow: 0 14px 36px -22px rgba(0,0,0,0.18);
}
.st-tier-ribbon-per,
.stv-split-ribbon-per { display: none; }
.st-summary-band .band-label { display: none; }
.st-tier-ribbon {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 20px;
  align-items: center;
  background: #e8e8ea;
  color: var(--o5-ink);
  padding: 18px 26px;
  border-bottom: 1px solid var(--o5-line);
}
.st-tier .st-tier-ribbon,
.stv-split .stv-split-ribbon { background: #e8e8ea !important; color: var(--o5-ink) !important; }
.st-tier-ribbon-l { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.st-tier-ribbon-name {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--o5-display);
  font-size: 17.5px; font-weight: 800;
  letter-spacing: -0.022em;
  color: var(--o5-ink);
}
.st-tier-ribbon-tag {
  font-family: var(--o5-display);
  font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--o5-silver);
  color: var(--o5-ink);
  line-height: 1.2;
}
.st-tier-ribbon-tag.is-pre { background: var(--o5-accent, #ff6f3c); color: #fff; }
.st-tier-ribbon-tag.is-vip { background: var(--o5-ink); color: #fff; }
.st-tier-ribbon-avail {
  font-family: var(--o5-display);
  font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  line-height: 1.2;
  background: var(--o5-silver);
  color: var(--o5-ink);
}
.st-tier-ribbon-avail.is-ok { background: #1f8a5b; color: #fff; }
.st-tier-ribbon-avail.is-few { background: #f5a623; color: #1a1a1a; }
.st-tier-ribbon-r { text-align: right; display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; }
.st-tier-ribbon-per {
  font-family: var(--o5-display);
  font-size: 8.5px; font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--o5-ink2);
}
.st-tier-ribbon-price {
  display: inline-flex; align-items: baseline; gap: 4px;
  justify-content: flex-end;
}
.st-tier-ribbon-price .ccy { font-family: var(--o5-display); font-size: 10.5px; font-weight: 700; color: var(--o5-ink2); }
.st-tier-ribbon-price .num { font-family: var(--o5-display); font-size: 21px; font-weight: 800; letter-spacing: -0.022em; color: var(--o5-ink); line-height: 1; }
.st-tier-body { position: relative; padding: 14px 24px 18px; }
.st-tier-desc {
  font-family: var(--o5-display);
  font-size: 13.5px;
  font-weight: 400;
  color: var(--o5-ink2);
  line-height: 1.6;
  margin: 0;
}
.stv-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--o5-display);
  font-size: 12.5px; font-weight: 700;
  letter-spacing: -0.005em;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--o5-line);
  background: var(--o5-surface);
  color: var(--o5-ink);
  cursor: pointer;
  white-space: nowrap;
}
.stv-pill svg { color: var(--o5-ink2); }
.stv-pill.is-on {
  background: var(--o5-surface-2);
  border-color: var(--o5-ink);
  color: var(--o5-ink);
}
.stv-pill.is-on svg { color: var(--o5-ink); }
.stv-pill.is-primary {
  margin-left: auto;
  background: var(--o5-ink);
  border-color: var(--o5-ink);
  color: #fff;
}
.stv-pill.is-primary svg { color: #fff; }
.stv-pill.is-step {
  margin-left: auto;
  padding: 4px 10px;
  gap: 20px;
  background: transparent;
  border: 1px solid var(--o5-ink);
  cursor: default;
}
.stv-pill.is-step button {
  width: 30px; height: 30px;
  border: 0; background: transparent;
  border-radius: 50%;
  color: var(--o5-ink);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.stv-pill.is-step button:disabled { opacity: 0.4; cursor: not-allowed; }
.stv-pill.is-step .val {
  min-width: 14px; text-align: center;
  font-family: var(--o5-display);
  font-size: 13.5px; font-weight: 800;
  color: var(--o5-ink);
}
.st-tier-pills {
  display: flex; align-items: center; gap: 8px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed transparent;
  flex-wrap: wrap;
}
.st-tier.is-open .st-tier-pills { border-top-color: var(--o5-line); }
.st-tier-pills .stv-pill { padding: 8px 14px; }
.st-tier-panel {
  margin-top: 14px;
  padding: 20px 22px;
  background: var(--o5-surface-2);
  border-radius: 14px;
}
.st-tier-panel--fp { padding: 16px 18px; }
.st-tier-panel--pol { padding: 20px 22px; }
.st-tier-incl {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px 24px;
}
.st-tier-body > .st-tier-incl { margin: 14px 18px 18px !important; padding: 20px 22px; }
.st-tier-incl li {
  display: flex; align-items: center; gap: 10px;
  font-size: 13.5px; font-weight: 400;
  color: var(--o5-ink);
  line-height: 1.6;
}
.st-tier-incl li .mark {
  flex-shrink: 0;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--o5-ink);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
}
.st-tier.is-on .st-tier-incl li .mark {
  background: var(--o5-ink);
  color: #fff;
}
.st-summary {
  background: var(--o5-surface);
  border: 1px solid var(--o5-line);
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 18px 40px -22px rgba(0,0,0,0.15);
  font-family: var(--o5-display);
}
.st-summary-band {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  background: #d62133;
  color: #fff;
  padding: 20px 22px 18px;
  border-bottom: 0;
}
.st-summary-band .pref {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--o5-display);
  font-size: 17px; font-weight: 800;
  letter-spacing: -0.018em;
  color: #fff;
  text-transform: none;
}
.st-summary-band .band-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: #fff;
  color: #d62133;
  font-family: var(--o5-mono, ui-monospace, monospace);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0;
}
.st-summary-band-r {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}
.st-summary-band .band-label {
  font-family: var(--o5-display);
  font-size: 8.5px; font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.7);
}
.st-summary-band .amt {
  display: inline-flex; align-items: baseline; gap: 4px;
  color: #fff;
  font-weight: 800;
  letter-spacing: -0.022em;
}
.st-summary-band .ccy { font-size: 13px; font-weight: 700; color: rgba(255,255,255,0.85); }
.st-summary-band .price { font-size: 24px; font-weight: 800; line-height: 1; color: #fff; }
.st-summary-body { padding: 22px 24px 24px; }
.st-summary-divider {
  margin: 18px 0;
  height: 1px;
  background: var(--o5-line);
  position: relative;
}
.st-summary-line {
  background: var(--o5-surface-2);
  border-radius: 12px;
  padding: 10px 12px;
}
.st-summary-line-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 10px;
  align-items: center;
}
.st-summary-line-title {
  flex: 1;
  min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
}
.st-summary-line-title b {
  font-family: var(--o5-display);
  font-size: 13.5px; font-weight: 800;
  letter-spacing: -0.012em;
  color: var(--o5-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.st-summary-line-sub {
  font-family: var(--o5-display);
  font-size: 11.5px; font-weight: 500;
  color: var(--o5-ink2);
  white-space: nowrap;
}
.st-summary-line-amt {
  font-size: 14px; font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--o5-ink);
  white-space: nowrap;
  justify-self: end;
}
.st-summary-line-step {
  display: inline-flex; align-items: center;
  background: var(--o5-surface);
  border: 1px solid var(--o5-line);
  border-radius: 999px;
  padding: 2px;
  flex: none;
}
.st-summary-line-step button {
  width: 24px; height: 24px;
  border: 0;
  background: transparent;
  border-radius: 50%;
  color: var(--o5-ink);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s;
}
.st-summary-line-step button:hover { background: var(--o5-surface-2); }
.st-summary-line-step > span {
  min-width: 20px;
  text-align: center;
  font-family: var(--o5-display);
  font-size: 12.5px; font-weight: 700;
  color: var(--o5-ink);
}
.st-summary-line-step button.remove {
  margin-left: 2px;
  border-left: 1px solid var(--o5-line);
  border-radius: 0 999px 999px 0;
  color: var(--o5-ink2);
  width: 26px;
}
.st-summary-line-step button.remove:hover { color: #d62133; background: transparent; }
.st-summary-fees {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 0 0;
  margin-bottom: 4px;
}
.st-summary-feerow {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px;
  font-size: 12.5px;
  color: var(--o5-ink2);
}
.st-summary-feerow > span:last-child { font-weight: 600; color: var(--o5-ink); }
.st-summary-feerow:first-child { font-weight: 700; color: var(--o5-ink); }
.st-summary-feerow:first-child > span:last-child { font-weight: 700; }
.st-summary-fees-divider {
  height: 1px;
  margin: 6px 0;
  background: var(--o5-line);
}
.st-summary-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 6px;
  padding: 24px 16px 22px;
  border: 1px dashed var(--o5-line);
  border-radius: 14px;
  margin-bottom: 14px;
}
.st-summary-empty .ico {
  width: 40px; height: 40px;
  border-radius: 12px;
  background: var(--o5-surface-2);
  color: var(--o5-ink2);
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: 4px;
}
.st-summary-empty b { font-size: 14px; font-weight: 700; color: var(--o5-ink); }
.st-summary-empty span { font-size: 12px; color: var(--o5-ink2); line-height: 1.45; }
.st-summary-cta {
  width: 100%;
  margin-top: 16px;
  background: #d62133;
  color: #fff;
  border: 0;
  padding: 16px 22px;
  border-radius: 999px;
  font-family: var(--o5-display);
  font-size: 14.5px; font-weight: 700;
  letter-spacing: -0.005em;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  transition: background .15s, transform .15s, box-shadow .15s;
  box-shadow: 0 14px 28px -14px rgba(214,33,51,0.6);
}
.st-summary-cta:hover:not(:disabled) { background: #b91c2c; box-shadow: 0 18px 32px -12px rgba(214,33,51,0.7); }
.st-summary-cta:active:not(:disabled) { transform: scale(0.99); }
.st-summary-cta:disabled {
  background: var(--o5-surface-2);
  color: var(--o5-ink3);
  cursor: not-allowed;
  box-shadow: none;
}
.st-summary-trust {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 16px;
  font-size: 11.5px;
  color: var(--o5-ink2);
}
.st-summary-trust span {
  display: inline-flex; align-items: center; gap: 6px;
}
.st-summary-trust span svg { color: var(--o5-ink3); flex-shrink: 0; }
.o5[data-theme="dark"] .st-tier-incl li .mark,
.o5[data-theme="dark"] .st-policy-ico,
.o5[data-theme="dark"] .st-summary-empty .ico,
.o5[data-theme="dark"] .st-tier-avail { background: #0a0a0a; }
.o5[data-theme="dark"] .st-summary-band,
.o5[data-theme="dark"] .st-summary-cta { background: #d62133; }
.o5[data-theme="dark"] .st-summary-cta:disabled { background: #0a0a0a; color: var(--o5-ink3); }
@media (max-width: 1080px) {
  .st-main { grid-template-columns: 1fr; }
  .st-main-r { position: static; }
  .st-summary { max-width: 480px; }
  .st-tier-incl { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .st-wrap { padding: 16px 18px 48px; }
  .st-header h1 { font-size: 28px; }
  .st-tier { padding: 18px 18px 14px; }
}
.st-section-head {
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 0;
}
.st-section-head h2 {
  /* design adds flex so the .op-step-num badge sits on the text baseline */
  display: flex;
  align-items: center;
  font-family: var(--o5-display);
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0 0 6px;
  color: var(--o5-ink);
}
.st-section-head p {
  font-family: var(--o5-display);
  font-size: 13px;
  color: var(--o5-ink2);
  margin: 0;
  line-height: 1.45;
}
.st-tier,
.stv-split {
  border-radius: 16px;
  background: var(--o5-surface);
  border: 1px solid var(--o5-line);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0,0,0,0.025);
  transition: background-color .15s, border-color .15s, box-shadow .22s;
}
.st-tier.is-on,
.stv-split.is-on {
  background: var(--o5-surface-2, #f7f5f0);
  border-color: var(--o5-ink2, #6b6b6b);
  border-width: 1px;
  box-shadow: 0 14px 36px -22px rgba(0,0,0,0.18);
}
.st-tier .st-tier-ribbon,
.stv-split .stv-split-ribbon {
  display: grid !important;
  grid-template-columns: 40px 1fr auto auto;
  gap: 16px;
  align-items: center;
  padding: 14px 18px !important;
  background: transparent !important;
  color: var(--o5-ink) !important;
  border-bottom: 1px solid transparent !important;
  font-family: var(--o5-display);
}
.st-tier.is-open .st-tier-ribbon,
.stv-split.is-open .stv-split-ribbon {
  border-bottom-color: var(--o5-line) !important;
}
.st-tier-ico,
.stv-split-ico {
  width: 40px; height: 40px;
  border-radius: 10px;
  background: var(--o5-surface-2, #f7f5f0);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--o5-ink);
  transition: background-color .15s, color .15s;
  flex: none;
}
.st-tier.is-on .st-tier-ico,
.stv-split.is-on .stv-split-ico {
  background: var(--o5-ink);
  color: #fff;
}
.st-tier .st-tier-ribbon-l,
.stv-split .stv-split-ribbon-l {
  display: flex !important;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.st-tier-ribbon-name,
.stv-split-ribbon-name {
  font-size: 14px !important;
  font-weight: 800 !important;
  letter-spacing: -0.015em !important;
  color: var(--o5-ink) !important;
  display: inline-flex !important;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.st-tier-ribbon-sub,
.stv-split-ribbon-sub {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--o5-ink2);
  line-height: 1.4;
}
.st-tier-ribbon-tag,
.stv-split-ribbon-tag {
  font-size: 9px !important;
  font-weight: 800 !important;
  letter-spacing: 0.1em !important;
  text-transform: uppercase !important;
  padding: 3px 8px !important;
  border-radius: 999px !important;
  line-height: 1.2 !important;
  background: var(--o5-accent, #ff6f3c) !important;
  color: #fff !important;
}
.st-tier-ribbon-tag.is-vip,
.st-tier-ribbon-tag.is-suite { background: var(--o5-ink) !important; color: #fff !important; }
.st-tier-ribbon-avail,
.stv-split-ribbon-avail {
  font-size: 9px !important;
  font-weight: 800 !important;
  letter-spacing: 0.1em !important;
  text-transform: uppercase !important;
  padding: 3px 8px !important;
  border-radius: 999px !important;
  line-height: 1.2 !important;
  color: #fff !important;
}
.st-tier-ribbon-avail.is-ok,
.stv-split-ribbon-avail.is-ok { background: var(--o5-green, #1f8a5b) !important; color: #fff !important; }
.st-tier-ribbon-avail.is-few,
.stv-split-ribbon-avail.is-few { background: #f5a623 !important; color: #fff !important; }
.st-tier-ribbon-avail.is-limited,
.stv-split-ribbon-avail.is-limited { background: var(--o5-ink) !important; color: #fff !important; }
.st-tier .st-tier-ribbon-r,
.stv-split .stv-split-ribbon-r {
  flex-direction: row !important;
  align-items: baseline !important;
  gap: 4px !important;
  white-space: nowrap;
  text-align: right;
}
.st-tier-ribbon-price,
.stv-split-ribbon-price {
  display: inline-flex !important;
  align-items: baseline;
  gap: 4px;
  font-family: var(--o5-display);
}
.st-tier-ribbon-price .ccy,
.stv-split-ribbon-price .ccy {
  font-size: 11px !important;
  font-weight: 700 !important;
  color: var(--o5-ink2) !important;
}
.st-tier-ribbon-price .num,
.stv-split-ribbon-price .num {
  font-size: 16px !important;
  font-weight: 800 !important;
  letter-spacing: -0.018em !important;
  color: var(--o5-ink) !important;
}
.st-tier .st-tier-body,
.stv-split .stv-split-body {
  padding: 0 !important;
}
.st-tier .st-tier-pills,
.stv-split .stv-split-pills {
  margin-left: 18px !important;
  margin-right: 18px !important;
  border-top: 1px solid transparent;
  gap: 8px;
  flex-wrap: wrap;
}
.st-tier.is-open .st-tier-pills,
.stv-split.is-open .stv-split-pills,
.st-tier:hover .st-tier-pills,
.stv-split:hover .stv-split-pills {
  border-top-color: var(--o5-line);
}
.st-tier .st-tier-pills .stv-pill,
.stv-split .stv-split-pills .stv-pill { padding: 8px 14px; font-size: 13px; }
.st-tier-ribbon-per,
.stv-split-ribbon-per { display: none !important; }
.st-tier .st-tier-panel,
.stv-split .stv-split-panel {
  margin: 14px 18px 18px !important;
  padding: 20px 22px;
  background: oklch(0.97 0.005 80);
  border-radius: 12px;
}
.st-addon-svg {
  width: 18px; height: 18px;
  stroke: currentColor;
  stroke-width: 1.7;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.st-addon-pills .stv-pill { padding: 8px 14px; font-size: 13px; }
.st-addon-panel .st-tier-incl {
  background: transparent;
  padding: 0;
  margin: 0;
  border-radius: 0;
}
.st-summary-sections { display: flex; flex-direction: column; gap: 14px; margin-bottom: 14px; }
@media (max-width: 720px) {
  .st-section-head h2 { font-size: 22px; }
}
.st-tier {
  cursor: default;
  transition: border-color .18s, box-shadow .28s, transform .22s ease;
  box-shadow: 0 1px 2px rgba(0,0,0,0.025);
}
.st-tier:hover {
  transform: translateY(-2px);
  border-color: var(--o5-ink2);
  box-shadow: 0 18px 36px -22px rgba(0,0,0,0.22);
}
.st-tier.is-on { transform: translateY(0); }
.st-tier.is-on:hover {
  transform: translateY(-2px);
  box-shadow: 0 22px 44px -22px rgba(0,0,0,0.28);
}
.st-tier:hover .st-tier-name { letter-spacing: -0.018em; }
.stv-pill {
  position: relative;
  transition: background .15s, color .15s, border-color .15s, transform .15s, box-shadow .2s;
}
.stv-pill:hover {
  border-color: var(--o5-ink);
  transform: translateY(-1px);
  box-shadow: 0 6px 14px -10px rgba(0,0,0,0.2);
}
.stv-pill:active { transform: translateY(0) scale(0.96); transition-duration: 80ms; }
.stv-pill svg { transition: transform .25s ease, color .15s; }
.stv-pill:hover svg { transform: scale(1.12); }
.stv-pill.is-on svg { color: var(--o5-ink); }
.stv-pill.is-on {
  animation: stPillPop 0.32s cubic-bezier(.34,1.56,.64,1);
}
.stv-pill.is-primary {
  background: var(--o5-ink);
  box-shadow: 0 4px 10px -4px rgba(0,0,0,0.25);
  transition: background .15s, transform .15s, box-shadow .2s;
}
.stv-pill.is-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 28px -10px rgba(0,0,0,0.4);
}
.stv-pill.is-primary:active {
  transform: translateY(0) scale(0.97);
  box-shadow: 0 4px 10px -4px rgba(0,0,0,0.25);
  transition-duration: 80ms;
}
.stv-pill.is-step { box-shadow: 0 1px 2px rgba(0,0,0,0.04); }
.stv-pill.is-step:hover { transform: none; box-shadow: 0 6px 14px -8px rgba(0,0,0,0.18); }
.stv-pill.is-step button {
  transition: background .14s ease, transform .14s ease, color .14s;
}
.stv-pill.is-step button:hover:not(:disabled) {
  background: var(--o5-surface-2);
  transform: scale(1.08);
}
.stv-pill.is-step button:active:not(:disabled) {
  transform: scale(0.88);
  transition-duration: 80ms;
}
.stv-pill.is-step .val {
  transition: transform .2s cubic-bezier(.34,1.56,.64,1);
  display: inline-block;
}
.stv-pill.is-step .val { animation: stValPop 0.3s ease; }
.st-tier-panel {
  animation: stPanelIn 0.26s cubic-bezier(.4,0,.2,1);
}
.st-tier-incl li {
  animation: stInclIn 0.34s ease backwards;
}
.st-tier-incl li:nth-child(1) { animation-delay: 0.05s; }
.st-tier-incl li:nth-child(2) { animation-delay: 0.09s; }
.st-tier-incl li:nth-child(3) { animation-delay: 0.13s; }
.st-tier-incl li:nth-child(4) { animation-delay: 0.17s; }
.st-tier-incl li:nth-child(5) { animation-delay: 0.21s; }
.st-tier-incl li:nth-child(6) { animation-delay: 0.25s; }
.st-tier-incl li .mark { transition: background .15s, transform .25s ease; }
.st-tier-incl li:hover .mark { transform: scale(1.12) rotate(-6deg); }
.st-tier:hover .st-tier-seat { color: var(--o5-ink); }
@media (prefers-reduced-motion: reduce) {
  .st-tier, .stv-pill, .st-tier-panel, .st-tier-incl li, .stv-pol-chip, .stv-fp-zone, .st-tier-tag.is-pre::after, .stv-pill.is-step .val, .st-tier-name {
    animation: none !important;
    transition: none !important;
  }
  .st-tier:hover { transform: none; }
  .stv-pill:hover, .stv-pill:active { transform: none; }
}
.st-tier,
.stv-split {
  border-radius: 14px !important;
  background: var(--o5-surface) !important;
  border: 1px solid var(--o5-line) !important;
  border-width: 1px !important;
  box-shadow: none !important;
  transform: none !important;
  transition: background-color .15s, border-color .15s !important;
}
.st-tier:hover,
.stv-split:hover {
  transform: none !important;
  box-shadow: none !important;
  border-color: var(--o5-line) !important;
}
.st-tier.is-on,
.stv-split.is-on {
  background: #fff6f5 !important;
  border-color: #d62133 !important;
  box-shadow: none !important;
  transform: none !important;
}
.st-tier.is-on:hover,
.stv-split.is-on:hover { transform: none !important; box-shadow: none !important; }
.st-tier.is-open,
.stv-split.is-open { background: var(--o5-surface-2, #f7f5f0) !important; }
.st-tier-name,
.st-tier:hover .st-tier-name { transition: none !important; letter-spacing: -0.015em !important; }
.st-tier-ribbon-tag::after,
.st-tier-tag::after,
.st-tier-tag.is-pre::after { display: none !important; animation: none !important; }
.st-summary-edits {
  display: flex; flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}
.st-edit {
  background: transparent;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--o5-silver, #ecebe6);
  transition: border-color .18s, background .18s;
}
.st-edit.is-editing {
  background: var(--o5-surface);
  border-color: var(--o5-ink);
}
.st-edit-row {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
}
.st-edit--event .st-edit-row {
  grid-template-columns: 52px 1fr;
  gap: 12px;
  padding: 12px;
  align-items: center;
}
.st-edit-thumb {
  width: 52px; height: 52px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid var(--o5-line);
  display: flex; align-items: center; justify-content: center;
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  background-image: repeating-linear-gradient(45deg, transparent 0 6px, rgba(0,0,0,0.03) 6px 7px);
}
.st-edit-thumb-lbl {
  font-family: var(--o5-mono, ui-monospace, monospace);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--o5-ink3);
  padding: 2px 5px;
  background: rgba(255,255,255,0.85);
  border-radius: 3px;
}
.st-edit--event .st-edit-body { gap: 2px; }
.st-edit--event .st-edit-k { margin-bottom: 1px; }
.st-edit--event .st-edit-v {
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.2;
}
.st-edit-sub {
  font-family: var(--o5-display);
  font-size: 12px;
  font-weight: 500;
  color: var(--o5-ink2);
  line-height: 1.35;
  margin-top: 2px;
}
.st-edit-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  color: var(--o5-ink2);
}
.st-edit-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.st-edit-k {
  font-family: var(--o5-display);
  font-size: 9.5px; font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--o5-ink3);
}
.st-edit-v {
  font-family: var(--o5-display);
  font-size: 13.5px; font-weight: 700;
  letter-spacing: -0.012em;
  color: var(--o5-ink);
}
.st-edit-btn {
  background: transparent;
  border: 0;
  padding: 4px;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--o5-ink2);
  cursor: pointer;
  transition: color .15s, transform .15s;
}
.st-edit-btn:hover {
  color: var(--o5-ink);
  transform: scale(1.06);
}
.st-edit-btn:active { transform: scale(0.94); }
.st-edit-btn--text {
  width: auto; height: auto;
  padding: 6px 14px;
  border: 1px solid var(--o5-silver, #ecebe6);
  border-radius: 999px;
  font-family: var(--o5-display);
  font-size: 12px; font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--o5-ink);
}
.st-edit-btn--text:hover {
  border-color: var(--o5-ink);
}
.st-edit.is-editing .st-edit-btn--text {
  width: 28px; height: 28px;
  padding: 0;
  border-radius: 50%;
}
.st-edit.is-editing .st-edit-btn {
  background: var(--o5-ink);
  border-radius: 50%;
  color: #fff;
}
.st-edit-btn:focus { outline: none; }
.st-edit-btn:focus-visible {
  outline: 2px solid var(--o5-ink);
  outline-offset: 2px;
}
.st-edit.is-readonly { background: var(--o5-surface-2); border-color: var(--o5-silver, #ecebe6); }
.st-edit.is-readonly .st-edit-row { padding: 10px 12px; }
@media (prefers-reduced-motion: reduce) {
  .st-edit-pick, .st-edit-btn, .st-edit-date, .st-edit-time {
    animation: none !important;
    transition: none !important;
  }
  .st-edit-btn:hover, .st-edit-date:hover, .st-edit-time:hover { transform: none !important; }
}
@keyframes stPillPop {
  0% { transform: scale(0.94); }
  60% { transform: scale(1.04); }
  100% { transform: scale(1); }
}
@keyframes stValPop {
  0% { transform: scale(1); }
  40% { transform: scale(1.22); }
  100% { transform: scale(1); }
}
@keyframes stPanelIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes stInclIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* FIX #3 root cause: purchase.css styles the legacy step headings with high
   specificity (e.g. .purchase-page #performance-selection .select-performance
   h1{display:table}), distorting the .op-step-num box into a black ellipse.
   Target the span directly under the heading contexts (0,4,1) and hard-lock
   its square so it holds regardless of the parent layout. No !important. */
.purchase-page .select-performance h1 .op-step-num,
.purchase-page .sec-title h1 .op-step-num {
  display:inline-flex; width:26px; min-width:26px; max-width:26px; height:26px;
  flex:none; box-sizing:border-box; padding:0; border-radius:50%;
}

/* Desktop cart .st-summary bridging. The Group C money markup (basket-*/ticket-item)
   is preserved and layered under the design shell; Total due reuses .basket-tickets-total
   (fed totalPrice by updateBasket, unchanged). CSS only — no value/calc change. */
.st-summary .info-box{border:0;padding:0;background:transparent}
.st-summary .info-box.tickets-total{display:flex;align-items:center;justify-content:space-between;background:#fff6f5;border:1.5px solid #d62133;border-radius:var(--o5-r);padding:16px 20px;margin-top:16px}
.st-summary .info-box.tickets-total .total-label{font-family:var(--o5-display);font-weight:800;color:var(--o5-ink);float:none}
.st-summary .info-box.tickets-total .basket-tickets-total{font-family:var(--o5-display);font-weight:800;color:#d62133;float:none}
.st-summary .info-box.tickets-total .basket-tickets-total .price-span{color:#d62133}
.st-summary .basket-performance-date{display:flex;justify-content:space-between;font-family:var(--o5-display);font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--o5-ink2);padding:12px 0}
.st-summary .ticket-item.st-summary-line{padding:12px 0;border-bottom:1px solid var(--o5-line)}
.st-summary .basket-ticket-name{font-family:var(--o5-display);font-weight:800;color:var(--o5-ink)}
.st-summary .info-box.promotion-code{margin-top:14px}
.st-summary .ticket-delete{color:var(--o5-ink3)}
.st-summary .ticket-delete:hover{color:#d62133}

/* == cart rail line layout fix ==
   updateBasket emits several label/value pairs inside one
   .st-summary-line-row, which is flex - so the pairs were laid out side
   by side and collided. Stack the pairs, make each pair the flex row,
   and neutralise the bootstrap floats. No JS change, no value change. */
.st-summary .ticket-inner.st-summary-line-row {
  display: block;
}
.st-summary .ticket-inner.st-summary-line-row > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0;
  min-width: 0;
}
.st-summary .ticket-inner.st-summary-line-row > div::before,
.st-summary .ticket-inner.st-summary-line-row > div::after {
  content: none;
}
.st-summary .ticket-inner .pull-left,
.st-summary .ticket-inner .pull-right {
  float: none !important;
}
.st-summary .ticket-inner .info-label {
  text-align: left;
  min-width: 0;
}
.st-summary .ticket-inner .info-text {
  text-align: right;
  white-space: nowrap;
  flex: none;
}
.st-summary .ticket-inner .ticket-delete {
  margin-left: 8px;
}

/* Event card: the design reserves a 52px column for a thumbnail we do
   not render (no backing field), which squeezed the event name into the
   remainder and wrapped it one word per line. Collapse to one column
   when no thumbnail is present. */
/* [A1.2] design is HORIZONTAL: 52px thumbnail column + 1fr body
   (Old Shopping Cart.css:286). An earlier fix for a wrapped event name forced
   this to a single stacked column, which is what made the event card stack. */
.st-summary .st-edit--event .st-edit-row {
  grid-template-columns: 52px 1fr;
  gap: 12px;
  padding: 12px;
  align-items: center;
}
.st-summary .st-edit--event .st-edit-v {
  white-space: normal;
  word-break: normal;
  overflow-wrap: anywhere;
}

/* ═══════════ Old Product Selection.css — new design set ═══════════
   Folded from claude/designs/Old Product Selection.css. The design set was
   replaced; this block carries the families the *current* design introduces and
   that this file did not already have: the .op-section-card shells, the .op-row
   product rows, the restructured cart internals (.op-cart-info / .op-cart-card /
   .op-promo / .op-grand-total) and the admin checkout form (.op-admin-*).

   Not folded, deliberately:
   - .op-role-toggle / .op-role-btn / .op-pay-admin{display:none} /
     #opPayCard.is-admin-role -- the mockup's CLIENT-SIDE customer/admin switch.
     The admin panel is gated server-side on ${isBoxOfficeUser}; shipping these
     would put the box-office form (and the #isBoxOfficeUser element that
     seat-selection.js treats as a capability probe) into every customer's DOM
     behind nothing but a CSS display:none. Kept out so the rules cannot tempt
     anyone back to the client toggle.
   - .st-tier-pills hover-reveal (max-height:0 until :hover) -- from the
     superseded design iteration, and it would hide the primary add-to-basket
     control behind hover, which is unusable on touch. Repo's always-visible
     flex version is kept.
   - .oh-* (header/footer/account panel, owned by option5.css + the o5-header
     fragment) and .sid-* (sign-in drawer, not on this page).

   .op-admin-grid is taken from this aggregate rather than the per-section
   extract: only the aggregate carries the @media (max-width:720px) collapse to
   one column. The six per-section extracts were verified to be strict subsets
   (zero selectors absent from this file + select-ticket.css), so they are
   ignored as sources. --o5-* tokens come from option5.css. */
.op-section-card{background:var(--o5-surface);border:1px solid var(--o5-line);border-radius:var(--o5-r);overflow:hidden;box-shadow:0 2px 14px -10px rgba(0,0,0,0.08)}
.op-section-card-head{background:var(--o5-surface-2);padding:22px 28px;border-bottom:1px solid var(--o5-line)}
.op-section-card-head h2{margin:0 0 6px;display:flex;align-items:center;font-family:var(--o5-display);font-size:20px;font-weight:800;letter-spacing:-.02em;color:var(--o5-ink)}
.op-section-card-head p{margin:0;font-family:var(--o5-display);font-size:13px;color:var(--o5-ink2);line-height:1.45}
.op-section-card-body{padding:28px}
/* ── Shopping Cart restructure ── */
.op-cart-info{background:var(--o5-surface-2);border-radius:12px;margin-top:14px}
.op-cart-info-row{display:flex;align-items:baseline;gap:10px;padding:10px 12px}
.op-cart-info-row+.op-cart-info-row{border-top:1px solid var(--o5-silver,#ecebe6)}
.op-cart-info-k{font-family:var(--o5-display);font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--o5-ink3);flex:none}
.op-cart-info-v{font-family:var(--o5-display);font-size:13px;font-weight:700;color:var(--o5-ink);margin-right:auto}
.op-cart-info-edit{flex:none;width:26px;height:26px;border-radius:50%;border:1px solid var(--o5-line);background:var(--o5-surface);color:var(--o5-ink2);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:border-color .15s,color .15s}
.op-cart-info-edit:hover{border-color:var(--o5-ink);color:var(--o5-ink)}
.op-cart-card{background:var(--o5-surface-2);border-radius:16px;padding:16px 18px;margin-bottom:10px}
.op-cart-card:last-child{margin-bottom:0}
.op-cart-card-head{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.op-cart-card-head b{font-family:var(--o5-display);font-size:14.5px;font-weight:800;letter-spacing:-.012em;color:var(--o5-ink);flex:1;min-width:0}
.op-cart-card-qty{font-family:var(--o5-display);font-size:13px;font-weight:700;color:var(--o5-ink2)}
.op-cart-card-del{flex:none;width:28px;height:28px;border-radius:50%;border:0;background:transparent;color:var(--o5-ink3);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s,color .15s}
.op-cart-card-del:hover{background:var(--o5-surface);color:#d62133}
.op-cart-card-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:6px 0;font-family:var(--o5-display);font-size:13px;color:var(--o5-ink2)}
.op-cart-card-row>span:first-child{display:inline-flex;align-items:center;gap:6px}
.op-cart-card-row>span:last-child{font-weight:700;color:var(--o5-ink)}
.op-cart-card-divider{height:1px;background:var(--o5-line);margin:6px 0}
.op-cart-card-row--total{padding-top:8px}
.op-cart-card-row--total>span{font-weight:800!important;color:var(--o5-ink)!important;font-size:13.5px}
.op-cart-tip{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;border:1px solid var(--o5-ink3);color:var(--o5-ink3);font-size:10px;font-weight:700;cursor:help}
.op-promo{margin-top:18px}
.op-promo-label{font-family:var(--o5-display);font-size:13.5px;font-weight:600;color:var(--o5-ink);margin:0 0 10px}
.op-promo-field{position:relative;margin-bottom:12px}
.op-promo-field input{width:100%;padding:13px 42px 13px 18px;border:1px solid var(--o5-line);border-radius:999px;background:var(--o5-surface);font-family:var(--o5-display);font-size:13.5px;font-weight:600;color:var(--o5-ink);outline:none;transition:border-color .15s;box-sizing:border-box}
.op-promo-field input:focus{border-color:var(--o5-ink)}
.op-promo-field input::placeholder{color:var(--o5-ink3);font-weight:500}
.op-promo-pencil{position:absolute;top:50%;right:16px;transform:translateY(-50%);color:var(--o5-ink3);pointer-events:none}
.op-promo-apply{display:flex;align-items:center;justify-content:center;width:100%;padding:14px;border:0;border-radius:999px;background:var(--o5-surface-2);color:var(--o5-ink);font-family:var(--o5-display);font-size:14.5px;font-weight:800;cursor:pointer;transition:background .15s}
.op-promo-apply:hover{background:var(--o5-line)}
.op-grand-total{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:14px;padding:16px 20px;border:1.5px solid #d62133;border-radius:999px;background:#fff6f5}
.op-grand-total-lbl{display:inline-flex;align-items:baseline;gap:6px;flex-wrap:wrap;font-family:var(--o5-display)}
.op-grand-total-lbl b{font-size:14.5px;font-weight:800;color:var(--o5-ink)}
.op-grand-total-lbl i{font-style:normal;font-size:11.5px;font-weight:700;color:var(--o5-ink)}
.op-grand-total-amt{font-family:var(--o5-display);font-size:18px;font-weight:800;color:#d62133;white-space:nowrap}
.op-grand-total-amt .ccy{font-size:11px;font-weight:700;margin-right:3px}
/* ── Add-ons section ── */
.op-row-list{display:flex;flex-direction:column}
.op-row{border-bottom:1px solid var(--o5-line)}
.op-row:last-child{border-bottom:0}
.op-row-main{display:grid;grid-template-columns:1fr auto;gap:24px;align-items:center;padding:22px 0}
.op-row-l{min-width:0}
.op-row-title{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.op-row-title b{font-family:var(--o5-display);font-size:21px;font-weight:800;letter-spacing:-.02em;color:var(--o5-ink)}
.op-row-tag{font-family:var(--o5-display);font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:5px 12px;border-radius:999px;background:var(--o5-ink);color:#fff;line-height:1.2}
.op-row-tag.is-pre{background:var(--o5-accent,#ff6f3c)}
.op-row-tag.is-few{background:#f5a623;color:#1a1a1a}
.op-row-desc{margin:8px 0 0;font-family:var(--o5-display);font-size:14px;color:var(--o5-ink2)}
.op-row-r{display:flex;align-items:center;gap:18px;flex:none}
.op-row-price{display:inline-flex;align-items:baseline;gap:5px;white-space:nowrap;font-family:var(--o5-display)}
.op-row-price .ccy{font-size:12px;font-weight:700;color:var(--o5-ink2)}
.op-row-price .num{font-size:25px;font-weight:800;letter-spacing:-.02em;color:var(--o5-ink)}
.op-row-r .stv-pill{flex:none}
/* ── Admin purchase form ── */
.op-admin-pay{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:22px}
.op-admin-sub{display:flex;flex-wrap:wrap;gap:14px 26px;margin:-8px 0 22px}
.op-admin-sub:empty{margin:0}
.op-admin-sub-opt{display:inline-flex;align-items:center;gap:9px;font-family:var(--o5-display);font-size:13px;font-weight:600;color:var(--o5-ink2);cursor:pointer;user-select:none;transition:color .15s}
.op-admin-sub-opt input{position:absolute;opacity:0;width:0;height:0}
.op-admin-sub-mark{width:18px;height:18px;flex:none;border:1.5px solid var(--o5-ink3);background:var(--o5-surface);display:inline-flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s;position:relative}
.op-admin-sub-opt input[type="checkbox"]+.op-admin-sub-mark{border-radius:50%}
.op-admin-sub-opt input[type="radio"]+.op-admin-sub-mark{border-radius:50%}
.op-admin-sub-mark svg{width:11px;height:11px;opacity:0;transition:opacity .15s}
.op-admin-sub-opt input[type="radio"]+.op-admin-sub-mark::after{content:'';width:8px;height:8px;border-radius:50%;background:#d62133;opacity:0;transform:scale(.4);transition:opacity .15s,transform .15s}
.op-admin-sub-opt input:checked+.op-admin-sub-mark{border-color:#d62133;background:#d62133}
.op-admin-sub-opt input[type="radio"]:checked+.op-admin-sub-mark{background:var(--o5-surface)}
.op-admin-sub-opt input[type="radio"]:checked+.op-admin-sub-mark::after{opacity:1;transform:scale(1)}
.op-admin-sub-opt input[type="checkbox"]:checked+.op-admin-sub-mark svg{opacity:1}
.op-admin-sub-opt:hover .op-admin-sub-mark{border-color:var(--o5-ink2)}
.op-admin-sub-opt:has(input:checked){color:var(--o5-ink)}
.op-admin-pill{padding:13px 20px;border-radius:999px;border:1.5px solid transparent;background:var(--o5-surface-2);font-family:var(--o5-display);font-size:12.5px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--o5-ink);cursor:pointer;transition:background .15s,color .15s,border-color .15s}
.op-admin-pill:hover{border-color:#d62133}
.op-admin-pill.is-on{background:#fff6f5;border-color:#d62133;color:var(--o5-ink)}
.op-admin-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
.op-admin-field{position:relative}
.op-admin-field input{width:100%;padding:15px 44px 15px 18px;border:1px solid var(--o5-line);border-radius:14px;background:var(--o5-surface);font-family:var(--o5-display);font-size:14px;font-weight:600;color:var(--o5-ink);outline:none;transition:border-color .15s;box-sizing:border-box}
.op-admin-field input:focus{border-color:var(--o5-ink)}
.op-admin-field input::placeholder{color:var(--o5-ink3);font-weight:500}
.op-admin-field svg{position:absolute;top:50%;right:16px;transform:translateY(-50%);color:var(--o5-ink3);pointer-events:none}
.op-admin-notes-wrap{position:relative;margin-bottom:20px}
.op-admin-notes{width:100%;min-height:140px;padding:16px 44px 16px 18px;border:1px solid var(--o5-line);border-radius:16px;background:var(--o5-surface);font-family:var(--o5-display);font-size:14px;font-weight:500;color:var(--o5-ink);outline:none;resize:vertical;box-sizing:border-box}
.op-admin-notes:focus{border-color:var(--o5-ink)}
.op-admin-notes-wrap svg{position:absolute;top:16px;right:18px;color:var(--o5-ink3);pointer-events:none}
.op-confirm-amt{margin-left:10px;padding-left:10px;border-left:1px solid rgba(255,255,255,.4);font-weight:800}
@media (max-width:720px){.op-admin-grid{grid-template-columns:1fr}}

/* Sold-out / insurance-selected states for the .op-row rows. `is-sold` was
   carried on .st-tier by th:classappend but had no rule on this page at all
   (the .is-sold rules in event-page.css target .evp-shows-row, a different
   page), so sold-out rows were visually identical to available ones. Kept the
   class and gave it a minimal treatment rather than inventing new markup. */
.op-row.is-sold .op-row-title b,
.op-row.is-sold .op-row-desc,
.op-row.is-sold .op-row-price .num { color: var(--o5-ink3); }
.op-row .soldout-badge {
  display: inline-block;
  margin-top: 8px;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--o5-surface-2);
  font-family: var(--o5-display);
  font-size: 10.5px; font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--o5-ink2);
}
.op-row.op-insurance.is-on { background: #fff6f5; }

/* Sections 2/3/4 live inside <div id="availablePurchaseSession" class="container">
   (purchase.html:235), and bootstrap's .container is a FIXED width -- 750/970/1170px
   at its breakpoints, never overridden. Section 1 is not inside it, so at desktop
   widths section 1 filled the ~780px grid column while sections 2-4 rendered at
   1170px: visibly wider AND overflowing the column by ~390px.

   This is also the residual cause of the horizontal scrollbar and the clipped cart
   rail. min-width:0 on .st-main-l let the GRID TRACK shrink, but a fixed-width child
   still paints past it, so the page kept overflowing. Neutralising .container here
   fixes the width mismatch and that overflow together. */
.st-main-l .container {
  width: 100%;
  max-width: 100%;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}

/* ── Section 2/3 row action: ONE control, not a stepper floating beside a button ──
   Behaviour is unchanged -- still "set a quantity, then press Add", which is what
   the backend supports: getEntranceTickets is additive and its cap check is
   per-request, so a tap-to-increment stepper would let repeated taps evade
   getMaximumSalableQuantityPerUser. This is presentation only.

   .quantity-input-group keeps .btn-minus / .btn-plus / input[name=ticketQuantity]
   as descendants -- seat-selection.js:977/986 walks parents() to find them. The
   input's border moved out of its inline style into here, because an inline
   !important cannot be overridden from a stylesheet. */
.op-qty {
  display: inline-flex;
  align-items: stretch;
  flex: none;
  border: 1.5px solid var(--o5-line);
  border-radius: 999px;
  background: var(--o5-surface);
  overflow: hidden;
}
.op-qty .quantity-input-group {
  display: flex;
  align-items: center;
  margin: 0;
  border: 0;
  background: transparent;
  width: auto;
}
.op-qty .quantity-input-group .input-group-btn { display: flex; width: auto; }
.op-qty .quantity-input-group .btn {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  padding: 0 14px;
  height: 100%;
  color: var(--o5-ink2);
  transition: color .15s, background .15s;
}
.op-qty .quantity-input-group .btn:hover { background: var(--o5-surface-2); color: var(--o5-ink); }
.op-qty .quantity-input-group input {
  width: 38px;
  border: 0 !important;
  background: transparent;
  box-shadow: none;
  font-family: var(--o5-display);
  font-size: 15px; font-weight: 800;
  color: var(--o5-ink);
  -moz-appearance: textfield;
}
.op-qty .quantity-input-group input::-webkit-outer-spin-button,
.op-qty .quantity-input-group input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.op-qty .choose-ticket-btn {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0;
  border: 0;
  border-radius: 0;
  border-left: 1.5px solid var(--o5-line);
  padding: 13px 20px;
  white-space: nowrap;
}
@media (max-width: 720px) {
  .op-qty .choose-ticket-btn { padding: 12px 14px; }
  .op-qty .quantity-input-group .btn { padding: 0 10px; }
}

/* ═══════════ Section 4 -- ADMIN checkout (box office) ═══════════
   Restyles boxoffice_new.html in place. The bootstrap tab plugin and the
   purchase.js radio cascade both impose structure, so the markup keeps its
   ul/li/.checkbox/.child-options skeleton and is re-skinned from here. */
.op-admin-pay {
  display: flex; flex-wrap: wrap; gap: 10px;
  list-style: none; margin: 0 0 22px; padding: 0;
}
.op-admin-pay > li { margin: 0; border: 0; border-radius: 0; }
.op-admin-pay .op-admin-pill { display: inline-block; text-decoration: none; }
/* bootstrap's tab plugin puts .active on the <li>, so the on-state is styled
   from the parent -- no JS change needed to drive the pill. */
.op-admin-pay > li.active > .op-admin-pill {
  background: #fff6f5;
  border-color: #d62133;
  color: var(--o5-ink);
}
.op-admin-sub {
  display: flex; flex-wrap: wrap; gap: 14px 26px;
  list-style: none; margin: -4px 0 22px; padding: 0;
}
.op-admin-sub > li { margin: 0; }
.op-admin-sub .checkbox { margin: 0; padding: 0; position: relative; }
.op-admin-sub .checkbox input[type="radio"],
.op-admin-sub .checkbox input[type="checkbox"] {
  position: absolute; opacity: 0; width: 0; height: 0;
}
.op-admin-sub .checkbox label {
  display: inline-flex; align-items: center; gap: 9px;
  margin: 0; cursor: pointer;
  font-family: var(--o5-display);
  font-size: 13px; font-weight: 600;
  color: var(--o5-ink2);
  transition: color .15s;
}
.op-admin-sub .checkbox label::before {
  content: ''; flex: none;
  width: 18px; height: 18px;
  border: 1.5px solid var(--o5-ink3);
  border-radius: 50%;
  background: var(--o5-surface);
  transition: border-color .15s, background .15s, box-shadow .15s;
}
.op-admin-sub .checkbox label:hover::before { border-color: var(--o5-ink2); }
.op-admin-sub .checkbox input:checked + label { color: var(--o5-ink); }
.op-admin-sub .checkbox input:checked + label::before {
  border-color: #d62133;
  background: #d62133;
  box-shadow: inset 0 0 0 3.5px var(--o5-surface);
}
/* Nested credit-card options under Royal Family / Corporate.
   HIDDEN BY DEFAULT IS BEHAVIOUR, NOT DECORATION: purchase.js:632/645 slideUp /
   slideDown these lists, and they must start collapsed. The rule that did that
   was .purchase-page .box-office .child-options in themes/<theme>/purchase.css,
   which is slated for deletion -- so this file owns it now. Losing it renders
   every nested card option expanded on load. */
.op-admin-sub .child-options,
.op-admin-sub .grandchild-options {
  display: none;
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  /* laid out as a row too, so the revealed card types read as a second flat row
     rather than a bulleted branch. purchase.js slideDown() sets display:block
     inline, which wins over this, so the flex row is applied to a wrapper-free
     child list via the > li rule below. */
}
.op-admin-sub .child-options > li,
.op-admin-sub .grandchild-options > li { display: inline-flex; margin: 0 22px 0 0; }
.op-admin-sub .child-options > li,
.op-admin-sub .grandchild-options > li { margin: 0 0 10px; }
.op-admin-sub .child-options > li:last-child,
.op-admin-sub .grandchild-options > li:last-child { margin-bottom: 0; }
/* [punch 7] The primary options stay a FLAT horizontal row of radio circles
   directly under the pills -- Royal Family and Corporate read
   CASH / CREDIT CARD / LPO / CHEQUE inline, not as an indented tree. The earlier
   `flex: 1 0 100%` forced any option owning a nested list onto its own full-width
   row, which is what produced the indented look.

   The nested credit-card list still EXISTS (dropping it NPEs
   setSpecialPaymentType:1930 when specialPaymentOptions == creditCard) and still
   sits inside the same <li> as its .checkbox, which purchase.js:632 requires. It
   is hidden until Credit Card is chosen, then slides open beneath the row. */
.op-admin-sub > li { display: flex; flex-direction: column; }
.op-admin-foot { display: flex; align-items: stretch; margin-top: 4px; }
.op-admin-foot .op-confirm { flex: 1; border-radius: 999px 0 0 999px; }
.op-admin-foot .op-confirm-amt {
  flex: none;
  margin: 0; padding: 0 22px;
  border: 0;
  border-left: 1px solid rgba(255,255,255,.4);
  border-radius: 0 999px 999px 0;
  background: #d62133;
  color: #fff;
  font-family: var(--o5-display);
  font-size: 15.5px; font-weight: 800;
  cursor: default;
  pointer-events: none;
}
@media (max-width: 720px) {
  .op-admin-foot { flex-direction: column; gap: 10px; }
  .op-admin-foot .op-confirm { border-radius: 999px; }
  .op-admin-foot .op-confirm-amt { border-radius: 999px; border-left: 0; padding: 14px 22px; }
}

/* ═══════════ Section 4 -- CUSTOMER checkout ═══════════
   standard_new.html keeps real bootstrap tabs (the PayPal and Apple Pay panes are
   tab panes), so the pills are <a data-toggle="tab"> inside <li>. .nav/.nav-tabs
   are dropped; .active lands on the <li>, so the on-state is styled from the
   parent -- no JS change. */
.op-pay-methods { list-style: none; padding: 0; }
.op-pay-methods > li { flex: 1; display: flex; margin: 0; }
.op-pay-methods > li > .op-pay-pill { flex: 1; text-decoration: none; }
.op-pay-methods > li.active > .op-pay-pill { border-color: #d62133; background: #fff6f5; }
.op-pay-methods > li.active > .op-pay-pill .radio { border-color: #d62133; }
.op-pay-methods > li.active > .op-pay-pill .radio::after {
  content: ''; position: absolute; inset: 3px;
  border-radius: 50%; background: #d62133;
}
/* .op-terms keeps the legacy input + label[for] pair rather than the design's
   wrapping <label>, so the Terms link behaves exactly as it did before. */
.op-terms label {
  margin: 0;
  font-weight: 500;
  font-family: var(--o5-display);
  font-size: 13px;
  line-height: 1.5;
  color: var(--o5-ink);
  cursor: pointer;
}
.op-pay-foot { display: flex; align-items: stretch; margin-top: 4px; }
.op-pay-foot .op-confirm { flex: 1; border-radius: 999px 0 0 999px; }
.op-pay-foot .op-confirm-amt {
  flex: none;
  margin: 0; padding: 0 22px;
  border: 0;
  border-left: 1px solid rgba(255,255,255,.4);
  border-radius: 0 999px 999px 0;
  background: #d62133;
  color: #fff;
  font-family: var(--o5-display);
  font-size: 15.5px; font-weight: 800;
  cursor: default;
  pointer-events: none;
}
/* purchase.js:106/111 toggles the DISABLED PROPERTY on #paymentSubmit, not a
   class -- so the ready state keys off :disabled here, unlike the admin button
   which carries .is-ready statically. */
.op-confirm:not(:disabled) {
  background: #d62133;
  cursor: pointer;
  box-shadow: 0 16px 30px -14px rgba(214,33,51,0.5);
}
.op-confirm:not(:disabled):hover { background: #b91c2c; transform: translateY(-1px); }
.op-pay-foot .op-confirm:disabled + .op-confirm-amt { background: var(--o5-ink3); }
.op-ir-gateways { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }
.op-free-order { text-align: center; }
.op-free-order h3 {
  margin: 0 0 18px;
  font-family: var(--o5-display);
  font-size: 18px; font-weight: 800;
  letter-spacing: -.02em;
  color: var(--o5-ink);
}
@media (max-width: 720px) {
  .op-pay-methods { flex-wrap: wrap; }
  .op-pay-foot { flex-direction: column; gap: 10px; }
  .op-pay-foot .op-confirm { border-radius: 999px; }
  .op-pay-foot .op-confirm-amt { border-radius: 999px; border-left: 0; padding: 14px 22px; }
}

/* [punch 3] price sits beside the control, hard right -- it was reading as
   floating mid-row because .op-row-r is the `auto` grid column and its content
   was free to sit wherever the column happened to start. */
.op-row-r { justify-content: flex-end; gap: 14px; }
.op-row-price { flex: none; text-align: right; }

/* ═══════════ cart rail -- punch list 9-15 ═══════════
   updateBasket() in seat-selection.js REGENERATES the line markup on every
   add/remove, in three country variants, so these rules key only on classes BOTH
   the template and that JS emit. Styling anything the JS does not emit would look
   correct until the first add and then revert. */

/* [11] .ticket-item already picks up the grey card from .st-summary-line; it just
   needs separation, since .st-summary-sections' flex gap only reaches its own
   direct children (.basket-performance), not the lines inside them. */
.st-summary-sections .ticket-item { margin-bottom: 10px; }
.st-summary-sections .ticket-item:last-child { margin-bottom: 0; }

/* .st-summary-line-row is a 3-column grid meant for a single summary line, but
   seat-selection.js:1517 puts it on .ticket-inner, which STACKS rows (name, unit
   price, fee, net, total, VAT). Left as a grid those rows lay out side by side.
   This is already live after any basket refresh, not something introduced here. */
.st-summary-sections .ticket-inner.st-summary-line-row { display: block; }

/* [12]/[13] rows inside a line card. The dividers were inline
   `border-bottom:1px solid lightslategray` in BOTH the template and the JS
   strings; inline styles cannot be overridden from a stylesheet, so they were
   replaced with .op-cart-card-row at source in both places. */
.st-summary-sections .ticket-inner > div {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; padding: 4px 0;
  font-family: var(--o5-display); font-size: 13px;
}
.st-summary-sections .ticket-inner > div.op-cart-card-row {
  border-bottom: 1px solid var(--o5-line);
  padding-bottom: 10px; margin-bottom: 8px;
}
.st-summary-sections .ticket-inner > div:last-child { margin-bottom: 0; }
.st-summary-sections .ticket-inner .info-label,
.st-summary-sections .ticket-inner .info-text { float: none !important; }
.st-summary-sections .ticket-inner .info-label { color: var(--o5-ink2); font-weight: 600; }
.st-summary-sections .ticket-inner .info-text { color: var(--o5-ink); font-weight: 700; text-align: right; }
.st-summary-sections .ticket-inner .basket-ticket-name {
  font-size: 14.5px; font-weight: 800; color: var(--o5-ink);
}

/* [9] the thumbnail square shows the event image when there is one; the folded
   .st-edit-thumb already supplies the placeholder square it falls back to. */
.st-edit-thumb { background-size: cover; background-position: center; }

/* [10] */
.op-cart-info-edit { text-decoration: none; flex: none; }

/* [14] Apply button: grey fill, no border. Legacy `tbtn wbg` gave it a white fill
   and a red outline. Done in CSS rather than markup because
   seat-selection.js:1671 regenerates this button too. */
.op-cart-rail .promo-apply,
.st-summary .promo-apply {
  background: var(--o5-surface-2) !important;
  border: 0 !important;
  color: var(--o5-ink) !important;
  border-radius: 999px !important;
  box-shadow: none !important;
  font-family: var(--o5-display); font-weight: 800;
  padding: 13px 18px !important; height: auto !important;
}
.op-cart-rail .promo-apply:hover,
.st-summary .promo-apply:hover { background: var(--o5-line) !important; }

/* ═══════════ cart -- exact design values (Old Shopping Cart.css) ═══════════
   Values copied verbatim from claude/designs/Old Shopping Cart.css, not
   approximated.

   SPECIFICITY NOTE: themes/<theme>/purchase.css styles these same elements from
   an 8-deep chain --
     .purchase-page .page-content .order-info .order-summary .summary-box
       .info-box .basket-performance .ticket-item
   which sets box-shadow 0 4px 4px rgba(0,0,0,.25), border-radius 6px,
   background #fff and margin 20px 0, and gives .ticket-inner > div a
   `border-bottom: 1px solid #ebebeb`. That chain matches the MOBILE cart (which
   sits inside .page-content) and outweighs anything short. The properties it sets
   are therefore reset explicitly here. All of it disappears when that file is
   deleted; until then this is what makes both carts agree. */

/* [2] line card == .op-cart-card, exactly */
.st-summary-sections .ticket-item,
.purchase-page .order-info .order-summary .summary-box .info-box .basket-performance .ticket-item {
  background: var(--o5-surface-2) !important;
  border-radius: 16px !important;
  padding: 16px 18px !important;
  margin: 0 0 10px !important;
  box-shadow: none !important;
  overflow: visible;
}
.st-summary-sections .ticket-item:last-child,
.purchase-page .order-info .order-summary .summary-box .info-box .basket-performance .ticket-item:last-child {
  margin-bottom: 0 !important;
}
.st-summary-sections .ticket-inner,
.purchase-page .order-info .order-summary .summary-box .info-box .basket-performance .ticket-item .ticket-inner {
  background: transparent !important;
  padding: 0 !important;
}

/* [3] dividers: 1px var(--o5-silver, #ecebe6), per the design. --o5-silver is not
   declared in option5.css, so the #ecebe6 fallback is what actually paints. The
   legacy #ebebeb 1px on EVERY .ticket-inner > div is what read as heavier -- it
   drew a rule under every line, not just the separators. */
.st-summary-sections .ticket-inner > div,
.purchase-page .order-info .order-summary .summary-box .info-box .basket-performance .ticket-item .ticket-inner > div {
  border-bottom: 0 !important;
  padding: 4px 0 !important;
}
.st-summary-sections .ticket-inner > div.op-cart-card-row,
.purchase-page .order-info .order-summary .summary-box .info-box .basket-performance .ticket-item .ticket-inner > div.op-cart-card-row {
  border-bottom: 1px solid var(--o5-silver, #ecebe6) !important;
  padding-bottom: 10px !important;
  margin-bottom: 8px !important;
}
.st-summary-sections .ticket-inner > div:last-child { margin-bottom: 0 !important; }

/* ═══════════ punch: section 2/4 layout ═══════════ */

/* [6] Long ticket descriptions ran under the price/stepper and clipped.
   .op-row-main is `1fr auto`, but a grid item defaults to min-width:auto, so the
   1fr column refused to shrink and its text overflowed into the auto column
   instead of wrapping. Same class of bug as the .st-main-l blowout. */
.op-row-l { min-width: 0; }
.op-row-desc { overflow-wrap: anywhere; word-break: break-word; }

/* [7] The design separates section cards by 36px (inline style:margin-top:36px on
   each <section> in the mockup). Sections 2 and 3 were nearly touching. */
.st-main-l .op-section-card + .op-section-card,
.st-main-l .op-section-card { margin-top: 36px; }
.st-main-l #performance-selection .op-section-card:first-of-type { margin-top: 0; }

/* [12] The admin/customer panels sit inside a bootstrap .row > .col-md-8, so the
   card content stopped at 66.67% of the column while sections 1-3 filled it.
   Neutralised inside the section card only. */
.op-section-card-body > .row { margin-left: 0; margin-right: 0; }
.op-section-card-body > .row > [class*="col-md-"] {
  width: 100%;
  float: none;
  padding-left: 0;
  padding-right: 0;
}

/* [9] Customer / Admin toggle -- PRESENTATION ONLY.
   The server still decides which panel exists (th:if on isBoxOfficeUser in
   purchase.html); this is an indicator of which one you are in, not a switch.
   The inactive button is deliberately inert and non-focusable -- there is no
   customer panel in a box-office user's DOM to switch to, by design. */
.op-role-toggle {
  display: inline-grid; grid-template-columns: 1fr 1fr; gap: 0;
  padding: 6px; border-radius: 999px;
  background: var(--o5-surface-2);
  margin-bottom: 24px;
}
.op-role-btn {
  padding: 11px 20px; border: 0; border-radius: 999px;
  background: transparent;
  font-family: var(--o5-display);
  font-size: 12.5px; font-weight: 800;
  color: var(--o5-ink2);
  white-space: nowrap;
}
.op-role-btn.is-on { background: #d62133; color: #fff; }
.op-role-btn:not(.is-on) { cursor: default; opacity: .55; }

/* ═══════════ grand total -- money path ═══════════
   .op-grand-total sits ON the legacy .info-box.tickets-total container, which is
   kept because seat-selection.js:1638 uses it as the insertBefore anchor for the
   promo form. The legacy .info-box rules (padding, clearfix :after, borders) must
   therefore be neutralised here rather than by removing the class. */
.op-cart-rail .info-box.tickets-total.op-grand-total,
.st-summary .info-box.tickets-total.op-grand-total {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-top: 14px;
  padding: 16px 20px !important;
  border: 1.5px solid #d62133 !important;
  border-radius: 999px !important;
  background: #fff6f5 !important;
  float: none !important;
}
.op-grand-total::after { content: none !important; }
.op-grand-total .op-grand-total-amt {
  float: none !important;
  font-family: var(--o5-display);
  font-size: 18px; font-weight: 800;
  color: #d62133;
  white-space: nowrap;
}
/* JS writes currency and amount into these two separately (1642/1643), so they
   stay distinct nodes; .ccy carries the design's smaller currency treatment. */
.op-grand-total .op-grand-total-amt .ccy {
  font-size: 11px; font-weight: 700; margin-right: 3px; color: #d62133;
}
.op-grand-total .op-grand-total-amt .second-currency {
  display: block;
  font-size: 11px; font-weight: 700;
  color: var(--o5-ink2);
}

/* Per-line date. The .basket-performance group wrapper and its single shared date
   header are gone: each cart line now carries its own date, taken from that row's
   own performance. Emitted identically by the template and by updateBasket. */
.st-summary-sections .basket-line-date {
  display: block;
  margin: -2px 0 6px;
  font-family: var(--o5-display);
  font-size: 11.5px; font-weight: 700;
  letter-spacing: .01em;
  color: var(--o5-ink2);
}
.st-summary-sections .basket-line-date .date { color: var(--o5-ink2); font-weight: 700; }

/* ═══════════ Group A: A1.4 / A3 / A5 ═══════════ */

/* [A1.4] Promo code as the design's fully-rounded PILL with Apply BELOW.
   Done in CSS, not markup, because updateBasket regenerates this exact promo
   form (seat-selection.js ~1618) -- a markup-only fix would revert on the first
   add. Legacy structure kept: .promo-form > .code-input-col > input.promo-code,
   then .code-btn-col > button.promo-apply. */
.op-cart-rail .promo-form,
.st-summary .promo-form { display: block; }
.op-cart-rail .promo-form .code-input-col,
.st-summary .promo-form .code-input-col { width: 100%; padding: 0; margin: 0 0 12px; float: none; }
.op-cart-rail .promo-form .code-btn-col,
.st-summary .promo-form .code-btn-col { width: 100%; padding: 0; float: none; }
.op-cart-rail .promo-form input.promo-code,
.st-summary .promo-form input.promo-code {
  width: 100%;
  padding: 13px 42px 13px 18px;
  border: 1px solid var(--o5-line) !important;
  border-radius: 999px !important;
  background: var(--o5-surface);
  font-family: var(--o5-display);
  font-size: 13.5px; font-weight: 600;
  color: var(--o5-ink);
  outline: none;
  box-shadow: none !important;
  height: auto !important;
  box-sizing: border-box;
}
.op-cart-rail .promo-form input.promo-code:focus,
.st-summary .promo-form input.promo-code:focus { border-color: var(--o5-ink) !important; }

/* [A3] Payment selector tubes -- SHORTER.
   NOTE: the design file value (Old Checkout Payment - Customer.css:16) is
   padding:15px 20px, which is exactly what was already deployed -- so "shorter"
   is a deliberate deviation from the design, not a port. Vertical padding
   15px -> 10px; computed height ~52px -> ~42px at the same 14px font.
   States are untouched: .is-on keeps the red outline + pink fill + filled radio,
   unselected keeps the neutral outline + empty radio, and flex:1 keeps them
   side by side. */
.op-pay-methods .op-pay-pill { padding: 10px 18px; }

/* [A5] Process-fee "?" badge rendered oval because the legacy
   .purchase-page .whats-this rule sizes it by padding inside a flex row, so it
   stretched horizontally and got squashed vertically. Give it a fixed square box
   that cannot flex, matching the design's .op-cart-tip
   (Old Shopping Cart.css:522). Applies in both render paths -- the fee row is
   regenerated by updateBasket, but this keys on .whats-this which both emit. */
.st-summary .whats-this,
.op-cart-rail .whats-this {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  width: 15px !important;
  height: 15px !important;
  min-width: 15px;
  padding: 0 !important;
  flex: 0 0 15px;
  flex-shrink: 0;
  border: 1px solid var(--o5-ink3) !important;
  border-radius: 50% !important;
  background: transparent !important;
  color: var(--o5-ink3) !important;
  font-family: var(--o5-display);
  font-size: 10px !important;
  font-weight: 700;
  line-height: 1 !important;
  text-align: center;
  cursor: help;
  vertical-align: middle;
}

/* ═══════════ A2: one slot, two states ═══════════
   Default -> only "+ Add to Basket". Once the tier has a basket line, .is-inbasket
   is set by reconcileTierRows() in seat-selection.js and the slot shows only the
   counter. Never both, and the swap is driven by REAL basket state, not a client
   flag -- so a remove from the cart rail reverts the row too. */
.op-qty .op-qty-step { display: none; }
.op-qty.is-inbasket .op-qty-step { display: flex; align-items: center; }
.op-qty.is-inbasket .choose-ticket-btn { display: none !important; }

/* the default state is a single black pill, per the design */
.op-qty:not(.is-inbasket) { border: 0; background: transparent; overflow: visible; }
.op-qty:not(.is-inbasket) .choose-ticket-btn {
  border: 0;
  border-radius: 999px;
  background: var(--o5-ink);
  color: #fff;
  padding: 13px 22px;
  white-space: nowrap;
}
.op-qty:not(.is-inbasket) .choose-ticket-btn:hover { background: #000; }

/* in-basket: the joined counter keeps the pill outline */
.op-qty.is-inbasket { border: 1.5px solid var(--o5-line); border-radius: 999px; overflow: hidden; }
.op-qty.is-inbasket .quantity-input-group input { font-weight: 800; }

/* ═══════════ A1 banner: flush with the card, rounded top corners ═══════════
   CAUSE of the gap and the square corners: the rail element carries BOTH
   .op-cart-rail and .st-summary. .op-cart-rail (line ~111) sets padding:22px and
   .st-summary does not set padding at all, so the 22px was unopposed -- it inset
   the band on all sides. Being inset, the band never reached the parent's edge,
   so .st-summary's overflow:hidden + border-radius:22px could not clip it, and it
   rendered as a floating square rectangle.

   Scoped to .op-cart-rail.st-summary on purpose. The MOBILE cart is
   `order-summary op-cart-rail` with NO .st-summary and NO .st-summary-band -- it
   still uses the unconverted .summary-box, so it has no banner to fix AND it
   relies on .op-cart-rail's 22px padding for its own inset. Removing that padding
   globally would strip the mobile cart's spacing.

   Radius 22px is the card's own value, read from
   claude/designs/Old Shopping Cart.css (.st-summary border-radius:22px). The
   content keeps its inset from .st-summary-body's existing padding:22px 24px 24px,
   so dropping the container padding costs nothing.

   CSS-only: updateBasket never emits .st-summary-band (0 references), so the
   banner is server-rendered only and there is no second render path to match. */
.op-cart-rail.st-summary { padding: 0; }
.op-cart-rail.st-summary > .st-summary-band {
  margin: 0;
  border-top-left-radius: 22px;
  border-top-right-radius: 22px;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* in-flight state for the tier control -- replaces the full-page HoldOn overlay
   on add/stepper. Visible enough that a slow network still reads as "working",
   cheap enough that it does not block the page. */
.op-qty.is-busy { opacity: .55; pointer-events: none; }
.op-qty.is-busy .choose-ticket-btn,
.op-qty.is-busy .quantity-input-group .btn { cursor: progress; }


/* ═══════════ opf-* : the shared pop-up component ═══════════
   Ported from claude/designs/Old Pop Ups.css. SHARED ON PURPOSE, not styled for
   the one dialog that uses it first: the payment-failure dialog moves onto
   these next and retires the sweetAlert box, so anything one-off here would
   have to be undone then.

   .opf-icon.is-emoji IS NOT IN THE DESIGN. Old Cart empty.html uses the class
   and Old Pop Ups.css never defines it, so an emoji would render at inherited
   size inside an 80px gradient circle -- a tiny glyph in a red disc. The
   variant below drops the gradient and scales the glyph to fill the same
   footprint, which is plainly what the markup intends. Invented, and flagged as
   invented. */
.opf-overlay{position:fixed;inset:0;background:rgba(10,10,12,0.55);display:flex;align-items:center;justify-content:center;padding:24px;z-index:400;opacity:0;visibility:hidden;transition:opacity .2s}
.opf-overlay.is-open{opacity:1;visibility:visible}
.opf-modal{width:380px;max-width:100%;background:var(--o5-surface,#fff);border-radius:24px;padding:40px 28px 28px;text-align:center;position:relative;overflow:hidden;box-shadow:0 30px 60px -16px rgba(0,0,0,0.35)}
.opf-modal::before{content:'';position:absolute;top:0;left:0;right:0;height:6px;background:linear-gradient(90deg,#d62133,#ff6f3c);border-radius:24px 24px 0 0}
.opf-icon{width:80px;height:80px;border-radius:50%;background:linear-gradient(135deg,#d62133,#ff6f3c);color:#fff;display:inline-flex;align-items:center;justify-content:center;margin:0 auto 22px;box-shadow:0 14px 28px -10px rgba(214,33,51,0.45)}
.opf-icon svg{width:36px;height:36px}
.opf-modal h2{font-family:var(--o5-display);font-size:24px;font-weight:800;letter-spacing:-.01em;color:var(--o5-ink);margin:0 0 12px}
.opf-modal p{font-family:var(--o5-display);font-size:14.5px;line-height:1.55;color:var(--o5-ink2);margin:0 0 24px}
.opf-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:13px 18px;border-radius:999px;border:1px solid var(--o5-red,#d62133);background:var(--o5-red,#d62133);color:#fff;font-family:var(--o5-display);font-weight:800;font-size:13.5px;cursor:pointer;transition:background .15s,border-color .15s,transform .15s;box-shadow:0 14px 28px -14px rgba(214,33,51,0.5)}
.opf-btn:hover{background:#b91c2c;border-color:#b91c2c;transform:translateY(-1px)}
/* TWO-BUTTON VARIANT, added to the shared component rather than borrowing
   .olf-btn from the forgot-password dialog -- one modal carrying two class
   vocabularies is the kind of thing that gets "tidied" into a bug later. The
   ghost is the neutral choice and goes first, so the destructive one is not
   under the thumb by default. */
.opf-actions{display:flex;gap:10px}
.opf-actions .opf-btn{flex:1}
.opf-btn.is-ghost{background:transparent;color:var(--o5-ink);border-color:var(--o5-line)}
.opf-btn.is-ghost:hover{background:var(--o5-surface-2);border-color:var(--o5-ink);color:var(--o5-ink)}
.opf-icon.is-emoji{background:var(--o5-surface-2);box-shadow:none;font-size:40px;line-height:1}

/* ═══════════ Step 4 · Buyer Information ═══════════
   Ported from claude/designs/Old Buyer information.css, the dedicated spec.

   NOT PORTED, on purpose:
     .co-verify      OTP is deferred, and a styled control that does nothing
                     invites someone to wire it.
     .co-pop         the bespoke country popover -- select2 is used instead and
                     renders its own dropdown; see buyer.js.
     .obi-*          .obi-wrap/.obi-back/.obi-next are the standalone design
                     page's chrome. Step 5 sits directly below this card here,
                     so its Continue lives in the card as .co-guest-continue.
     .lv-*           the design file's own option picker, not part of the step.

   THE SIGN-IN MODAL'S oli-* BLOCK IS GONE with sign-in-modal.html. Only the two
   brand marks survive, scoped under .co-sso-btn, because the design's tab pane
   reuses those class names. */

/* THE ONE RULE THE WHOLE STEP DEPENDS ON. Panels swap by the hidden attribute,
   and hidden gets its display:none from the UA stylesheet -- which ANY author
   rule setting display beats. .co-fields{display:grid} alone was enough to
   render a hidden element, so both showed at once. The design ships this at the
   top of its stylesheet for the same reason. Scoped to the step rather than
   global, so it cannot reach anything else on the page. */
#buyer [hidden]{display:none!important}

/* ── The tab bar: log in, or continue as guest ── */
.co-authtabs{display:flex;flex-direction:column;gap:20px;margin-bottom:22px}
.co-tabbar{display:grid;grid-template-columns:1fr 1fr;gap:0;padding:6px;border-radius:999px;background:var(--o5-surface-2)}
.co-tab{padding:13px 18px;border:0;border-radius:999px;background:transparent;font-family:var(--o5-display);font-size:13.5px;font-weight:800;color:var(--o5-ink2);cursor:pointer;transition:background .15s,color .15s,box-shadow .15s}
.co-tab:hover{color:var(--o5-ink)}
.co-tab.is-on{background:var(--o5-ink);color:#fff;box-shadow:0 6px 14px -8px rgba(0,0,0,0.3)}
.co-tabpanel{display:flex;flex-direction:column;gap:0}

/* ── Login pane ── */
.co-sso-list{display:flex;flex-direction:column;gap:10px}
.co-sso-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:15px 20px;border:1px solid var(--o5-line);border-radius:999px;background:var(--o5-surface);font-family:var(--o5-display);font-size:14.5px;font-weight:800;color:var(--o5-ink);cursor:pointer;transition:border-color .15s}
.co-sso-btn:hover{border-color:var(--o5-ink)}
.co-sso-btn .ico{width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;flex:none}
.co-sso-btn .oli-lg-apple svg{width:16px;height:18px}
.co-sso-btn .oli-lg-google{width:18px;height:18px;background:conic-gradient(from -45deg,#ea4335 0deg 90deg,#fbbc04 90deg 180deg,#34a853 180deg 270deg,#4285f4 270deg 360deg);border-radius:50%;mask:radial-gradient(circle 6px at center,transparent 99%,#000 100%);-webkit-mask:radial-gradient(circle 6px at center,transparent 99%,#000 100%)}

/* Apple and Google are rendered but not wired -- see the note in purchase.html.
   Disabled and greyed rather than a clickable no-op, with a chip that says so,
   because a button that looks live and does nothing gets reported as a bug. */
.co-sso-btn:disabled{opacity:.5;cursor:not-allowed;color:var(--o5-ink2)}
.co-sso-btn:disabled:hover{border-color:var(--o5-line)}
.co-soon{padding:3px 9px;border-radius:999px;background:var(--o5-surface-2);color:var(--o5-ink3);font-family:var(--o5-display);font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;white-space:nowrap}

.co-or{display:block;font-family:var(--o5-display);font-size:13px;color:var(--o5-ink2);line-height:1.5;margin:20px 0 16px}
.co-login-form{display:flex;flex-direction:column}
.co-login-fields{display:flex;flex-direction:column;gap:12px}
.co-pwd-ctl{position:relative}
.co-pwd-ctl input{padding-right:48px}
.co-eye{position:absolute;top:50%;right:16px;transform:translateY(-50%);background:transparent;border:0;padding:0;color:var(--o5-ink2);cursor:pointer;display:inline-flex}
.co-eye:hover{color:var(--o5-ink)}
.co-forgot{align-self:flex-end;display:inline-block;margin-top:2px;font-family:var(--o5-display);font-size:11.5px;font-weight:700;color:#d62133;text-decoration:none;cursor:pointer}
.co-forgot:hover,.co-forgot:focus{color:#b91c2c;text-decoration:none}
.co-login-submit{margin-top:18px;width:100%;padding:14px 22px;border-radius:999px;background:#d62133;color:#fff;border:0;font-family:var(--o5-display);font-size:14.5px;font-weight:800;cursor:pointer;transition:background .15s}
.co-login-submit:hover{background:#b91c2c}

/* ── The buyer fields ── */
.co-fields{display:grid;gap:14px}
.co-fields.two{grid-template-columns:1fr 1fr}
.co-field{display:flex;flex-direction:column;gap:6px;min-width:0;position:relative}
.co-ctl{display:flex;align-items:center;gap:0;border:1px solid var(--o5-line);border-radius:999px;background:transparent;padding:0;min-height:46px;transition:border-color .15s}
.co-ctl:focus-within{border-color:var(--o5-ink)}
.co-ctl input{flex:1;border:0;border-radius:999px;background:transparent;padding:12px 18px;font-family:var(--o5-display);font-size:14px;font-weight:600;color:var(--o5-ink);outline:none;min-width:0;width:100%}
/* The phone field's input is the RIGHT-HAND grid cell, with .co-phone-cc to its
   left, so a full pill would round an edge that sits in the middle of the
   control -- visible the moment autofill paints it. */
.co-phone-ctl input{border-radius:0 999px 999px 0}
.co-ctl input::placeholder{color:var(--o5-ink3);font-weight:500}

/* AUTOFILL. Chrome paints an autofilled input with its own background, set on
   the internal -internal-autofill-selected pseudo-class with UA !important --
   which author CSS cannot override directly. Two things are needed and the
   first version of this rule got both wrong.

   AN OPAQUE INSET SHADOW, not a transparent one. The trick works by PAINTING
   OVER the background Chrome applied; a transparent shadow paints nothing, so
   the blue stayed exactly where it was. The colour has to be what the field
   sits on -- .co-ctl is background:transparent over the card body, so
   var(--o5-surface).

   AND THE RADIUS MUST BE ON THE INPUT. It was on .co-ctl, the wrapper, while
   the browser paints the input -- so even once the fill was covered it rendered
   as a square block inside the rounded pill. That is the square corner, and no
   colour override can fix it: the element being painted has to be the element
   with the corners. Giving the input its own radius is the smaller of the two
   structural options; moving the whole pill onto the input would mean
   rebuilding .co-phone-ctl and .co-pwd-ctl, which position children against the
   wrapper.

   -webkit-text-fill-color or the text reverts to Chrome's colour, caret-color
   for the cursor, and the long background-color transition kept as belt and
   braces for versions that still animate it. */
.co-ctl input:-webkit-autofill,
.co-ctl input:-webkit-autofill:hover,
.co-ctl input:-webkit-autofill:focus,
.co-ctl input:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px var(--o5-surface) inset!important;box-shadow:0 0 0 1000px var(--o5-surface) inset!important;-webkit-text-fill-color:var(--o5-ink)!important;caret-color:var(--o5-ink);transition:background-color 9999s ease-in-out 0s}

.co-hint{font-family:var(--o5-display);font-size:11.5px;color:var(--o5-ink3);padding:0 18px;line-height:1.4}
.co-field-caption{margin:-2px 0 0;padding:0 18px;font-family:var(--o5-display);font-size:11.5px;color:var(--o5-ink3);line-height:1.3}

/* Phone. The design's prefix cell carries a flag and a dial code; there is no
   dial-code column in the schema, so this shows the flag alone -- see the note
   in purchase.html. Grid rather than flex so the prefix keeps its width. */
/* The phone pill's country trigger. Ported from
   claude/designs/Phone Number pill.css -- it replaces the flag-only span that
   stood in while there was no dial-code column to show. It is a <button> now,
   so it needs the focus treatment the other triggers have. */
.co-phone-cc{display:inline-flex;align-items:center;gap:6px;padding:12px 14px 12px 16px;border-right:1px solid var(--o5-line);font-family:var(--o5-display);font-size:14px;font-weight:700;color:var(--o5-ink);background:none;border-top:0;border-bottom:0;border-left:0;border-radius:999px 0 0 999px;cursor:pointer;flex:none}
.co-phone-cc:hover{background:var(--o5-surface-2)}
.co-phone-cc svg{color:var(--o5-ink2);transition:transform .18s}
.co-phone-cc.is-open svg{transform:rotate(180deg)}
.co-phone-cc .flag{font-size:16px;line-height:1}
.co-phone-cc:focus{outline:none}
.co-phone-cc:focus-visible{outline:2px solid var(--o5-ink);outline-offset:2px}
/* The dial code sits between flag and caret and must not wrap or shrink. */
.co-phone-cc [data-cc-dial]{white-space:nowrap}
/* The pill row is flag, name, dial code -- the code pushed to the right edge.
   (Only in the phone pop: the country dropdowns have two spans, not three.) */
[data-cc-list] li span:last-child{margin-left:auto;color:var(--o5-ink3);font-weight:500}
.co-phone-ctl{display:grid;grid-template-columns:auto 1fr;gap:0}

/* The gate on step 5. */
.co-guest-continue{margin-top:6px;width:100%;padding:14px 22px;border-radius:999px;background:#d62133;color:#fff;border:0;font-family:var(--o5-display);font-size:14.5px;font-weight:800;cursor:pointer;transition:background .15s}
.co-guest-continue:hover{background:#b91c2c}
.co-guest-continue:disabled{background:var(--o5-surface-2);color:var(--o5-ink3);cursor:not-allowed}
.co-guest-continue:disabled:hover{background:var(--o5-surface-2)}

/* "Logged in as ..." pill, member state only. */
.mb-pill{display:flex;align-items:center;gap:10px;padding:6px;background:#e9f4ee;border-radius:999px}
.mb-check{width:26px;height:26px;border-radius:50%;background:#fff;color:#1f8a5b;display:inline-flex;align-items:center;justify-content:center;flex:none}
.mb-line{flex:1;font-family:var(--o5-display);font-size:12.5px;font-weight:600;letter-spacing:-.005em;color:#1f8a5b;line-height:1.35;min-width:0}
.mb-line b{font-weight:800;color:#1f8a5b}
.mb-line .mb-email{color:#1f8a5b;font-weight:500;opacity:.75}
.mb-switch{background:#fff;color:#1f8a5b;border:0;border-radius:999px;padding:7px 14px;font-family:var(--o5-display);font-size:11.5px;font-weight:800;cursor:pointer;flex:none;white-space:nowrap;transition:background .15s,color .15s}
.mb-switch:hover{background:#1f8a5b;color:#fff}

/* ── The four dropdowns ──
   Ported from claude/designs/Old Drop Down.css. SELECT2 IS GONE from this step;
   .co-trigger is a real <button> and .co-pop is the design's own popover, driven
   by co-select.js. Everything select2 was supplying is supplied there.

   TWO DEVIATIONS FROM THE DESIGN, both deliberate:

   1. The design raises stacking with
        .co-field:has([data-trigger].is-open){z-index:40}
      :has() is inert on Safari below 15.4 and Chrome below 105 -- which fails
      silently, and fails on exactly the phones most likely to be looking at the
      bottom of a checkout. co-select.js sets .is-open on the field instead.

   2. .co-pop is pinned below the trigger with no fallback, so a field low in the
      viewport opens off-screen. .is-up flips it above; co-select.js decides
      which, and writes an inline max-height for the room actually available.

   THE FOCUS RING IS PINNED HERE. A red ring was showing on the trigger and no
   :focus rule in any stylesheet this page loads accounts for it -- the only red
   one on the site is scoped to .o5-events-list -- which pointed at the UA ring
   on select2's tabindex span following the OS accent colour. Declaring it
   outright means it cannot come from anywhere else. */
/* THE CLIP THAT ATE THE POPOVERS. .op-section-card carries overflow:hidden,
   and a clip applies to descendants at EVERY stacking level -- z-index
   cannot escape an ancestor's overflow -- so Occupation, Nationality and
   Residence were cut off at the card's bottom edge.

   LIFTED ON THIS CARD ONLY, not on .op-section-card globally. The clip is
   there to round .op-section-card-head's surface-2 background to the top
   corners, which the head can do itself -- but steps 1 to 3 hold the
   performance picker and the seat map, and whether anything in those
   relies on being clipped is not something this change needs to find out.
   Step 4 is the only card with a popover to let out.

   The alternative was a position:fixed popover positioned from the
   trigger's rect, which needs repositioning on every scroll and every
   ancestor's scroll -- more moving parts than lifting one clip.

   The radius is minus the card's 1px border, or the head's corner sits a
   hair outside the card's. */
#buyer{overflow:visible}
#buyer .op-section-card-head{border-radius:calc(var(--o5-r) - 1px) calc(var(--o5-r) - 1px) 0 0}

/* ── FIELD STATE: error, success, and the Continue lifecycle ──
   Ported verbatim from claude/designs/Old Buyer information.css.

   THE GREEN TICK IS A PROMISE THE SERVER HAS TO KEEP. .is-success on email and
   phone is applied only once the duplicate check has come back NEGATIVE --
   never on client-side validation alone. A tick on an address that then fails
   ACCOUNT_EXISTS at payment is the page telling the visitor something the
   server contradicts a moment later. The other six fields tick on client
   validation, because nothing downstream can disagree with them.

   .co-dupe-error sits below the hint, one block per field, wording unchanged
   from the design. */
.co-ctl.is-success{border-color:var(--o5-line);position:relative;padding-right:34px}
.co-ctl.is-success::after{content:'';position:absolute;right:14px;top:50%;transform:translateY(-50%);width:16px;height:16px;flex:none;background:var(--o5-green,#1f8a5b);border-radius:50%;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='5 12 10 17 19 8'/%3E%3C/svg%3E");background-size:10px 10px;background-repeat:no-repeat;background-position:center}
.co-ctl.is-error{border-color:var(--o5-red,#d62133)}
.co-trigger.is-success{border-color:var(--o5-line);position:relative;padding-right:36px}
.co-trigger.is-success::after{content:'';position:absolute;right:14px;top:50%;transform:translateY(-50%);width:16px;height:16px;flex:none;background:var(--o5-green,#1f8a5b);border-radius:50%;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='5 12 10 17 19 8'/%3E%3C/svg%3E");background-size:10px 10px;background-repeat:no-repeat;background-position:center}
.co-trigger.is-success .caret{display:none}
.co-dupe-error{display:none;align-items:center;gap:10px;background:#fdecec;border-radius:999px;padding:12px 18px;margin:-4px 0 0}
.co-dupe-error.is-on{display:flex}
.co-dupe-error .de-mark{width:22px;height:22px;border-radius:50%;background:#fff;color:var(--o5-red,#d62133);display:inline-flex;align-items:center;justify-content:center;flex:none;font-family:var(--o5-display);font-weight:800;font-size:13px}
.co-dupe-error .de-line{flex:1;font-family:var(--o5-display);font-size:12.5px;font-weight:600;letter-spacing:-.005em;color:var(--o5-red,#d62133);line-height:1.35}
.co-guest-continue.is-ready{background:var(--o5-red,#d62133);color:#fff;cursor:pointer}
.co-guest-continue.is-ready:hover{background:#b91c2c}
.co-guest-continue.is-done{background:var(--o5-green,#1f8a5b);color:#fff;cursor:pointer}
.co-guest-issues{margin:10px 0 0;padding:0;font-family:var(--o5-display);font-size:11.5px;font-weight:400;color:var(--o5-red,#d62133);line-height:1.4}
.co-guest-issues:empty{display:none}
.co-guest-continue.is-shake{animation:coGuestShake .4s}
@keyframes coGuestShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-6px)}40%{transform:translateX(6px)}60%{transform:translateX(-4px)}80%{transform:translateX(4px)}}

.co-field.is-open{z-index:40}
.co-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:12px 18px;border:1px solid var(--o5-line);border-radius:999px;background:transparent;font-family:var(--o5-display);font-size:14px;font-weight:700;color:var(--o5-ink);cursor:pointer;text-align:left;transition:border-color .15s}
.co-trigger:hover{border-color:var(--o5-ink2)}
.co-trigger.is-open{border-color:var(--o5-ink)}
.co-trigger:focus{outline:none}
.co-trigger:focus-visible{outline:2px solid var(--o5-ink);outline-offset:2px}
/* .co-label and .co-caret, NOT the design's .label and .caret. bootstrap.css
   is loaded on this page and owns both names globally:
     .label  (4845) font-size:75%, font-weight:bold, color:#fff, padding
     .caret  (3502) width:0, height:0, border-top:4px dashed
   An element's own single-class rule beats an inherited value regardless of
   specificity, so the trigger's chosen value rendered at 10.5px, bold, and
   WHITE ON WHITE -- a member's saved gender or country looked blank -- while
   the 13x13 SVG chevron was collapsed to 0x0 and replaced by bootstrap's
   triangle. Namespacing is the fix; enumerating every property bootstrap
   sets would leave the same trap for the next component. [data-label] is
   still the JS hook, so co-select.js is unaffected. */
.co-trigger .l{display:inline-flex;align-items:center;gap:10px;min-width:0}
.co-trigger .flag{font-size:16px;line-height:1;flex:none}
.co-trigger .flag:empty{display:none}
.co-trigger .co-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--o5-display);font-size:14px;font-weight:600;color:var(--o5-ink);padding:0;display:inline;line-height:normal;border-radius:0}
.co-trigger .co-label.is-placeholder{color:var(--o5-ink3);font-weight:500}
.co-trigger .co-caret{color:var(--o5-ink2);transition:transform .18s;flex:none;width:13px;height:13px;border:0}
.co-trigger.is-open .co-caret{transform:rotate(180deg)}

.co-pop{position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:500;background:var(--o5-surface);border:1px solid var(--o5-line);border-radius:16px;padding:8px;box-shadow:0 22px 44px -16px rgba(0,0,0,0.22),0 4px 12px -4px rgba(0,0,0,0.05);max-height:320px;display:flex;flex-direction:column}
.co-pop.is-up{top:auto;bottom:calc(100% + 8px)}
.co-pop[hidden]{display:none}
.co-pop-search{display:flex;align-items:center;gap:8px;padding:10px 14px;border:1px solid var(--o5-line);border-radius:999px;margin-bottom:6px;flex:none}
.co-pop-search svg{color:var(--o5-ink3);flex:none}
.co-pop-search input{flex:1;min-width:0;border:0;background:transparent;outline:none;font-family:var(--o5-display);font-size:13.5px;font-weight:600;color:var(--o5-ink)}
.co-pop-search input::placeholder{color:var(--o5-ink3);font-weight:500}
/* position:relative so it is the offsetParent of its own rows -- without it
   .co-pop is, and li.offsetTop then carries the search box's height, which
   co-select.js was comparing against the list's own scrollTop. */
.co-pop-list{position:relative;list-style:none;margin:0;padding:4px 2px;overflow-y:auto;-webkit-overflow-scrolling:touch;min-height:0}
.co-pop-list li{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:10px;cursor:pointer;font-family:var(--o5-display);font-size:13.5px;font-weight:600;color:var(--o5-ink);transition:background .12s}
.co-pop-list li:hover{background:var(--o5-surface-2)}
/* The keyboard's highlight. Distinct from :hover so arrowing through the list
   reads the same whether or not a pointer happens to be resting on it. */
.co-pop-list li.is-active{background:var(--o5-surface-2)}
.co-pop-list li.is-on{background:var(--o5-ink);color:#fff}
.co-pop-list li.is-on.is-active{background:var(--o5-ink)}
.co-pop-list li .flag{font-size:15px;line-height:1;flex:none}
.co-pop-list li .flag:empty{display:none}
.co-pop-list .empty{padding:14px 12px;font-family:var(--o5-display);font-size:12.5px;color:var(--o5-ink3);text-align:center;cursor:default;display:block}
.co-pop-list .empty:hover{background:transparent}

/* Step 5 while step 4 is incomplete. pointer-events rather than a disabled
   attribute so the whole section is inert, payment method tabs included. */
.op-section-card.is-locked{opacity:.45;pointer-events:none;user-select:none}

@media (max-width:640px){
    .co-fields.two{grid-template-columns:1fr}
}

/* The payment button's reason line. .co-dupe-error's -4px top margin is tuned
   to tuck under a .co-hint in step 4; there is no hint above this one, so it
   gets ordinary spacing instead. Everything else -- pill, circled mark, colour,
   full width -- is inherited unchanged, which is the point of reusing it. */
.op-pay-issue { margin: 10px 0 0; }
