/* ==========================================================================
   Ask Camarillo — styles

   Themed to the City of Camarillo's own municipal identity, sampled from
   cityofcamarillo.org's stylesheet (the city publishes no formal brand guide,
   so these are the values its live site actually uses):
     Indigo     #1c1b60   primary text and headings — the dominant site color
     Deep Blue  #082173   interactive: links, buttons, focus
     Gold       #bda663   the single accent
     Pale Blue  #f5f8fd / #dbe7f0   page surface and rules
   Note this palette has no orange in it at all, which is why the old orchard
   amber is gone rather than merely reduced. Error states use a crimson drawn
   from the same site (#eb1f49) rather than an orange.

   Typography also matches the city site: Playfair Display (headings) +
   Montserrat (body/UI), both from Google Fonts in one request.

   NOT the Visit Camarillo palette — that is the destination-marketing brand
   (visitcamarillo.com), a different organization from the municipality.

   Committed to a light, projector-legible surface throughout (no dark mode).
   ========================================================================== */

:root {
  --paper: #f5f8fd;
  --card: #ffffff;
  --ink: #1c1b60;
  --ink-muted: #565a80;
  --ink-faint: #8a8ea8;
  --line: #dbe7f0;
  --line-strong: #b9cbdf;

  /* Names kept as --teal/--amber so the ~200 downstream references don't all
     have to churn; the values are now the city's deep blue and gold. */
  --teal: #082173;
  --teal-deep: #1c1b60;
  --teal-wash: #e8effa;
  --amber: #bda663;
  --amber-wash: #f6f1e2;
  --danger: #b02a45;
  --danger-wash: #fae6ea;

  /* Zone scale is otherwise untouched — it already separates well and is what
     the map legend depends on. Only residential moved, off the old orange. */
  --zone-residential: #bda663;
  --zone-commercial: #1f6f72;
  --zone-industrial: #6b4e71;
  --zone-agricultural: #7a8b4f;
  --zone-open_space: #3f7d53;
  --zone-public: #2e4c6d;
  --zone-mixed: #8c6e52;
  --zone-other: #8c6e52;
  --zone-unknown: #9aa0a6;

  --font-display: "Playfair Display", Georgia, "Times New Roman", serif;
  --font-body: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --radius: 8px;
  --radius-sm: 5px;
  --shadow-card: 0 1px 2px rgba(30, 42, 46, 0.06), 0 4px 12px rgba(30, 42, 46, 0.06);
  --header-h: 60px;
  --footer-h: 34px;
}

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

/* The UA stylesheet's `[hidden] { display: none }` is specificity 0,0,1, so any
   class rule that sets `display` silently beats it and the element stays
   visible after `el.hidden = true`. That bit the Ask button's spinner (it kept
   animating after an answer rendered) and would have bitten anything else
   toggled the same way. This reset makes the attribute authoritative. */
[hidden] {
  display: none !important;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  margin: 0;
  color: var(--teal-deep);
  font-weight: 600;
}

button {
  font-family: inherit;
}

a {
  color: var(--teal);
}

.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;
}

:focus-visible {
  outline: 3px solid var(--amber);
  outline-offset: 2px;
}

/* ---------------------------------- header ---------------------------- */

.app-header {
  flex: none;
  height: var(--header-h);
  display: flex;
  align-items: center;
  padding: 0 20px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.brand-mark {
  width: 32px;
  height: 32px;
  color: var(--teal);
  flex: none;
}

.brand-text {
  min-width: 0;
}

.brand-text h1 {
  font-size: 1.28rem;
  line-height: 1.1;
  white-space: nowrap;
}

.tagline {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.parcel-count {
  color: var(--ink-faint);
}

.parcel-count::before {
  content: "· ";
}

/* ---------------------------------- layout ------------------------------ */

.layout {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(300px, 380px) 1fr;
  grid-template-rows: 1fr 1fr;
  grid-template-areas:
    "chat map"
    "chat results";
  gap: 1px;
  background: var(--line);
}

.chat-panel,
.map-panel,
.results-panel {
  background: var(--paper);
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Hard boundary: below 1024px these panels stack (map, chat, results), so
     anything that overflows the chat panel lands on top of the results panel
     beneath it. Nothing inside should overflow now — .chat-log scrolls and
     .ask-form is fixed height — but this makes spilling into a neighbouring
     panel structurally impossible rather than merely unlikely. */
  overflow: hidden;
}

.chat-panel {
  grid-area: chat;
}

.map-panel {
  grid-area: map;
  position: relative;
  background: var(--card);
}

.results-panel {
  grid-area: results;
  border-top: 1px solid var(--line);
}

/* ---------------------------------- chat panel -------------------------- */

.chat-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 18px 8px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.chat-welcome p {
  margin: 0 0 6px;
  color: var(--ink-muted);
  font-size: 0.9rem;
}

.chat-welcome-muted {
  color: var(--ink-faint) !important;
  font-size: 0.82rem !important;
}

.turn {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Same reasoning as .suggestions — turns keep their intrinsic height and the
     transcript scrolls, rather than every turn compressing as the log fills. */
  flex: none;
}

.turn-question {
  align-self: flex-end;
  max-width: 92%;
  background: var(--teal-deep);
  color: #fdfaf3;
  padding: 8px 12px;
  border-radius: var(--radius) var(--radius) 2px var(--radius);
  font-size: 0.88rem;
}

.turn-answer {
  border-left: 3px solid var(--amber);
  padding: 6px 0 6px 12px;
}

.turn-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--ink-faint);
  margin: 0 0 3px;
}

.turn-answer-text {
  margin: 0;
  font-size: 0.92rem;
  color: var(--ink);
}

.turn-answer.is-clarification {
  border-left-color: var(--teal);
}

.turn-answer.is-error {
  border-left-color: var(--danger);
}

.turn-answer.is-loading .turn-answer-text {
  color: var(--ink-muted);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.turn-badge {
  display: inline-block;
  margin-top: 6px;
  font-size: 0.72rem;
  color: var(--ink-muted);
  background: var(--teal-wash);
  border-radius: 999px;
  padding: 2px 9px;
}

.query-toggle {
  margin-top: 8px;
  font-size: 0.8rem;
}

.query-toggle > summary {
  cursor: pointer;
  color: var(--teal);
  font-weight: 600;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  user-select: none;
}

.query-toggle > summary::-webkit-details-marker {
  display: none;
}

.query-toggle > summary::before {
  content: "▸";
  font-size: 0.7em;
  transition: transform 0.15s ease;
}

.query-toggle[open] > summary::before {
  transform: rotate(90deg);
}

.query-sql {
  margin: 6px 0 0;
  background: var(--ink);
  color: #eef3f2;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 160px;
  overflow-y: auto;
}

.query-debug {
  margin: 6px 0 0;
  font-size: 0.74rem;
  color: var(--ink-faint);
}

/* suggestion chips */

/* Suggestions sit inside the transcript as its last child rather than in a
   fixed strip above the input, which gives the chat the panel's full height.
   No border-top: it reads as part of the conversation, not a separate tray. */
.suggestions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  /* flex: none matters. As a flex item in the column-flex .chat-log it would
     otherwise shrink before the log started scrolling, squashing the chips
     into a clipped row. Non-shrinking means the log scrolls instead, which is
     what keeps a wrapped set of chips fully readable. */
  flex: none;
}

.suggestions:empty {
  display: none;
}

/* After the first answer this holds a single model-generated follow-up, so it
   is labelled and indented to read as a continuation of the last answer
   rather than as a fresh menu of options. */
.suggestions.is-followup {
  padding-left: 12px;
  border-left: 3px solid transparent;
}

.suggestions-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}

/* Recall control on any turn that is not currently at the bottom. Small, but
   the gold keeps it findable when several are stacked up the transcript. */
.turn-recall {
  align-self: flex-start;
  margin-top: 2px;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--teal);
  border-radius: 999px;
  padding: 4px 12px;
  font-family: inherit;
  font-size: 0.7rem;
  line-height: 1.4;
  min-height: 28px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.turn-recall::before {
  content: "↑ ";
  color: var(--amber);
}

.turn-recall:hover:not(:disabled) {
  background: var(--teal-wash);
  border-color: var(--teal);
}

.turn-recall:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Brief flash so a recalled turn is visibly the one that just moved — without
   it the transcript reorders with no explanation of what changed. */
.turn.is-recalled .turn-question,
.turn.is-recalled .turn-answer {
  animation: recall-flash 1.2s ease-out;
}

@keyframes recall-flash {
  0% { background: var(--amber-wash); }
  100% { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .turn.is-recalled .turn-question,
  .turn.is-recalled .turn-answer {
    animation: none;
  }
}

.chip {
  flex: none;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--teal-deep);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 0.8rem;
  cursor: pointer;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  transition: background 0.12s ease, border-color 0.12s ease;
}

.chip:hover {
  border-color: var(--teal);
  background: var(--teal-wash);
}

.chip:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ask form */

.ask-form {
  flex: none;
  padding: 12px 18px 16px;
  border-top: 1px solid var(--line);
  background: var(--card);
}

.input-row {
  display: flex;
  gap: 8px;
}

#question-input {
  flex: 1;
  min-width: 0;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  font-size: 0.95rem;
  font-family: inherit;
  color: var(--ink);
  background: var(--paper);
}

#question-input:focus {
  border-color: var(--teal);
  background: var(--card);
}

.btn-primary {
  flex: none;
  height: 44px;
  min-width: 78px;
  padding: 0 18px;
  border: none;
  border-radius: var(--radius);
  background: var(--teal);
  color: #fff;
  font-size: 0.92rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background 0.12s ease;
}

.btn-primary:hover {
  background: var(--teal-deep);
}

.btn-primary:disabled {
  background: var(--ink-faint);
  cursor: not-allowed;
}

/* --- Sign-in ------------------------------------------------------------- */

/* Groups the attribution and the sign-out control so the pair stays pinned
   right whether or not either one is showing (account-bar is hidden until
   sign-in; presented-by drops its text on narrow screens). */
.header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

.presented-by {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  color: var(--ink-faint);
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.presented-by strong {
  font-weight: 600;
  color: var(--ink-muted);
}

.presented-by-mark {
  height: 18px;
  width: auto;
  display: block;
  flex: none;
  opacity: 0.85;
}

.account-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.btn-quiet {
  height: 34px;
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-muted);
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}

.btn-quiet:hover {
  background: var(--teal-wash);
  color: var(--teal-deep);
}

.auth-gate {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(30, 42, 46, 0.55);
}

.auth-gate[hidden] {
  display: none;
}

.auth-gate-card {
  width: min(420px, 100%);
  padding: 28px;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-card);
  text-align: center;
}

.auth-gate-card h2 {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--ink);
}

.auth-gate-card p {
  margin: 0 0 20px;
  color: var(--ink-muted);
  font-size: 0.95rem;
  line-height: 1.5;
}

.input-meta {
  margin-top: 6px;
  text-align: right;
  font-size: 0.72rem;
  color: var(--ink-faint);
}

/* spinners */

.spinner,
.btn-spinner {
  display: inline-block;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  animation: spin 0.7s linear infinite;
}

.turn-answer.is-loading .spinner {
  border: 2px solid var(--teal-wash);
  border-top-color: var(--teal);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spinner,
  .btn-spinner {
    animation-duration: 1.6s;
  }
}

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

.map-panel #map {
  position: absolute;
  inset: 0;
}

.map-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--paper);
  color: var(--ink-muted);
  font-size: 0.88rem;
  z-index: 5;
  transition: opacity 0.2s ease;
}

.map-overlay .spinner {
  border-color: var(--line-strong);
  border-top-color: var(--teal);
}

.map-overlay.is-hidden {
  opacity: 0;
  pointer-events: none;
}

.map-legend {
  position: absolute;
  bottom: 10px;
  left: 10px;
  z-index: 4;
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 0.72rem;
  max-width: 190px;
  box-shadow: var(--shadow-card);
}

.map-legend-title {
  font-weight: 700;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.64rem;
  margin-bottom: 5px;
}

.map-legend-items {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--ink);
}

.zone-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex: none;
  display: inline-block;
}

/* maplibre popup overrides */

.maplibregl-popup {
  max-width: min(300px, 84vw) !important;
}

.maplibregl-popup-content {
  padding: 12px 30px 12px 14px;
  border-radius: var(--radius);
  font-family: var(--font-body);
  box-shadow: var(--shadow-card);
}

.maplibregl-popup-close-button {
  width: 30px;
  height: 30px;
  font-size: 18px;
  line-height: 1;
  color: var(--ink-muted);
}

.parcel-popup .popup-apn {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  margin-bottom: 2px;
}

.parcel-popup .popup-address {
  font-weight: 700;
  color: var(--teal-deep);
  margin-bottom: 4px;
  font-size: 0.92rem;
  word-break: break-word;
}

.parcel-popup .popup-zone {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  margin-bottom: 8px;
  color: var(--ink);
}

.parcel-popup .popup-stats {
  margin: 0;
  display: grid;
  grid-template-columns: auto auto;
  gap: 2px 10px;
  font-size: 0.8rem;
}

.parcel-popup .popup-stats dt {
  color: var(--ink-faint);
}

.parcel-popup .popup-stats dd {
  margin: 0;
  font-weight: 600;
  text-align: right;
}

/* ---------------------------------- results ------------------------------ */

.results-header {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 12px 18px 8px;
}

.results-header h2 {
  font-size: 1rem;
}

.results-count {
  font-size: 0.78rem;
  color: var(--ink-muted);
}

.results-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0 18px 16px;
}

.results-empty {
  color: var(--ink-faint);
  font-size: 0.85rem;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
}

#results-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
}

#results-table thead {
  position: sticky;
  top: 0;
  background: var(--teal-wash);
  z-index: 1;
}

#results-table th {
  text-align: left;
  padding: 8px 10px;
  font-weight: 700;
  color: var(--teal-deep);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  border-bottom: 1px solid var(--line);
}

#results-table th:hover {
  background: var(--amber-wash);
}

#results-table th.sorted-asc::after {
  content: " ▲";
  font-size: 0.65em;
}

#results-table th.sorted-desc::after {
  content: " ▼";
  font-size: 0.65em;
}

#results-table td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

#results-table tbody tr {
  cursor: pointer;
}

#results-table tbody tr:hover {
  background: var(--teal-wash);
}

#results-table tbody tr.is-selected {
  background: var(--amber-wash);
}

/* mobile results cards */

.card-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.result-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  cursor: pointer;
  min-height: 44px;
}

.result-card:hover,
.result-card:active {
  border-color: var(--teal);
}

.result-card .card-address {
  font-weight: 700;
  color: var(--teal-deep);
  font-size: 0.9rem;
  margin-bottom: 4px;
}

.result-card .card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 0.8rem;
  color: var(--ink-muted);
}

.result-card .card-meta strong {
  color: var(--ink);
}

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

.site-footer {
  flex: none;
  min-height: var(--footer-h);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 14px;
  font-size: 0.7rem;
  color: var(--ink-faint);
  background: var(--card);
  border-top: 1px solid var(--line);
  text-align: center;
}

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

@media (max-width: 1023px) {
  .layout {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
  }

  .map-panel {
    order: 1;
    flex: none;
    height: 50vh;
  }

  .chat-panel {
    order: 2;
    flex: none;
  }

  /* Was 32vh when the chips had their own strip below this box. They now live
     inside it, so it takes that height back — enough that the five starters
     are visible on load without scrolling. */
  .chat-log {
    max-height: 40vh;
  }

  .results-panel {
    order: 3;
    flex: none;
  }

  .results-body {
    overflow-y: visible;
  }
}

@media (max-width: 767px) {
  .app-header {
    padding: 0 14px;
    height: 52px;
  }

  .brand-mark {
    width: 26px;
    height: 26px;
  }

  .brand-text h1 {
    font-size: 1.05rem;
  }

  .tagline {
    font-size: 0.7rem;
  }

  /* At 390px the header is brand + attribution + sign-out, which is too much.
     Keep the mark (it costs 18px) and drop the words. */
  .header-right {
    gap: 10px;
  }

  .presented-by span {
    display: none;
  }

  .map-panel {
    height: 40vh;
  }

  /* Reclaims the height the separate suggestion strip used to occupy — the
     chips now scroll with the transcript instead of sitting below it. */
  .chat-log {
    max-height: 30vh;
    padding: 12px 14px 6px;
  }

  /* Deliberately not the old nowrap/scroll-snap carousel: a horizontal
     scroller nested inside a vertical one is awkward on touch, and five
     wrapped chips fit fine at 390px. */
  .suggestions {
    gap: 6px;
  }

  .chip {
    font-size: 0.75rem;
    padding: 6px 12px;
  }

  .ask-form {
    padding: 10px 14px 14px;
  }

  .results-header {
    padding: 10px 14px 6px;
  }

  .results-body {
    padding: 0 14px 14px;
  }

  .table-wrap {
    display: none;
  }

  .card-list {
    display: flex;
  }

  .site-footer {
    font-size: 0.64rem;
    padding: 8px 10px;
  }
}

@media (min-width: 768px) {
  .card-list {
    display: none;
  }
}
