/* FareChair — browse pages. Same tokens as the app: dark navy, royal blue
   accent, Sora display / Inter body / DM Mono for figures.
   Radius scale: 4 / 8 / 14 / 999. Spacing on a 4px rhythm. */

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  --bg:#07090F;--bg2:#0B0E18;
  --card:rgba(255,255,255,0.038);--card2:rgba(255,255,255,0.065);
  --border:rgba(255,255,255,0.07);--border2:rgba(255,255,255,0.13);
  --indigo:#2E7DF5;--indigo-l:#5B9BFF;--indigo-dim:rgba(46,125,245,0.13);
  --green:#22D3A5;--green-dim:rgba(34,211,165,0.10);
  /* Secondary and tertiary text were 52% and 27% white. Against this
     background that is roughly 5:1 and 2:1 — the tertiary tone failed the
     4.5:1 readability threshold outright, which is why source lines and
     "from" labels washed out on a phone in daylight. Raised to about 7:1 and
     4.6:1. Still clearly subordinate to the headline, just readable. */
  --text:#FFFFFF;--text2:rgba(255,255,255,0.66);--text3:rgba(255,255,255,0.50);
  --dm:'Inter',sans-serif;--sy:'Sora',sans-serif;--mono:'DM Mono',monospace;
}
html{scroll-behavior:smooth}
.skip-link{position:absolute;left:-9999px;top:0;z-index:999;background:var(--indigo);color:#fff;
  padding:10px 18px;border-radius:0 0 10px 0;font-size:14px;font-weight:600;text-decoration:none}
.skip-link:focus{left:0}
/* Keyboard focus. The search fields are excluded: .search-bar already shows
   focus with its own border and glow, and a second outline drawn inside it
   reads as a box around the input rather than an indicator. */
a:focus-visible,button:focus-visible,input:focus-visible,summary:focus-visible{
  outline:2px solid var(--indigo-l);outline-offset:2px;border-radius:6px}
.search-input:focus-visible,.search-loc:focus-visible{outline:none}
body{background:var(--bg);color:var(--text);font-family:var(--dm);min-height:100vh;overflow-x:hidden;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
::selection{background:rgba(46,125,245,.3)}
:focus-visible{outline:2px solid var(--indigo-l);outline-offset:2px;border-radius:4px}
@media(prefers-reduced-motion:reduce){*{animation-duration:.001ms!important;transition-duration:.001ms!important;scroll-behavior:auto!important}}
svg.ico{flex-shrink:0;display:block}

/* Crawlable but visually hidden — real links for search engines, no clutter. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ── Nav ── */
.nav{position:sticky;top:0;z-index:300;height:58px;display:flex;align-items:center;justify-content:space-between;padding:0 40px;background:rgba(7,9,15,.88);backdrop-filter:blur(24px);border-bottom:1px solid var(--border)}
.logo{font-family:var(--sy);font-size:20px;font-weight:800;letter-spacing:-1.5px;display:flex;align-items:center;gap:8px}
.logo span{color:var(--indigo)}
.nav-links{display:flex;gap:2px;list-style:none}
.nav-links a{color:var(--text2);font-size:13px;font-weight:500;padding:6px 12px;border-radius:8px;transition:color .15s,background .15s}
.nav-links a:hover{color:var(--text);background:var(--card2)}

/* ── Breadcrumb ── */
.crumb{max-width:1240px;margin:0 auto;padding:20px 40px 0;font-size:12px;color:var(--text3);display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.crumb a:hover{color:var(--text2)}
.crumb .sep{opacity:.5}

/* ── Page head ── */
.wrap{max-width:1240px;margin:0 auto;padding:0 40px 80px}
.phead{display:flex;gap:28px;align-items:center;padding:32px 0 40px;flex-wrap:wrap}
.part{width:132px;height:132px;border-radius:14px;flex-shrink:0;background-size:cover;background-position:center;border:1px solid var(--border);position:relative;overflow:hidden}
.part::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(0,0,0,.35))}
.ptext{min-width:0;flex:1}
.ptitle{font-family:var(--sy);font-size:38px;font-weight:800;letter-spacing:-1.4px;line-height:1.1}
.psub{color:var(--text2);font-size:14px;margin-top:12px;max-width:60ch;line-height:1.6}
.pchip{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--indigo-l);background:var(--indigo-dim);border:1px solid rgba(46,125,245,.25);padding:4px 12px;border-radius:999px;margin-bottom:16px}

/* ── Section heads ── */
/* Genre jump bar on the concerts and theatre hubs. Sticks under the nav so
   it stays reachable while scrolling a very long page. */
.genre-jump{display:flex;flex-wrap:wrap;gap:8px;margin:24px 0 8px;position:sticky;top:0;
  z-index:20;padding:14px 0;background:var(--bg);border-bottom:1px solid var(--border)}
.genre-jump a{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;
  color:var(--text2);text-decoration:none;background:var(--card);border:1px solid var(--border);
  padding:7px 13px;border-radius:999px;transition:color .15s,border-color .15s,background .15s}
.genre-jump a:hover{color:var(--text);border-color:var(--indigo);background:rgba(46,125,245,.10)}
.gj-n{font-family:var(--mono);font-size:11px;color:var(--text3)}
.genre-jump a:hover .gj-n{color:var(--indigo-l)}
.sec-n{font-family:var(--mono);font-size:13px;font-weight:400;color:var(--text3);margin-left:10px}
/* Anchored headings shouldn't hide under the sticky bar when jumped to. */
h2.sec[id]{scroll-margin-top:84px}
@media(max-width:640px){
  .genre-jump{gap:6px;padding:11px 0;margin:18px 0 6px}
  .genre-jump a{font-size:12px;padding:6px 11px}
}
/* Location panel. Sits above the events list rather than beside the heading,
   because on a touring act's page the first useful action is narrowing two
   dozen nationwide dates to the ones you could actually get to. */
.loc-panel{display:flex;align-items:center;justify-content:space-between;gap:16px;
  flex-wrap:wrap;background:var(--card);border:1px solid var(--border);
  border-radius:14px;padding:14px 18px;margin:0 0 18px}
.loc-panel.on{background:var(--indigo-dim);border-color:rgba(46,125,245,.3)}
.loc-panel-msg{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--text2)}
.loc-panel-msg svg{color:var(--text3);flex:none}
.loc-panel.on .loc-panel-msg{color:var(--text)}
.loc-panel.on .loc-panel-msg svg{color:var(--indigo-l)}
.loc-panel-ctl{display:flex;align-items:center;gap:9px}
.loc-input{background:var(--bg2);border:1px solid var(--border2);border-radius:10px;
  outline:none;color:var(--text);font-family:var(--dm);font-size:13.5px;
  padding:9px 13px;width:160px;transition:border-color .15s}
.loc-input:focus{border-color:var(--indigo)}
.loc-input::placeholder{color:var(--text3)}
.loc-near{display:inline-flex;align-items:center;gap:7px;background:var(--indigo);
  border:1px solid var(--indigo);color:#fff;font-size:13.5px;font-weight:600;
  padding:9px 15px;border-radius:10px;cursor:pointer;white-space:nowrap;
  transition:background .15s}
.loc-near:hover:not(:disabled){background:var(--indigo-l)}
.loc-near:disabled{opacity:.6;cursor:default}
.loc-clear{background:none;border:none;color:var(--text3);font-size:12.5px;
  font-weight:600;cursor:pointer;padding:8px 4px}
.loc-clear:hover{color:var(--text)}
h3.sub-sec{font-family:var(--sy);font-size:15px;font-weight:700;letter-spacing:-.3px;
  margin:26px 0 12px;display:flex;align-items:center;gap:9px;color:var(--text2)}
h3.sub-sec:first-child{margin-top:0}
h3.sub-sec::before{content:'';width:3px;height:15px;border-radius:2px;
  background:var(--indigo);flex:none}
#nearWrap{margin-bottom:4px}
@media(max-width:640px){
  .loc-panel{padding:13px 15px;gap:12px}
  .loc-panel-msg{font-size:13.5px}
  .loc-panel-ctl{width:100%}
  .loc-input{flex:1;width:auto}
}
/* Colour-coded league cards on the sports hub, matching the homepage so both
   pages describe the same leagues the same way. The icons are generic sport
   pictograms, not league marks — those belong to the leagues. */
.lgc-c{position:relative;background:color-mix(in srgb,var(--lg-hue) 7%,var(--card));
  border-color:color-mix(in srgb,var(--lg-hue) 22%,var(--border))}
.lgc-c svg{color:var(--lg-hue);margin-bottom:7px;display:block}
.lgc-c:hover{border-color:var(--lg-hue);
  background:color-mix(in srgb,var(--lg-hue) 14%,var(--card2))}
@supports not (color-mix(in srgb,red 50%,blue)){
  .lgc-c{background:var(--card);border-color:var(--border)}
}

/* City cards show a team count rather than a row of badges: 113 small images
   across 42 cards read as clutter, and the number says the same thing. Only
   teams whose own name begins with the city are counted — nothing is inferred
   about where a club actually plays. */
.ct-card{position:relative}

/* US map on the cities page. Boundaries are Census Bureau data; the dots are
   the 392 city pages at their real coordinates.

   No panel: the coastline is already a strong shape and a rounded box around
   it just competed with it. The map carries its own weight instead, in the
   site's blue rather than neutral grey, so it reads as part of FareChair
   rather than a chart dropped into the page. */
.us-map{margin:20px 0 4px;position:relative}
.us-map svg{width:100%;height:auto;display:block;overflow:visible}

.mp-bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;min-height:32px;
  flex-wrap:wrap}
.mp-hint{font-size:12.5px;color:var(--text3)}
.mp-hint kbd{font-family:var(--mono);font-size:10.5px;background:rgba(255,255,255,.06);
  border:1px solid var(--border2);border-radius:4px;padding:1px 5px;color:var(--text2)}
.mp-zoom{font-family:var(--dm);font-size:12px;font-weight:600;color:var(--text3)}
.mp-ctrl{margin-left:auto;display:flex;gap:6px}
.mp-ctrl button{background:transparent;border:1px solid var(--border2);color:var(--text2);
  font-size:13px;font-weight:600;padding:6px 12px;border-radius:9px;cursor:pointer;
  transition:border-color .15s,color .15s,background .15s;min-width:34px}
.mp-ctrl button:hover{border-color:var(--indigo);color:#fff;background:var(--indigo-dim)}

/* Land sits above the page in a blue-tinted fill, with borders bright enough
   to actually read as borders. */
/* The coastline gets its own weight, but there is no national outline in the
   data — only 49 state shapes. So the states are drawn twice: once underneath
   with a thick bright stroke, then again on top with their fill. The filled
   layer covers the inner half of every stroke and hides the interior borders
   completely, leaving the thick line visible only where nothing sits on top of
   it — the outside edge of the country.

   This is why the fill below is opaque rather than a 7% tint: a translucent
   fill would let the glow show straight through and light up every state
   border instead of just the coast. #0A111F is that tint flattened onto the
   page background, so it looks identical. */
.mp-glow path{fill:none;stroke:#5B9BFF;stroke-width:5;stroke-linejoin:round;
  stroke-linecap:round;opacity:.6;pointer-events:none}
.mp-state{fill:#0A111F;stroke:rgba(91,155,255,.38);stroke-width:1.1;
  cursor:pointer;transition:fill .18s,stroke .18s,opacity .18s}
.mp-state:hover{fill:#111C31}
/* Focused on one state: the rest of the country recedes rather than
   disappearing, so you keep your bearings. */
.us-map.is-focused .mp-state{opacity:.34}
.us-map.is-focused .mp-state.is-on{opacity:1;fill:#122139;stroke:rgba(91,155,255,.85);
  stroke-width:1.6}
.us-map.is-focused .mp-glow path{opacity:.18}
.mp-where{font-family:var(--sy);font-size:15px;font-weight:700;color:#fff}
.mp-back{background:var(--indigo-dim);border:1px solid var(--indigo);color:#fff;
  font-family:var(--dm);font-size:12.5px;font-weight:600;padding:6px 13px;
  border-radius:9px;cursor:pointer;transition:background .15s}
.mp-back:hover{background:var(--indigo)}
.us-map svg{cursor:grab;touch-action:pan-y;outline:none}
.us-map.is-panning svg{cursor:grabbing}
.us-map svg:focus-visible{outline:2px solid var(--indigo);outline-offset:4px;border-radius:10px}

/* Dots are set inline as the map zooms, so no transition on radius or stroke —
   animating them makes zooming feel laggy. The dark ring is what separates a
   dot from the land beneath it, and from its neighbours in a cluster. */
.mp-city{cursor:pointer}
.mp-city circle{fill:var(--indigo-l);stroke:#07090F;stroke-width:1.5;
  transition:fill .12s}
/* Invisible, but it is what the finger actually hits. */
.mp-hit{fill:transparent;stroke:none;pointer-events:all}
.mp-city:hover .mp-hit,.mp-city:focus-visible .mp-hit{fill:rgba(91,155,255,.14)}
.mp-city:hover circle,.mp-city:focus-visible circle{fill:#fff}

/* Cities of the state you tapped. This is the main way into a city — the map
   above is for orientation, this is for choosing. */
/* Sits directly under the map so the state you tapped and its cities read as
   one thing. */
.mp-list{margin:14px 0 4px;background:var(--bg2);border:1px solid var(--border2);
  border-radius:14px;padding:14px 16px 16px}
.mp-list-head{display:flex;align-items:baseline;gap:10px;margin-bottom:12px}
.mp-list-head strong{font-family:var(--sy);font-size:17px;color:#fff}
.mp-list-head span{font-size:12.5px;color:var(--text3)}
.mp-list-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(168px,1fr));gap:8px}
.mp-list-grid a{display:flex;flex-direction:column;gap:2px;padding:11px 13px;
  background:var(--card);border:1px solid transparent;border-radius:10px;
  text-decoration:none;transition:border-color .15s,background .15s}
.mp-list-grid a:hover{background:var(--card2);border-color:var(--indigo)}
.ml-n{font-weight:600;font-size:14.5px;color:#fff}
.ml-m{font-size:12px;color:var(--text3)}
@media(max-width:720px){
  .mp-list-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:7px}
  .mp-list-grid a{padding:12px}
}

/* Labels placed at build time where they fit. Cities that lost the collision
   still show their name on hover, so nothing on the map is unidentifiable. */
.mp-label{font-family:var(--dm);font-size:11px;font-weight:600;fill:rgba(255,255,255,.72);
  paint-order:stroke;stroke:#07090F;stroke-width:3.5;stroke-linejoin:round;
  pointer-events:none;transition:fill .12s}
.mp-city:hover .mp-label,.mp-city:focus-visible .mp-label{fill:#fff}
/* Visibility is decided live by the script, which re-runs the collision test
   for whatever is on screen. Hover always wins, at any zoom. */
.mp-city:not(.is-labelled) .mp-label{opacity:0}
.mp-city:hover .mp-label{opacity:1 !important}

@media(max-width:720px){
  .mp-hint{font-size:11.5px;flex-basis:100%;order:2}
  .mp-ctrl{margin-left:0}
  .mp-ctrl button{padding:7px 13px}
}

/* "Show more dates": the list starts at 24 because that is a sensible first
   screenful, not because that is all there is. */
.more-wrap{display:flex;justify-content:center;margin:18px 0 4px}
.more-btn{background:transparent;border:1px solid var(--border2);color:var(--text2);
  font-family:var(--dm);font-size:14px;font-weight:600;padding:11px 26px;
  border-radius:11px;cursor:pointer;transition:border-color .15s,color .15s,background .15s}
.more-btn:hover:not(:disabled){border-color:var(--indigo);color:#fff;background:var(--indigo-dim)}
.more-btn:disabled{opacity:.55;cursor:default}
.more-btn:focus-visible{outline:2px solid var(--indigo-l);outline-offset:2px}
.more-end{text-align:center;margin:16px 0 4px;color:var(--text3)}

/* Search within a city or venue. Sits above the chips because it narrows what
   the chips then filter. */
.ss{position:relative;display:flex;align-items:center;margin:0 0 12px}
.ss-ico{position:absolute;left:14px;display:flex;color:var(--text3);pointer-events:none}
.ss input{width:100%;background:var(--bg2);border:1px solid var(--border2);
  border-radius:12px;padding:13px 42px 13px 42px;color:var(--text);
  font-family:var(--dm);font-size:15px;transition:border-color .15s}
.ss input::placeholder{color:var(--text3)}
.ss input:focus{outline:none;border-color:var(--indigo)}
.ss input:focus+.ss-clear,.ss input:not(:placeholder-shown)+.ss-clear{display:flex}
.ss-clear{position:absolute;right:8px;width:28px;height:28px;display:flex;
  align-items:center;justify-content:center;background:none;border:0;
  color:var(--text3);font-size:20px;line-height:1;cursor:pointer;border-radius:8px}
.ss-clear:hover{color:#fff;background:var(--card)}
.ss input::-webkit-search-cancel-button{display:none}

/* Event-type chips on city pages. A city with thousands of events needs a
   way in that isn't scrolling. */
.cat-bar{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 16px}
.cat-chip{background:transparent;border:1px solid var(--border2);color:var(--text2);
  font-family:var(--dm);font-size:13.5px;font-weight:600;padding:8px 16px;
  border-radius:999px;cursor:pointer;transition:border-color .15s,color .15s,background .15s}
.cat-chip:hover{border-color:var(--indigo);color:#fff}
.cat-chip.is-on{background:var(--indigo);border-color:var(--indigo);color:#fff}
.cat-chip:focus-visible{outline:2px solid var(--indigo-l);outline-offset:2px}
.empty .linkish{background:none;border:0;padding:0;font:inherit;color:var(--indigo-l);
  text-decoration:underline;cursor:pointer}
@media(max-width:720px){
  .cat-bar{gap:6px;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;padding-bottom:2px}
  .cat-bar::-webkit-scrollbar{display:none}
  .cat-chip{flex:0 0 auto;padding:8px 15px}
}

/* City grid: a touch more room than the league cards, since city names run
   longer and the region headings already break the page into short lists. */
.lgc-grid{gap:12px}
.ct-n{color:var(--text3)}
.ct-n::before{content:' · '}

h2.sec{margin:0}
.loc-label{display:inline-flex;align-items:center;gap:8px;background:var(--card);
  border:1px solid var(--border);border-radius:10px;padding:8px 13px;color:var(--text3);
  transition:border-color .15s}
.loc-label:focus-within{border-color:var(--indigo)}
.loc-label:focus-within svg{color:var(--indigo-l)}
.loc-input{background:transparent;border:none;outline:none;color:var(--text);
  font-family:var(--dm);font-size:13.5px;width:130px}
.loc-input::placeholder{color:var(--text3)}
.loc-near{background:var(--indigo-dim);border:1px solid rgba(46,125,245,.3);
  color:var(--indigo-l);font-size:12.5px;font-weight:600;padding:8px 14px;
  border-radius:10px;cursor:pointer;white-space:nowrap;
  transition:background .15s,border-color .15s}
.loc-near:hover:not(:disabled){background:rgba(46,125,245,.2);border-color:var(--indigo)}
.loc-near:disabled{opacity:.6;cursor:default}
h3.sub-sec{font-family:var(--sy);font-size:15px;font-weight:700;letter-spacing:-.3px;
  margin:26px 0 12px;display:flex;align-items:center;gap:9px;color:var(--text2)}
h3.sub-sec:first-child{margin-top:0}
h3.sub-sec::before{content:'';width:3px;height:15px;border-radius:2px;
  background:var(--indigo);flex:none}
#nearWrap{margin-bottom:4px}
.loc-clear{background:none;border:none;color:var(--text3);font-size:12.5px;
  font-weight:600;cursor:pointer;padding:6px 4px}
.loc-clear:hover{color:var(--text)}
@media(max-width:640px){
  .loc-label{flex:1}
  .loc-input{width:100%}
}
h2.sec{font-family:var(--sy);font-size:20px;font-weight:700;letter-spacing:-.5px;margin:48px 0 20px;display:flex;align-items:center;gap:11px}
h2.sec::before{content:'';width:3px;height:19px;border-radius:2px;background:var(--indigo);flex:none}
h2.sec:first-of-type{margin-top:16px}
.note{font-size:12.5px;color:var(--text3);margin-top:-12px;margin-bottom:20px}

/* ── Event rows ── */
.elist{display:flex;flex-direction:column;gap:8px}
/* ── Ticket rows ──────────────────────────────────────────────────────
   The row is an actual stub: two semicircular bites are cut out of the top
   and bottom edges with a radial-gradient mask, and the perforation between
   them is a column of real dots. Because it is a mask, the bites show the
   page through the row rather than painting a matching circle on top — so
   they stay correct on any background. */
.erow{display:flex;align-items:stretch;gap:0;
  background:rgba(255,255,255,0.062);
  border-radius:12px;transition:background .15s,transform .15s;
  position:relative;isolation:isolate;
  --notch:15px;            /* diameter of the bite */
  --stub:118px;            /* width of the date stub  */
  -webkit-mask:
    radial-gradient(circle var(--notch) at var(--stub) 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--notch) at var(--stub) 100%,transparent 99%,#000 100%);
  -webkit-mask-composite:source-in;
  mask:
    radial-gradient(circle var(--notch) at var(--stub) 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--notch) at var(--stub) 100%,transparent 99%,#000 100%);
  mask-composite:intersect}
.erow:hover{background:rgba(255,255,255,0.095);transform:translateY(-1px)}

/* the perforation: a dotted column, inset so it clears both bites */
/* The perforation carries the whole ticket metaphor — at 55% opacity against
   a stub only 6% lighter than the body, the two halves read as one dark block
   and the shape was lost. Brighter dots, tighter spacing. */
.erow::before{content:'';position:absolute;left:var(--stub);top:12px;bottom:12px;
  width:2px;margin-left:-1px;z-index:2;pointer-events:none;
  background:repeating-linear-gradient(180deg,
    rgba(120,175,255,.95) 0 5px,transparent 5px 10px)}

.edate{font-family:var(--mono);font-size:12px;color:var(--indigo-l);
  width:var(--stub);flex-shrink:0;line-height:1.5;padding:18px 20px;
  /* Was a 10% tint over a 3.8% card — a 6% difference, invisible in practice.
     The stub needs to look like a torn-off half, so it gets a real step up in
     value plus its own edge. */
  background:linear-gradient(180deg,rgba(46,125,245,.24),rgba(46,125,245,.16));
  display:flex;flex-direction:column;justify-content:center}
.edate b{display:block;color:var(--text);font-size:15px;font-weight:500}
.einfo{padding:18px 22px}
.eprice{padding:18px 0}
.ecta{margin:0 20px;align-self:center}
@media (prefers-reduced-motion:reduce){.erow:hover{transform:none}}
/* no mask support: fall back to a plain bordered row rather than a broken one */
@supports not ((mask-composite:intersect) or (-webkit-mask-composite:source-in)){
  .erow{-webkit-mask:none;mask:none;border:1px solid var(--border)}
}
.einfo{flex:1;min-width:0}
.ename{font-size:14.5px;font-weight:600;letter-spacing:-.2px;margin-bottom:4px}
.evenue{font-size:12px;color:var(--text2);display:flex;align-items:center;gap:5px}
.eprice{text-align:right;flex-shrink:0}
.eamt{font-family:var(--mono);font-size:16px;color:var(--green)}
.eamt.none{font-size:12.5px;color:var(--text2);font-family:var(--dm)}
.elbl{font-size:10.5px;color:var(--text3);margin-top:2px}
.ecta{background:var(--indigo);color:#fff;font-size:12.5px;font-weight:600;padding:8px 16px;border-radius:8px;flex-shrink:0;transition:opacity .15s}
.ecta:hover{opacity:.86}
.esrc{font-size:10.5px;color:var(--text3);margin-top:4px;text-align:right}
/* One entry per marketplace. Wraps rather than truncating: a price that gets
   cut off is worse than a row that grows a line. */
.esrc-multi{display:flex;flex-wrap:wrap;gap:2px 5px;justify-content:flex-end;align-items:center;
  color:var(--indigo-l)}
.esrc-one{white-space:nowrap}
.esrc-one b{font-weight:600}
.esrc-sep{opacity:.45}
.esrc-note{display:block;font-size:9.5px;color:var(--text3);opacity:.8;margin-top:1px}

/* ── Team grid ──
   16:9 art panel matching the source aspect, so Ticketmaster's artwork is
   never cropped. Colour sits behind as the fallback: it shows through while
   the image loads, and stays for teams with no artwork. */
.tgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(196px,1fr));gap:16px}
.tcard{display:block;background:var(--card);border:1px solid var(--border);border-radius:14px;overflow:hidden;transition:border-color .15s,background .15s,transform .15s}
.tcard:hover{border-color:var(--indigo);background:rgba(46,125,245,.10);transform:translateY(-2px)}
.tart{display:block;width:100%;aspect-ratio:16/9;background-size:contain;background-position:center;background-repeat:no-repeat;border-bottom:1px solid var(--border);position:relative}
/* The gradient existed to keep a logo legible over club colour. With the name
   set into the block instead, it adds depth so a tile reads as a designed card
   rather than a flat swatch. */
.tart::after{content:'';position:absolute;inset:0;
  background:linear-gradient(160deg,rgba(255,255,255,.10),rgba(0,0,0,.34))}

/* ── Wordmark tiles ───────────────────────────────────────────────────────
   Club marks are league creative and we do not have permission to use them,
   so tiles carry the club's colour and its name instead. See the note in
   fc.js. Set in the display face at a size that fills the block, which is
   what stops it looking like a placeholder for a missing image. */
.tart-word{display:flex;align-items:flex-end}
/* The page hero is a 132px square rather than a wide tile, so the name needs
   to be smaller and centred to sit properly inside it. */
.part.tart-word .tw{padding:0 8px 9px;text-align:center}
.part.tart-word .tw-city{font-size:8.5px;letter-spacing:.06em}
.part.tart-word .tw-nick{font-size:15px;line-height:1.05}
.tw{position:relative;z-index:1;padding:0 14px 12px;width:100%;
  color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.35)}
/* Light primaries — Steelers gold, Saints old gold — need dark type. */
.tart-word.is-light .tw{color:#10131a;text-shadow:0 1px 1px rgba(255,255,255,.35)}
.tw-city{display:block;font-size:11px;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;opacity:.82;line-height:1.2;margin-bottom:1px}
.tw-nick{display:block;font-family:var(--sy);font-weight:800;
  font-size:clamp(17px,2.4vw,22px);letter-spacing:-.02em;line-height:1.05}
/* The name is inside the block now, so repeating it underneath is noise. */
.tart-word + .tname{display:none}
@media(max-width:560px){
  .tw-nick{font-size:16px}
  .tw{padding:0 11px 10px}
}
.tname{display:block;padding:12px 16px 14px;font-size:13.5px;font-weight:600;letter-spacing:-.2px;line-height:1.3}
@supports not (aspect-ratio:16/9){.tart{height:110px}}

/* Attribution. Ticketmaster tags a minority of images with a credit string;
   when one comes back we show it over the image rather than dropping it. */
.art-credit{position:absolute;right:5px;bottom:4px;z-index:2;max-width:calc(100% - 10px);
  font-size:9.5px;line-height:1.25;color:rgba(255,255,255,.62);
  text-shadow:0 1px 2px rgba(0,0,0,.85);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  pointer-events:none}

/* ── Conference cards ── */
.lgc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:12px}
.lgc{display:flex;flex-direction:column;gap:4px;padding:20px 24px;background:var(--card);border:1px solid var(--border);border-radius:14px;transition:border-color .15s,background .15s}
.lgc:hover{border-color:var(--indigo);background:var(--card2)}
.lgc-n{font-family:var(--sy);font-size:20px;font-weight:800;letter-spacing:-.7px}
.lgc-s{font-size:11.5px;color:var(--text3)}
.pt-grid{display:flex;flex-wrap:wrap;gap:8px}
.pt{font-size:13px;color:var(--text2);background:var(--card);border:1px solid var(--border);padding:8px 16px;border-radius:999px;transition:color .15s,border-color .15s}
.pt:hover{color:var(--text);border-color:var(--indigo);background:rgba(46,125,245,.10)}

/* ── Explainer ── */
.exp{background:var(--bg2);border:1px solid var(--border);border-radius:14px;padding:28px 32px;margin-top:48px}
.exp h3{font-family:var(--sy);font-size:16px;font-weight:700;margin-bottom:12px}
.exp p{font-size:13.5px;color:var(--text2);line-height:1.7;max-width:76ch}
.exp p+p{margin-top:12px}

/* ── Loading / empty ── */
.sk{height:70px;background:var(--card);border:1px solid var(--border);border-radius:14px;margin-bottom:8px;position:relative;overflow:hidden}
.sk::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,.04),transparent);animation:sh 1.4s infinite}
@keyframes sh{100%{transform:translateX(100%)}}
.empty{padding:40px;text-align:center;color:var(--text3);font-size:14px;border:1px solid var(--border);border-radius:14px;background:var(--card)}

/* ── Footer ── */
.foot{border-top:1px solid var(--border);background:var(--bg2);padding:40px 0 48px;margin-top:64px}
.foot-in{max-width:1240px;margin:0 auto;padding:0 40px}
.foot-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:32px;margin-bottom:32px}
.foot-h{font-size:11px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text3);margin-bottom:12px}
.foot-l{display:flex;flex-direction:column;gap:8px}
.foot-l a{font-size:13px;color:var(--text2);transition:color .15s}
.foot-l a:hover{color:var(--text)}
.disc{font-size:11.5px;color:var(--text3);line-height:1.7;border-top:1px solid var(--border);padding-top:24px;max-width:88ch}

@media(max-width:860px){
  /* The nav used to scroll sideways to fit five links next to the logo. On a
     375px screen that hid "Sports" entirely and clipped "Concerts" to
     "oncerts" — links a visitor cannot see are links that do not exist, and a
     horizontal scroll inside a sticky header is easy to miss.

     Two rows instead: logo, then the links spread across the full width. The
     header gets taller, which is the trade, but every destination is visible
     without discovering a gesture. */
  .nav{padding:8px 16px 10px;height:auto;flex-wrap:wrap;justify-content:center;
    row-gap:6px}
  .nav .logo{width:100%;justify-content:center;font-size:18px}
  .nav-links{display:flex;flex-wrap:nowrap;overflow:visible;width:100%;
    justify-content:space-between;gap:0}
  .nav-links a{white-space:nowrap;padding:5px 4px;font-size:12.5px;
    letter-spacing:-.1px}

  /* Very narrow phones need one more notch of room. */
  @media(max-width:360px){
    .nav-links a{font-size:11.5px;padding:5px 2px}
  }

  /* Team tiles: two per row on phones, not one.
     The grid's 196px minimum resolves to a single column on a 375px screen,
     which turned "All NFL teams" into 32 full-width blocks and about eight
     screens of scrolling to reach the last one. Two columns at a shorter
     ratio puts the same 32 teams in 16 rows and makes the grid scannable
     rather than something to endure. */
  .tgrid{grid-template-columns:repeat(2,1fr);gap:10px}
  .tart{aspect-ratio:3/2}
  @supports not (aspect-ratio:3/2){.tart{height:96px}}
  .tw{padding:0 10px 9px}
  .tw-city{font-size:9.5px;letter-spacing:.07em}
  .tw-nick{font-size:15px;line-height:1.1}
  .crumb,.wrap,.foot-in{padding-left:20px;padding-right:20px}
  .ptitle{font-size:28px}
  .part{width:88px;height:88px}
  /* Ticket stays horizontal on phones — stub on the left, as on desktop.
     It used to run across the top, stacking date / details / price / a
     full-width button into four bands about 190px tall.

     Laid out as a grid rather than a flex row. As a flex row the price column
     sized itself to the widest source line ("Ticketmaster At checkout ·
     SeatGeek At checkout"), which squeezed the title to one word per line and
     let the two columns overlap. The grid gives the title the full width of
     the right-hand area and puts price and button on a second line beneath
     it, so nothing competes for the same space. */
  /* A 15px bite reads as a small perforation on a 118px desktop stub; on a
     64px one it is nearly a quarter of the width and dominates the row. */
  .erow{display:grid;--stub:64px;--notch:10px;
    grid-template-columns:var(--stub) 1fr auto;
    grid-template-rows:auto auto;
    align-items:stretch;column-gap:0;row-gap:0}
  .edate{grid-column:1;grid-row:1 / 3;width:auto;height:auto;
    padding:12px 4px;flex-direction:column;align-items:center;
    justify-content:center;gap:1px;text-align:center;font-size:10.5px}
  .edate b{display:block;font-size:16px;line-height:1.12}
  .einfo{grid-column:2 / 4;grid-row:1;padding:12px 14px 2px;min-width:0}
  .einfo .ename{font-size:14.5px;line-height:1.28;margin-bottom:3px}
  .einfo .evenue{font-size:11.5px;line-height:1.35}
  .eprice{grid-column:2;grid-row:2;width:auto;text-align:left;
    padding:2px 0 12px 14px;display:flex;flex-direction:column;
    align-items:flex-start;justify-content:flex-end;min-width:0}
  .eamt{font-size:18px}
  .elbl{display:inline;margin:0 0 0 4px}
  .esrc{text-align:left;font-size:10px;margin-top:3px}
  .esrc-multi{justify-content:flex-start}
  .ecta{grid-column:3;grid-row:2;align-self:end;justify-self:end;
    margin:0 14px 12px 8px;padding:9px 14px;font-size:12px;width:auto}

  /* Contrast: the source line and "from" label sat on --text3, which is
     legible on a desktop monitor and close to invisible on a phone outdoors.
     Both carry real information — which marketplace, and that the figure is a
     starting price — so they move up a step. */
  .esrc{color:var(--text2)}
  .esrc-one b{color:var(--text)}
  .elbl{color:var(--text2)}
}

/* ── Event pages ──────────────────────────────────────────────────────────
   Per-event comparison pages generated by gen/events.js. Deliberately plain:
   the page exists to state a date, a venue and what each marketplace asks,
   then get out of the way. */
.evhead{padding:28px 0 20px;border-bottom:1px solid var(--border)}
.evhead h1{font-family:var(--sy);font-weight:800;font-size:clamp(24px,4.4vw,38px);
  line-height:1.14;letter-spacing:-.02em;margin:0 0 10px}
.evmeta{color:var(--text2);font-size:15px;margin:2px 0}

.evbox{margin:26px 0 34px}
.evbox h2{font-family:var(--sy);font-weight:700;font-size:17px;margin:0 0 12px}
.evtab{width:100%;border-collapse:collapse;margin-bottom:14px}
.evtab td{padding:14px 12px;border-bottom:1px solid var(--border);vertical-align:middle}
.evtab tr:last-child td{border-bottom:0}
.evsrc{font-size:15px;font-weight:600}
/* The disclosure sits under the source name rather than beside the price, so
   it reads as a property of the marketplace and not a footnote on the number. */
.evnote{display:block;font-size:11px;font-weight:400;color:var(--text3);margin-top:3px}
.evamt{font-family:var(--mono);font-size:19px;text-align:right;white-space:nowrap}
.evgo{text-align:right;width:1%}
.evfine{color:var(--text3);font-size:12.5px;line-height:1.55;margin:10px 0 0;max-width:56ch}
.evback{margin:26px 0 40px}
.evback a{color:var(--indigo-l);font-size:15px;font-weight:600}

.btn{display:inline-block;background:var(--indigo);color:#fff;font-weight:600;
  font-size:14px;padding:9px 18px;border-radius:9px;border:0;cursor:pointer;
  font-family:var(--dm)}
.btn:hover{background:var(--indigo-l)}
.btn-lg{display:block;width:100%;padding:14px;font-size:15px;
  background:var(--card2);border:1px solid var(--border2)}
.btn-lg:hover{background:var(--card2);border-color:var(--indigo)}
.btn-lg:disabled{opacity:.55;cursor:default}

@media(max-width:560px){
  .evtab td{padding:12px 6px}
  .evamt{font-size:17px}
}
