/* ===== Jerk Alert — Website UI kit styles ===== */
@import url('../colors_and_type.css');

* { box-sizing: border-box; }
:root { --ja-kb: 0px; }
html, body { margin: 0; padding: 0; }
body { font-family: var(--font-body); color: var(--fg1); background: var(--bg); -webkit-font-smoothing: antialiased; }
#root { min-height: 100vh; display: flex; flex-direction: column; }
button { font-family: inherit; }
a { color: inherit; text-decoration: none; }
.ico { display: inline-flex; align-items: center; justify-content: center; }
.ico svg { display: block; }

/* ---- layout ---- */
.wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.flex { display: flex; }
.col { display: flex; flex-direction: column; }
.between { justify-content: space-between; }
.center { align-items: center; }
.gap-1{gap:4px}.gap-2{gap:8px}.gap-3{gap:12px}.gap-4{gap:16px}.gap-5{gap:20px}.gap-6{gap:24px}.gap-8{gap:32px}
.grow { flex: 1; }
.wrapw { flex-wrap: wrap; }

/* ---- buttons ---- */
.btn { font-family: var(--font-display); font-weight: 800; border: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: var(--r-pill); transition: transform var(--dur-fast) var(--ease-pop), box-shadow var(--dur) var(--ease-out), background var(--dur) var(--ease-out); white-space: nowrap; }
.btn:active { transform: scale(.97); }
.btn-lg { font-size: 16px; padding: 13px 24px; }
.btn-md { font-size: 14px; padding: 10px 18px; }
.btn-sm { font-size: 13px; padding: 7px 14px; }
.btn-primary { background: var(--ja-alert); color: #fff; box-shadow: var(--sh-alert); }
.btn-primary:hover { background: var(--ja-alert-ink); box-shadow: 0 10px 26px rgba(251,77,26,.4); }
.btn-secondary { background: var(--ja-teal); color: #fff; }
.btn-secondary:hover { background: var(--ja-teal-deep); }
.btn-ghost { background: #fff; color: var(--fg1); border: 1.5px solid var(--line-strong); }
.btn-ghost:hover { border-color: var(--fg3); box-shadow: var(--sh-sm); }
.btn-subtle { background: var(--ja-alert-tint); color: var(--ja-alert-ink); }
.btn-subtle:hover { background: #ffd9cc; }
.btn-ink { background: var(--ja-ink); color: #fff; }
.btn-ink:hover { background: var(--ja-ink-soft); }
.btn-awesome { background: var(--awesome); color: #fff; }
.btn-awesome:hover { background: #128257; }
.btn:disabled { opacity: .55; pointer-events: none; }
/* Icon-only and text-only click targets are real <button>s (keyboard, screen reader); this strips the UA chrome. */
.btn-icon { background: none; border: none; padding: 0; margin: 0; color: var(--fg3); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font: inherit; }
.btn-icon:hover { color: var(--fg1); }

/* ---- pills ---- */
.pill { font-family: var(--font-display); font-weight: 800; font-size: 13.5px; display: inline-flex; align-items: center; gap: 7px; padding: 9px 15px; border-radius: var(--r-pill); border: 1.5px solid var(--line-strong); background: #fff; color: var(--fg1); cursor: pointer; transition: all var(--dur) var(--ease-out); }
.pill:hover { border-color: var(--fg3); transform: translateY(-1px); }
.pill.on { background: var(--ja-ink); color: #fff; border-color: var(--ja-ink); }

/* ---- badges ---- */
.badge { font-family: var(--font-display); font-weight: 800; font-size: 11px; letter-spacing: .05em; display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px; border-radius: var(--r-pill); white-space: nowrap; }
.badge svg { width: 13px; height: 13px; }
.badge-verified { background: var(--ja-ink); color: #fff; }
.badge-cleared { background: var(--awesome-tint); color: var(--awesome); }
.badge-offender { background: var(--ja-alert-tint); color: var(--ja-alert-ink); }
.badge-trending { background: var(--ja-yellow-tint); color: var(--ja-yellow-deep); }
/* Status pills that are not a plate status: outline = neutral fact (UNVERIFIED, REMOVED), warn = waiting on
   the user or the clock (PENDING, CONFIRM IN YOUR EMAIL), new = unread count. One shape for all of them. */
.badge-outline { background: #fff; color: var(--fg2); border: 1px solid var(--line-strong); padding: 5px 10px; }
.badge-warn { background: var(--ja-yellow-tint); color: var(--ja-ink); border: 1.5px solid var(--ja-yellow-deep); padding: 4.5px 10px; }
.badge-new { background: var(--ja-alert); color: #fff; }
.badge-teal { background: var(--ja-teal-tint); color: var(--ja-teal-deep); }

/* ---- avatar ---- */
.avatar { border-radius: var(--r-pill); display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-display); font-weight: 900; color: #fff; flex: none; }

/* ---- jerk meter ---- */
.meter { display: inline-flex; align-items: center; gap: 3px; }
.meter .ico svg { display: block; }

/* ---- cards ---- */
.card { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--sh-sm); }
.listing { display: flex; gap: 16px; padding: 16px; cursor: pointer; transition: box-shadow var(--dur) var(--ease-out), transform var(--dur) var(--ease-out); }
.listing:hover { box-shadow: var(--sh-md); transform: translateY(-2px); }
.thumb { border-radius: var(--r-md); flex: none; position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.thumb .ph { color: #fff; opacity: .85; }

/* ---- inputs ---- */
.field { width: 100%; border: 1.5px solid var(--line-strong); border-radius: var(--r-md); padding: 12px 14px; font-family: var(--font-body); font-size: 16px; color: var(--fg1); background: #fff; outline: none; transition: border-color var(--dur), box-shadow var(--dur); }
select.field { cursor: pointer; padding-right: 8px; }
.state-select { text-align: center; font-weight: 800; }
.field:focus { border-color: var(--ja-teal); box-shadow: 0 0 0 3px var(--ja-teal-tint); }

/* ---- reason picker (icon buttons) ---- */
.reason-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.reason-btn {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 7px;
  padding: 12px 7px 11px; min-height: 104px; border: 1.5px solid var(--line-strong);
  border-radius: var(--r-md); background: #fff; cursor: pointer; text-align: center;
  transition: border-color .12s, background .12s, transform .12s, box-shadow .12s;
}
.reason-btn:hover { border-color: var(--fg3); transform: translateY(-1px); box-shadow: var(--sh-sm); }
.reason-btn:active { transform: scale(.97); }
.reason-btn img { width: 54px; height: 54px; object-fit: contain; display: block; pointer-events: none; }
.reason-btn .rlucide { width: 54px; height: 54px; display: flex; align-items: center; justify-content: center; }
.reason-btn .rlabel { font-family: var(--font-display); font-weight: 700; font-size: 11.5px; line-height: 1.18; color: var(--fg2); text-wrap: balance; }
.reason-btn.on { box-shadow: 0 0 0 1.5px currentColor inset; }
.reason-btn.disabled { opacity: .4; pointer-events: none; }
/* Track-frequency picker reuses the reason tile; .rdesc is its one extra line. */
.reason-btn.compact { min-height: 0; padding: 14px 10px 12px; }
.reason-btn .rdesc { font-size: 11.5px; color: var(--fg3); line-height: 1.3; }

/* ---- top nav ---- */
/* padding-top keeps the nav clear of the status bar / punch-hole camera when the webview
   draws edge-to-edge (installed app, PWA, viewport-fit=cover). 0 in a normal browser. */
.nav { position: sticky; top: 0; z-index: 50; background: #fff; border-bottom: 1px solid var(--line); padding-top: env(safe-area-inset-top); }
.nav-inner { height: 68px; display: flex; align-items: center; gap: 20px; }
.logo { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.logo img { height: 38px; width: auto; }
.logo-word { font-family: var(--font-display); font-weight: 900; font-size: 24px; letter-spacing: -.02em; line-height: 1; }
/* The header lookup is a miniature licence plate: a stamped body, an embossed rim,
   two mounting bolts and the state on its own band. It is the same act as reading a
   plate in traffic, so it should look like one rather than like a web search field. */
.navsearch { flex: 0 0 auto; display: flex; align-items: center; position: relative; width: 320px;
  background: linear-gradient(180deg, #fdfdf8 0%, #f2f1e8 55%, #e6e5db 100%);
  border: 2px solid #16233f; border-radius: 9px; overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 2px rgba(255,255,255,.75), 0 1px 2px rgba(22,35,63,.28); }
/* No mounting bolts at this size: at ~24px of plate body they land on the number
   and read as specks rather than as hardware. The rim and the state band carry it. */
.navsearch .seg { display: flex; align-items: center; gap: 7px; padding: 8px 13px; flex: 1; }
.navsearch .state-seg { background: linear-gradient(180deg, #1d2c4d, #16233f); border-radius: 6px; padding: 8px 11px; margin-left: 5px; }
.navsearch .state-seg .ico { color: rgba(255,255,255,.65) !important; }
.navsearch .state-seg select { color: #fff !important; letter-spacing: .06em; }
.navsearch .state-seg select option { color: #16233f; background: #fff; }
/* The go button already carries an arrow; the in-field magnifier only ate room the
   number needed, and a plate that clips its own number is worse than no metaphor. */
.navsearch .seg:not(.state-seg) > .ico { display: none; }
.navsearch .seg:not(.state-seg) { padding-left: 11px; min-width: 118px; }
.navsearch input { border: none; outline: none; font-family: var(--font-display); font-weight: 900; font-size: 16px;
  letter-spacing: .07em; width: 100%; background: transparent; color: #16233f; }
.navsearch input::placeholder { color: rgba(22,35,63,.38); font-weight: 800; letter-spacing: .06em; }
.navsearch .divider { width: 0; margin: 0; }
.navsearch .go { background: var(--ja-alert); color: #fff; border: none; margin: 4px; border-radius: 6px; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; cursor: pointer; flex: none; }
.navlink { font-family: var(--font-display); font-weight: 700; font-size: 14px; color: var(--fg2); cursor: pointer; background: none; border: none; padding: 0; }
/* The Watch reads as a destination, not a link: a pill, to the right of the post CTA. */
.nav-watch { border: 1.5px solid var(--line-strong); border-radius: var(--r-pill); padding: 8px 15px;
  background: #fff; white-space: nowrap; transition: border-color .15s, color .15s, background .15s; }
.nav-watch:hover { border-color: var(--ja-teal); color: var(--ja-teal); background: var(--ja-teal-tint); }
.navlink:hover { color: var(--fg1); }

/* ---- incident map ---- */
.map-layout { display: grid; grid-template-columns: 1fr 340px; gap: 18px; }
.map-panel {
  position: relative; border-radius: var(--r-lg); overflow: hidden;
  border: 1.5px solid var(--line-strong); box-shadow: var(--sh-sm);
  aspect-ratio: 16 / 10; background: #FBF4E9; cursor: crosshair; width: 100%;
}
.map-bg { position: absolute; inset: 0; width: 100%; height: 100%; }
.map-pin {
  position: absolute; transform: translate(-50%,-50%); border: none; background: none;
  padding: 0; cursor: pointer; transition: transform var(--dur) var(--ease-pop);
}
.map-pin-dot {
  width: 36px; height: 36px; border-radius: var(--r-pill); background: var(--pin);
  border: 2.5px solid #fff; box-shadow: 0 3px 8px rgba(30,45,51,.28);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.map-pin-dot img { width: 30px; height: 30px; object-fit: contain; display: block; }
.map-pin:hover { transform: translate(-50%,-50%) scale(1.14); }
.map-pin.on { transform: translate(-50%,-50%) scale(1.22); }
.map-pin.on .map-pin-dot { box-shadow: 0 0 0 4px color-mix(in srgb, var(--pin) 30%, transparent), 0 4px 10px rgba(30,45,51,.3); }
.map-card {
  position: absolute; width: 232px; background: #fff; border: 1.5px solid var(--line-strong);
  border-radius: var(--r-md); box-shadow: var(--sh-lg); padding: 13px; z-index: 50;
  display: flex; flex-direction: column; gap: 7px; cursor: default;
}
.map-card-link {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; margin-top: 2px;
  background: none; border: none; cursor: pointer; padding: 0;
  font-family: var(--font-display); font-weight: 800; font-size: 13px; color: var(--ja-teal);
}
.map-card-link:hover { color: var(--ja-alert); }
.map-list { display: flex; flex-direction: column; min-height: 0; }
.map-list-scroll { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; max-height: 460px; padding-right: 4px; }
.map-row {
  display: flex; align-items: center; gap: 11px; padding: 10px; cursor: pointer;
  border-radius: var(--r-md); border: 1.5px solid var(--line); background: #fff; transition: all var(--dur-fast) var(--ease-out);
}
.map-row:hover { border-color: var(--line-strong); }
.map-row.on { border-color: var(--ja-alert); background: var(--ja-alert-tint); }
.map-row-ico {
  width: 42px; height: 42px; flex: none; border-radius: var(--r-sm); padding: 5px;
  background: #fff; border: 1.5px solid; display: flex; align-items: center; justify-content: center;
}
.map-row-ico img { width: 100%; height: 100%; object-fit: contain; display: block; }
@media (max-width: 820px) {
  .map-layout { grid-template-columns: 1fr; }
  .map-list-scroll { max-height: 320px; }
}

/* ---- hero ---- */
.hero { background: var(--bg-warm); border-bottom: 1px solid var(--line); position: relative; overflow: hidden; }
.hero-grid { display: grid; grid-template-columns: 1.25fr 0.85fr; gap: 32px; align-items: center; }
.hero-mascot { position: relative; }
.hero-mascot img { width: 100%; max-width: 440px; height: auto; display: block;
  filter: drop-shadow(0 18px 30px rgba(217,77,26,.18)); animation: mascotFloat 5s ease-in-out infinite; }
@keyframes mascotFloat { 0%,100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-12px) rotate(-1.2deg); } }
@media (max-width: 860px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-mascot { order: -1; }
  .hero-mascot img { max-width: 280px; margin: 0 auto 8px; animation: none; }
}
.hero-search { display: flex; align-items: center; background: #fff; border: 2px solid var(--ja-ink); border-radius: var(--r-pill); box-shadow: var(--sh-md); overflow: hidden; }
.hero-search .seg { display: flex; align-items: center; gap: 10px; padding: 16px 20px; flex: 1; }
.hero-search input { border: none; outline: none; font-family: var(--font-body); font-size: 16px; font-weight: 500; width: 100%; background: transparent; }
.hero-search .divider { width: 1px; align-self: stretch; background: var(--line-strong); margin: 12px 0; }
.hero-search .go { background: var(--ja-alert); color: #fff; border: none; margin: 6px; border-radius: var(--r-pill); height: 52px; padding: 0 26px; display: flex; align-items: center; gap: 8px; cursor: pointer; font-family: var(--font-display); font-weight: 800; font-size: 16px; box-shadow: var(--sh-alert); }

/* ---- category tile ---- */
.cat-tile { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 20px; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; cursor: pointer; transition: all var(--dur) var(--ease-out); box-shadow: var(--sh-xs); }
.cat-tile:hover { transform: translateY(-3px); box-shadow: var(--sh-md); border-color: transparent; }
.cat-ico { width: 48px; height: 48px; border-radius: var(--r-md); display: flex; align-items: center; justify-content: center; }

/* ---- section ---- */
.section { padding: 56px 0; }
.section.warm { background: var(--bg-warm); }
.eyebrow { font-family: var(--font-display); font-weight: 800; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--ja-alert); }

/* ---- footer ---- */
.footer { background: var(--ja-ink); color: var(--fg-on-dark); margin-top: auto; padding: 48px 0 32px; }
.footer a { color: rgba(255,248,240,.72); font-size: 14px; display: block; padding: 5px 0; }
.footer a:hover { color: #fff; }
.footer h5 { font-family: var(--font-display); font-weight: 800; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: #fff; margin: 0 0 8px; }

/* ---- detail ---- */
.plate-banner { display: grid; grid-template-columns: 2fr 1fr; gap: 12px; height: 320px; }
.plate-photo { background: #1b2b31; border-radius: var(--r-lg); overflow: hidden; display: flex; align-items: center; justify-content: center; padding: 28px; }
.lp { width: 100%; max-width: 460px; aspect-ratio: 2 / 1; background: linear-gradient(#fdfdfb, #eef1ee); border: 3px solid #16324a; border-radius: 16px; box-shadow: 0 10px 24px rgba(0,0,0,.35), inset 0 0 0 2px #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; padding: 6% 4%; }
.lp-state { font-family: var(--font-display); font-weight: 800; font-size: clamp(14px, 3.4vw, 26px); letter-spacing: .06em; color: #16324a; text-transform: uppercase; }
.lp-num { font-family: var(--font-display); font-weight: 900; font-size: clamp(34px, 10vw, 78px); letter-spacing: .09em; color: #16324a; line-height: 1; margin: 2% 0; }
.lp-org { position: absolute; bottom: 6%; font-family: var(--font-body); font-weight: 600; font-size: clamp(8px, 1.6vw, 11px); letter-spacing: .12em; color: #6b7f8c; text-transform: uppercase; }
.plate-inf { border-radius: var(--r-lg); display: flex; align-items: center; justify-content: center; padding: 40px; }
@media (max-width: 720px) { .plate-banner { grid-template-columns: 1fr; height: auto; } .plate-photo { height: 220px; } .plate-inf { height: 160px; } }
.gallery { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 6px; border-radius: var(--r-lg); overflow: hidden; height: 320px; }
.gallery > div { position: relative; display: flex; align-items: center; justify-content: center; color: #fff; }
.breakdown-bar { height: 10px; border-radius: var(--r-pill); background: var(--jerk-track); overflow: hidden; }
.breakdown-bar > div { height: 100%; border-radius: var(--r-pill); }

/* ---- map panel ---- */
.mappanel { background: #E9EDE9; border-radius: var(--r-lg); position: relative; overflow: hidden; border: 1px solid var(--line); }
.mappin { position: absolute; transform: translate(-50%,-100%); cursor: pointer; }

/* ---- modal ---- */
/* The insets keep the modal — and its footer buttons — clear of the status bar and of the
   Android system nav bar (back / home / recents), which overlay the webview when it draws
   edge-to-edge. Both are 0 in a normal desktop browser. max-height is 100% (of the scrim's
   padded content box) rather than 90vh: vh counts the strip UNDER the system bars, so 90vh
   put the footer beneath the nav buttons on a phone. */
.scrim { position: fixed; inset: 0; background: rgba(30,45,51,.5); backdrop-filter: blur(3px); z-index: 100; display: flex; align-items: center; justify-content: center; padding: calc(24px + env(safe-area-inset-top)) 24px calc(24px + env(safe-area-inset-bottom)); }
.modal { background: #fff; border-radius: var(--r-xl); box-shadow: var(--sh-lg); width: 100%; max-width: 520px; max-height: 100%; overflow-y: auto; }

/* A modal that opts in with .modal-flex is a THREE-PART box at every width: a fixed head, a
   scrolling middle, and a fixed foot. Before this, head/body/foot all sat in one scrolling box
   and the foot was held down with position:sticky — so on a short sheet (phone, or keyboard
   open) the sticky foot rode up over the header, and on the desktop the Cancel / Post buttons
   scrolled out of sight. A flex column cannot do either: the foot is always on screen and the
   head and foot can never overlap each other or the content.
   Only the foot carries the bottom safe-area inset, not the scrim — the sheet is meant to reach
   the bottom edge of the screen, so padding the scrim would leave a strip of backdrop under it.
   env() is 0 in a desktop browser, so this costs nothing there. */
.modal.modal-flex { display: flex; flex-direction: column; overflow: hidden; }
.modal.modal-flex > .modal-head, .modal.modal-flex > .modal-foot { flex: none; }
.modal.modal-flex > .modal-body { flex: 1 1 auto; overflow-y: auto; min-height: 0; -webkit-overflow-scrolling: touch; }
.modal.modal-flex > .modal-foot { padding-bottom: calc(16px + env(safe-area-inset-bottom)) !important; }
/* The head needs the TOP inset for the same reason the foot needs the bottom one: at phone widths
   .scrim drops to padding:0 so the sheet can reach both screen edges, which throws away the
   env() padding the scrim carries on desktop. Without this the title sits under the status bar /
   punch-hole camera. !important because the modals set their own inline padding.
   --ja-safe-top lets the device simulator supply an inset env() cannot report inside an iframe. */
.modal.modal-flex > .modal-head { padding-top: calc(20px + var(--ja-safe-top, env(safe-area-inset-top))) !important; }

/* ---- toast ---- */
.toast { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); background: var(--ja-ink); color: #fff; padding: 14px 22px; border-radius: var(--r-pill); box-shadow: var(--sh-lg); font-family: var(--font-display); font-weight: 800; font-size: 15px; z-index: 200; display: flex; align-items: center; gap: 10px; animation: toastin .4s var(--ease-pop); }
.toast.toast-error { background: var(--ja-alert-ink); }
@keyframes toastin { from { transform: translate(-50%,20px); opacity: 0; } }

@media (max-width: 900px) {
  .results-grid { grid-template-columns: 1fr !important; }
  .map-col { display: none !important; }
  .detail-grid { grid-template-columns: 1fr !important; }

  .filter-aside { position: static !important; top: auto !important; }
}

/* ---- license plate tag ---- */
.plate {
  font-family: var(--font-display); font-weight: 900; letter-spacing: .08em;
  font-size: 15px; color: var(--ja-ink); white-space: nowrap; flex: none;
  background: #FFFDF7; border: 2px solid var(--ja-ink); border-radius: 7px;
  padding: 3px 9px; line-height: 1.15;
  box-shadow: inset 0 0 0 1.5px #fff;
}
.plate.lg { font-size: 30px; letter-spacing: .1em; padding: 7px 16px; border-radius: 11px; border-width: 3px; }
.plate-field {
  font-family: var(--font-display); font-weight: 900; letter-spacing: .14em;
  text-transform: uppercase; text-align: center; font-size: 22px;
}

/* ---- header: the tight band ----
   The lookup used to be `display:none` below 900px, which is why the header looked like it
   carried no plate entry at all. It stays now, but a plate that clips its own number is worse
   than no plate — so it holds a min-width and the room comes from the labels beside it. The
   band starts where the row stops fitting (~1010px), NOT at 900: between the two the plate was
   being flex-shrunk while the 900px rules had not yet run. */
@media (max-width: 1010px) {
  .navsearch { max-width: 380px; }
  .navsearch .seg { padding: 7px 10px; }
  .navsearch input { font-size: 15px; letter-spacing: .06em; }
  .nav-inner nav { gap: 13px !important; }
  .nav-watch { padding: 8px 12px; }
  /* Sign in becomes its shield icon — the same font-size:0 trick the hero go button uses.
     Button renders its label as a bare text node, so there is no span to hide. */
  .nav .btn-ghost { font-size: 0; gap: 0; padding: 9px 11px; }
  .nav .btn-ghost .ico { font-size: 17px; }
  .nav .nav-post .btn { padding-left: 13px; padding-right: 13px; }
  .logo-word { font-size: 21px; }
  .logo img { height: 33px; }
}

/* ---- state pulldown inside search bars ---- */
.hero-search select, .navsearch select {
  border: none; outline: none; background: transparent; cursor: pointer;
  font-family: var(--font-display); font-weight: 800; color: var(--ja-ink);
  letter-spacing: .04em; padding-right: 2px; -webkit-appearance: none; appearance: none;
}
.hero-search select { font-size: 16px; }
.navsearch select { font-size: 16px; width: 3.6ch; }
.hero-search .state-seg, .navsearch .state-seg { flex: none; }

/* ===== Mobile / responsive hardening ===== */
/* P0: keep grid/flex children from setting a min-content floor wider than the viewport */
.results-grid > *, .map-layout > *, .detail-grid > * { min-width: 0; }
.map-row > .col, .map-row .col { min-width: 0; flex: 1; }

@media (min-width: 700px) { .loc-label { white-space: nowrap; } }

@media (max-width: 700px) {
  .cat-grid { grid-template-columns: repeat(2, 1fr) !important; }
  .how-grid { grid-template-columns: 1fr !important; }
  .about-grid { grid-template-columns: 1fr !important; gap: 28px !important; }
  .results-head { flex-wrap: wrap; }
  .sort-ctl { width: 100%; justify-content: flex-start; }
  .card-meta { flex-wrap: wrap; }
  .card-meta .card-addr { flex: 1 1 100%; }
}

@media (max-width: 600px) {
  .nav .navlink, .nav .badge-verified { display: none !important; }
  /* The states/plates directory is the only route to per-state reporting info, and in the app
     the header is the only place it can live — keep it when the other navlinks go. */
  .nav .navlink.nav-states { display: inline-flex !important; font-size: 12.5px; white-space: nowrap; }
  .nav .nav-states-rest { display: none; }
  .nav-inner { gap: 12px; }
  .logo img { height: 30px; }
  .logo-word { font-size: 20px; }
  .reason-grid { grid-template-columns: repeat(2, 1fr); }
  .track-freq-grid { grid-template-columns: repeat(2, 1fr) !important; }
  /* P2 touch targets */
  .filter-check { min-height: 44px; }
  .pop-chip { padding: 10px 15px !important; }
  .footer a { padding: 9px 0; }
}

@media (max-width: 480px) {
  .wrap { padding: 0 16px; }
  .nav-inner { gap: 8px; }
  .nav .btn-md { padding: 9px 13px; font-size: 13px; }
  .listing { gap: 12px; }
  .listing .thumb { width: 92px !important; height: 92px !important; }
}

/* ---- mobile bottom tab bar (phones only) ---- */
.mobilebar { display: none; }
.mb-item { background: none; border: none; cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 6px 2px; min-height: 52px; color: var(--fg3); font-family: var(--font-display); font-weight: 700; font-size: 10.5px; letter-spacing: .02em; }
.mb-item .ico { color: inherit; }
.mb-badge-wrap { position: relative; display: flex; }
.mb-badge { position: absolute; top: -5px; right: -9px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: var(--r-pill); background: var(--ja-alert); color: #fff; font-family: var(--font-display); font-weight: 800; font-size: 10px; line-height: 16px; text-align: center; box-shadow: 0 0 0 2px #fff; }
.mb-item.on { color: var(--ja-alert); }
.mb-item:active { transform: scale(.94); }
.mb-fab { justify-self: center; align-self: center; transform: translateY(-14px); width: 58px; height: 58px; border-radius: var(--r-pill); background: var(--ja-alert); color: #fff; border: 3px solid #fff; box-shadow: var(--sh-alert); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: transform var(--dur-fast) var(--ease-pop); }
.mb-fab:active { transform: translateY(-14px) scale(.93); }
@media (max-width: 700px) {
  .mobilebar { display: grid; grid-template-columns: repeat(5, 1fr); align-items: center; position: fixed; left: 0; right: 0; bottom: 0; z-index: 90; background: #fff; border-top: 1px solid var(--line); padding: 5px 6px calc(5px + env(safe-area-inset-bottom)); box-shadow: 0 -4px 18px rgba(30,45,51,.07); }
  body { padding-bottom: calc(74px + env(safe-area-inset-bottom)); }
  .toast { bottom: calc(88px + env(safe-area-inset-bottom)); }
}

/* ---- phone spacing pass ---- */
@media (max-width: 600px) {
  /* Hero search at 412px: the "Search" label was eating the plate field, clipping it to
     "PLAT". Collapse the button to its icon and tighten the segments so the plate — up to
     8 characters — always fits. */
  .hero-search .seg { padding: 13px 14px; gap: 8px; }
  .hero-search .state-seg { padding-right: 8px; }
  .hero-search input { font-size: 16px; }   /* keep 16px: anything smaller zooms on focus */
  /* .navsearch is hidden on phones, so this is the only plate entry on the home screen —
     drop the in-field magnifier (the button already carries one) and give it the room. */
  .hero-search .seg:not(.state-seg) > .ico { display: none; }
  .hero-search .go { height: 46px; padding: 0 15px; margin: 5px; gap: 0; font-size: 0; }
  .hero-search .go .ico { font-size: 0; }

  /* Section headers: "Browse by category" was wrapping while "See all" broke onto two
     lines beside it. Let the heading take the row and keep the link on one line. */
  .section .flex.between.center { gap: 12px; }
  .section .flex.between.center .navlink { white-space: nowrap; flex: none; }

  /* Vertical rhythm: 56px band padding leaves dead space on a phone. */
  .section { padding: 36px 0; }
  .hero-grid { padding: 36px 20px 44px !important; }
  .footer { padding: 36px 0 24px; }
}

/* ---- phone: collapsible results filters ---- */
.filter-toggle { display: none; }
@media (max-width: 900px) {
  /* Above 900px the aside sits in its own column. Below, it became a full-width block
     pushed above the results, so it hides behind a toggle instead. */
  .filter-toggle {
    display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px;
    margin-bottom: 14px; padding: 10px 16px; background: #fff;
    border: 1.5px solid var(--line-strong); border-radius: var(--r-pill);
    font-family: var(--font-display); font-weight: 800; font-size: 14px;
    color: var(--ja-ink); cursor: pointer;
  }
  .filter-toggle .ico:last-child { margin-left: auto; }
  .filter-aside { display: none !important; }
  .filter-aside.open { display: block !important; }
}

/* Cards whose generous desktop padding is too much on a phone. */
@media (max-width: 600px) { .pad-card { padding: 32px 20px !important; } }

/* ---- phone: plate detail gallery ---- */
@media (max-width: 600px) {
  /* .gallery had no phone rule: at 412px the plate render was squeezed into a ~250px
     column inside a fixed 320px-tall row. Stack it and let the height follow content. */
  .gallery { grid-template-columns: 1fr !important; height: auto !important; }
  .gallery > div { min-height: 150px; }
}

@media (max-width: 480px) {
  /* Several wraps carry an inline padding shorthand (e.g. "28px 24px"), which beats the
     .wrap rule above and keeps 24px gutters on a 412px screen. !important reclaims the
     horizontal gutters while leaving each block's own vertical padding alone. */
  .wrap { padding-left: 16px !important; padding-right: 16px !important; }
  /* 8-character plates at 30px + .1em tracking overflow their nowrap tag. */
  .plate.lg { font-size: 24px; padding: 6px 12px; }
}

/* ---- bottom-sheet modals on phones ---- */
@media (max-width: 600px) {
  /* --ja-kb is the on-screen keyboard height, published by the visualViewport listener in
     index.html. Without it the sheet's foot — the input and the primary button — sits behind
     the keyboard, because position:fixed measures the layout viewport and that does not
     shrink when the keyboard opens. */
  .scrim { align-items: flex-end; padding: 0; padding-bottom: var(--ja-kb, 0px); }
  .modal { max-width: 100%; width: 100%; max-height: calc(100dvh - var(--ja-kb, 0px)); border-radius: var(--r-xl) var(--r-xl) 0 0; animation: sheetUp .28s var(--ease-out); }
  /* Keep the sticky footer reachable while the body scrolls under it. */
  .modal:not(.modal-flex) > .flex.between.center:last-child { position: sticky; bottom: 0; background: var(--bg-warm); }
}
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* ---- reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .hero-mascot img { animation: none !important; }
  .toast, .modal { animation: none !important; }
  .listing:hover, .cat-tile:hover, .pill:hover { transform: none !important; }
}

/* ---- phone fit hardening (app WebView) ----
   The Android WebView can report a layout width above 600px (system display-size setting),
   which left the Post an Alert sheet on its desktop 3-column grid and overflowing sideways.
   These rules widen the phone treatment and stop flex/grid children from forcing a min width. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
/* clip, NOT hidden: overflow-x:hidden on html/body turns the document into a scroll container
   in Android WebView, which kills touch-scrolling everywhere except the fixed bottom bar. */
body { overflow-x: clip; }
.modal, .modal * { min-width: 0; }
@media (max-width: 820px) {
  .reason-grid { grid-template-columns: repeat(2, 1fr); }
  .reason-btn { padding-left: 4px; padding-right: 4px; }
  .reason-btn .rlabel { overflow-wrap: anywhere; }
}
@media (max-width: 700px) {
  .scrim { align-items: flex-end; padding: 0; padding-bottom: var(--ja-kb, 0px); }
  .modal { width: 100%; max-width: 100%; max-height: calc(100dvh - var(--ja-kb, 0px)); border-radius: var(--r-xl) var(--r-xl) 0 0; }
  .modal:not(.modal-flex) > .flex.between.center:last-child { position: sticky; bottom: 0; background: var(--bg-warm); }
  .modal > .col, .modal-body > .col { padding-left: 16px !important; padding-right: 16px !important; }
  .modal > .flex.between.center { padding-left: 16px !important; padding-right: 16px !important; }
}
/* State picker: keep the caret and 44px touch height on a phone. */
select.state-select { min-height: 44px; }

/* Search-result card meta: the address is the only long string here, so it always gets its own   line. It used to be a flex item inside a flex row, which shrank it to min-content and stacked
   long addresses one word per line. Inline flow wraps at the container width instead. */
.card-meta { flex-wrap: wrap; row-gap: 2px; }
.card-meta .card-addr { flex: 1 1 100%; min-width: 0; display: block; line-height: 1.35; text-wrap: pretty; }
.card-meta .card-addr svg { vertical-align: -2px; margin-right: 3px; }

/* Phone top bar. Both "Post an Alert" and "Sign in" in a 390px header clipped Sign in off the
   right edge. Post an Alert goes — the tab bar's FAB is the identical action — and Sign in (or
   the account avatar) stays, because that one has no other obvious home for a signed-out user.
   Hiding both left the header looking broken rather than clean. */
/* Below 900px the row cannot hold the lookup AND both actions. The lookup wins — it is the
   point of the header — and Post an Alert and The Watch are both already on the mobile tab bar,
   which is why .nav-post was hidden at 700px in the first place. This just starts it earlier
   and takes The Watch with it, instead of letting the plate clip its own number. */
@media (max-width: 900px) {
  .nav .nav-post, .nav .nav-watch { display: none !important; }
}

@media (max-width: 700px) {
  /* Below 700px the plate cannot hold its min-width beside the logo, and the hero search is
     the plate entry at that size anyway (see the .hero-search phone rules). Hidden here, as
     it was before 4 Aug — the change was only ever meant to recover the 700–1010px band. */
  .navsearch { display: none !important; }
  .nav .nav-post { display: none !important; }
  .nav-inner { gap: 12px; }
  .nav .btn-md { padding: 9px 13px; font-size: 13px; }
}

/* ---- P2: minimum touch targets (15 Aug 2026; floor raised 44→48 via --tap-min, 31 Aug 2026) ----
   The union of the two conditions is deliberate. pointer:coarse alone misses the desktop
   device simulator (an iframe on a mouse machine); max-width alone misses the Android
   WebView, which can report a layout width above 600px when the system display-size
   setting is turned up. Together they cover both. Desktop between 900 and 1010px — the
   band where the header only just fits — is left exactly as it was tuned.
   min-height raises the box where there is room for it. Where a control has to stay
   visually small, a transparent ::after inflates the HIT area and nothing else.
   This block sits at the end of the file on purpose: several of these classes are sized
   by an earlier phone rule of equal specificity, so it has to win on source order. */
@media (pointer: coarse), (max-width: 700px) {
  /* Padding-sized controls: no floor at all before this. .btn-md is Sign in / Post an
     Alert (~38px), .btn-sm ~31px, .pill ~37px, .pop-chip ~40px. Floor is the --tap-min
     token (48px, colors_and_type.css) so the number lives in one place. */
  .btn-sm, .btn-md, .pill, .pop-chip, .filter-check, .nav-watch { min-height: var(--tap-min, 48px); }
  .pop-chip, .nav-watch { display: inline-flex; align-items: center; }
  /* Icon-only buttons need the width too, or they stay ~38px across. Sign in collapses to
     its shield icon below 1010px, and the lookup's go button is a 38px square. */
  .nav .btn-ghost { min-width: var(--tap-min, 48px); }
  .navsearch .go { width: var(--tap-min, 48px); height: var(--tap-min, 48px); }
  /* The modal close X is a 22px icon in a bare span, in the corner where a miss dismisses
     nothing. The head is ~62px tall so 48 fits inside it; the negative margin keeps the
     glyph over the pixel it sat on before, so nothing looks different. */
  .modal-head > .modal-close { min-width: var(--tap-min, 48px); min-height: var(--tap-min, 48px); display: inline-flex; align-items: center; justify-content: center; margin-right: -13px; }
  /* 14px text with 9px padding measured 38px. */
  .footer a { padding: 12px 0; }
  /* Text-styled buttons, ~18px tall. Growing the box would move the layout around them,
     so only the hit area grows. */
  .navlink, .map-card-link { position: relative; }
  .navlink::after, .map-card-link::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); height: var(--tap-min, 48px); }
  /* Map pins: the dot stays 36px — bigger and pins collide at city zoom — and the button
     around it carries the touch area. It is translate(-50%,-50%) positioned, so growing
     the box keeps the dot over its own coordinate. */
  .map-pin { min-width: var(--tap-min, 48px); min-height: var(--tap-min, 48px); display: flex; align-items: center; justify-content: center; }
}

/* ---- result-card header (31 Aug 2026) ---- */
/* When the plate tag and the status badge could not share one line, the badge painted over the
   plate (the plate is nowrap and overflowed its shrunken box). The header row now wraps in
   SiteCards.jsx; this rule keeps the badge itself in one piece when it drops to its own line. */
.badge { white-space: nowrap; flex: none; }

/* Buttons never squish (31 Aug 2026): a tight flex row used to shrink a button until its label
   clipped (Post Alert in the modal footer on a phone). Rows that can get tight wrap instead —
   the five .modal-foot rows and the incident-map plate row now carry wrapw. Full-width buttons
   (width:100%) sit in column layouts, where flex-shrink does not apply to width. */
.btn { white-space: nowrap; flex-shrink: 0; }
