/* Phase 8 mobile inventory styles -- hand-written, no build step, no CDN.
   app.css (vendored above this file) is a purged Tailwind build that only
   contains the utility classes the Phase 5/7 ticket templates already use;
   rather than hand-maintain a second purge list, the inventory templates
   use this small, purpose-built component stylesheet instead. Mobile-first
   throughout: base rules target a phone width, the min-width query widens
   layout for tablet/desktop. */

/* ------------------------------------------------------------------ */
/* Phase 10 -- iPhone safe areas, demo banner, and top-bar/nav chrome.  */
/*                                                                      */
/* Safe areas: base.html sets viewport-fit=cover, which is what makes   */
/* env(safe-area-inset-*) resolve to nonzero values under the notch /   */
/* Dynamic Island and above the home indicator. Every horizontal gutter */
/* below therefore adds max(<gutter>, env(safe-area-inset-left/right))  */
/* so landscape orientation never tucks content under the rounded       */
/* corners, and every bottom-most element adds the bottom inset so the  */
/* home-indicator bar never sits on top of a button. Values degrade to  */
/* the plain gutter on any browser without env() support.               */
/* ------------------------------------------------------------------ */

:root {
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* Prevents a single long token (an unbroken asset tag, serial, URL, or
   pasted ticket line) from forcing a horizontal page scroll on a 390px
   iPhone viewport -- the whole app is meant to scroll vertically only. */
body { overflow-x: hidden; }

.demo-banner {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25rem .5rem;
  background: #b45309;
  color: #fff;
  font-size: .8rem;
  line-height: 1.3;
  padding: calc(.5rem + var(--safe-top)) max(.75rem, var(--safe-right)) .5rem max(.75rem, var(--safe-left));
  border-bottom: 2px solid #78350f;
}
.demo-banner-dot {
  width: .6rem; height: .6rem; border-radius: 999px; background: #fde68a; flex: 0 0 auto;
}
.demo-banner-text { font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.demo-banner-sub { color: #fef3c7; font-weight: 500; }

.app-topbar {
  background: #0f172a;
  color: #fff;
  font-size: .75rem;
  line-height: 1.35;
  text-align: center;
  padding: .45rem max(.5rem, var(--safe-right)) .45rem max(.5rem, var(--safe-left));
}
/* Without a demo banner above it the top bar is itself the topmost
   element, so it -- not the banner -- owns the notch inset. */
body > .app-topbar:first-child { padding-top: calc(.45rem + var(--safe-top)); }

.inv-topnav {
  display: flex;
  align-items: center;
  gap: .4rem;
  background: #fff;
  border-bottom: 1px solid #e2e8f0;
  padding: .4rem max(.75rem, var(--safe-right)) .4rem max(.75rem, var(--safe-left));
}
.inv-topnav-link {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  /* >=44px tall: Apple's minimum comfortable touch target. The previous
     .4rem/.875rem combination rendered ~29px tall, which is genuinely
     hard to hit one-handed while walking a building. */
  min-height: 44px;
  padding: .4rem .7rem;
  border-radius: .5rem;
  font-size: .875rem;
  font-weight: 600;
  color: #334155;
  text-decoration: none;
}
.inv-topnav-link:hover { background: #f1f5f9; }
.inv-topnav-link-demo { background: #fef3c7; color: #92400e; }
.inv-topnav-spacer { flex: 1 1 auto; }

/* Account/logout menu: a native <details> disclosure, no JS. Collapsing
   the name + role + Log out button into one control is what keeps the
   nav row on a single line at 375px instead of wrapping into a second
   row that pushed page content down. */
.inv-account { position: relative; }
/* Measured at 390px: Tickets + Inventory + Demo Guide + a full display
   name and role pushed the nav row to 459px against a 390px viewport, so
   the account control was clipped off the right edge and the whole
   document scrolled sideways on every page. Both halves of the fix
   matter -- the account control becomes a fixed-width initials button
   below 560px (a name + a role word like "technician" is unbounded), and
   the nav's own padding/gaps tighten below 480px. */
.inv-account { position: relative; flex: 0 0 auto; }
.inv-account-summary {
  display: inline-flex; align-items: center; gap: .35rem; cursor: pointer; list-style: none;
  border: 1px solid #e2e8f0;
}
.inv-account-summary::-webkit-details-marker { display: none; }
.inv-account-initials {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem; flex: 0 0 auto; border-radius: 999px;
  background: #1e293b; color: #fff; font-size: .72rem; font-weight: 800; letter-spacing: .02em;
}
.inv-account-name,
.inv-account-role { display: none; }
.inv-account-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 560px) {
  .inv-account-initials { display: none; }
  .inv-account-name { display: inline; }
  .inv-account-role { display: inline-block; }
}

@media (max-width: 479px) {
  .inv-topnav { gap: .2rem; padding-left: max(.4rem, var(--safe-left)); padding-right: max(.4rem, var(--safe-right)); }
  .inv-topnav-link { padding: .4rem .5rem; font-size: .82rem; }
}
.inv-account-role {
  flex: 0 0 auto; background: #f1f5f9; color: #475569; border-radius: 999px;
  padding: .05rem .4rem; font-size: .68rem; text-transform: uppercase; letter-spacing: .03em;
  white-space: nowrap;
}
.inv-account-menu {
  position: absolute; right: 0; top: calc(100% + .3rem); z-index: 40; min-width: 13rem;
  background: #fff; border: 1px solid #e2e8f0; border-radius: .7rem; padding: .7rem;
  box-shadow: 0 8px 24px rgba(15, 23, 42, .12);
}
.inv-account-menu-name { font-size: .78rem; color: #64748b; margin-bottom: .5rem; }

.inv-page {
  max-width: 640px;
  margin: 0 auto;
  /* The bottom gutter clears the iPhone home indicator in standalone
     mode; the side gutters clear the rounded corners in landscape. */
  padding: .75rem max(.75rem, var(--safe-right)) calc(3rem + var(--safe-bottom)) max(.75rem, var(--safe-left));
}
.inv-page-wide { max-width: 900px; }

/* Safe-area-aware page gutter for the Phase 5/7 ticket templates, which
   are built from the vendored Tailwind subset (app.css) and so have no
   env()-aware utility of their own. Applied alongside their existing
   `px-3 sm:px-4` classes, which it intentionally overrides -- inventory.css
   loads after app.css, and the max() below never yields less padding than
   those utilities did at the matching breakpoint. */
.app-page {
  padding-left: max(.75rem, var(--safe-left));
  padding-right: max(.75rem, var(--safe-right));
  padding-bottom: calc(2.5rem + var(--safe-bottom));
}
@media (min-width: 640px) {
  .app-page {
    padding-left: max(1rem, var(--safe-left));
    padding-right: max(1rem, var(--safe-right));
  }
}

.inv-h1 { font-size: 1.25rem; font-weight: 700; color: #0f172a; margin: .5rem 0 1rem; }
.inv-h2 { font-size: 1rem; font-weight: 700; color: #0f172a; margin: 1.25rem 0 .5rem; }
.inv-muted { color: #64748b; font-size: .875rem; }
.inv-note { white-space: pre-wrap; }

.inv-search-form { display: flex; gap: .5rem; margin-bottom: 1rem; }
.inv-search-input {
  flex: 1; min-width: 0; border: 1px solid #cbd5e1; border-radius: .6rem;
  padding: .75rem .9rem; font-size: 1rem;
}
.inv-search-btn {
  border: 0; border-radius: .6rem; background: #1e293b; color: #fff; font-weight: 600;
  padding: 0 1.1rem; font-size: .95rem;
}

.inv-tile-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: .6rem; margin-bottom: 1.5rem;
}
@media (min-width: 560px) { .inv-tile-grid { grid-template-columns: repeat(4, 1fr); } }
.inv-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .3rem; background: #fff; border: 1px solid #e2e8f0; border-radius: .9rem;
  padding: 1.1rem .5rem; text-decoration: none; color: #0f172a; font-weight: 600;
  font-size: .85rem; text-align: center; min-height: 84px;
}
.inv-tile:active { background: #f1f5f9; }
.inv-tile-icon { font-size: 1.5rem; line-height: 1; }
.inv-tile-badge {
  display: inline-block; margin-top: .15rem; background: #fee2e2; color: #b91c1c;
  border-radius: 999px; padding: .05rem .5rem; font-size: .7rem; font-weight: 700;
}

.inv-card {
  background: #fff; border: 1px solid #e2e8f0; border-radius: .8rem; padding: .9rem;
  margin-bottom: .6rem;
}
.inv-card-link { display: block; text-decoration: none; color: inherit; }
.inv-card-title { font-weight: 700; color: #0f172a; font-size: .95rem; }
.inv-card-sub { color: #64748b; font-size: .8rem; margin-top: .15rem; }
.inv-card-row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }

.inv-empty { color: #94a3b8; font-size: .9rem; padding: 1.25rem 0; text-align: center; }

.inv-badge {
  display: inline-block; border-radius: 999px; padding: .1rem .55rem; font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .02em;
}
.inv-badge-installed { background: #dcfce7; color: #166534; }
.inv-badge-spare { background: #e0e7ff; color: #3730a3; }
.inv-badge-in_repair { background: #fef3c7; color: #92400e; }
.inv-badge-missing { background: #fee2e2; color: #991b1b; }
.inv-badge-retired { background: #e2e8f0; color: #475569; }
.inv-badge-working { background: #dcfce7; color: #166534; }
.inv-badge-needs_attention { background: #fef3c7; color: #92400e; }
.inv-badge-broken { background: #fee2e2; color: #991b1b; }
.inv-badge-unknown { background: #e2e8f0; color: #475569; }
.inv-badge-warn { background: #fef3c7; color: #92400e; }
.inv-badge-bulk { background: #f1f5f9; color: #475569; }

.inv-field { margin-bottom: .9rem; }
.inv-label { display: block; font-size: .85rem; font-weight: 600; color: #334155; margin-bottom: .3rem; }
.inv-input, .inv-select, .inv-textarea {
  width: 100%; border: 1px solid #cbd5e1; border-radius: .55rem; padding: .65rem .75rem;
  font-size: 1rem; background: #fff; color: #0f172a;
}
.inv-textarea { min-height: 5rem; resize: vertical; }
.inv-help { font-size: .78rem; color: #64748b; margin-top: .25rem; }
.inv-error-box {
  background: #fef2f2; border: 1px solid #fecaca; color: #991b1b; border-radius: .6rem;
  padding: .75rem; margin-bottom: 1rem; font-size: .9rem;
}
.inv-error-box ul { margin: 0; padding-left: 1.1rem; }
.inv-conflict-box {
  background: #fffbeb; border: 1px solid #fde68a; color: #92400e; border-radius: .6rem;
  padding: .75rem; margin-bottom: 1rem; font-size: .9rem;
}
.inv-info-box {
  background: #eff6ff; border: 1px solid #bfdbfe; color: #1e3a8a; border-radius: .6rem;
  padding: .75rem; margin-bottom: 1rem; font-size: .9rem;
}

.inv-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  border: 1px solid #cbd5e1; border-radius: .6rem; background: #fff; color: #0f172a;
  font-weight: 600; font-size: .9rem; padding: .65rem 1rem; cursor: pointer; text-decoration: none;
}
.inv-btn-block { width: 100%; }
.inv-btn-lg { padding: .9rem 1rem; font-size: 1rem; min-height: 52px; }
.inv-btn-primary { background: #1e293b; color: #fff; border-color: #1e293b; }
.inv-btn-danger { background: #fff; color: #b91c1c; border-color: #fecaca; }
.inv-btn-danger-solid { background: #b91c1c; color: #fff; border-color: #b91c1c; }
.inv-btn-ghost { background: transparent; border-color: transparent; color: #334155; }
.inv-btn:disabled { opacity: .5; cursor: not-allowed; }

.inv-action-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .5rem; margin: 1rem 0; }
@media (min-width: 480px) { .inv-action-grid { grid-template-columns: repeat(3, 1fr); } }

.inv-history-item {
  border-left: 2px solid #e2e8f0; padding: .1rem 0 .8rem .8rem; margin-left: .3rem; font-size: .85rem;
}
.inv-history-time { color: #94a3b8; font-size: .75rem; }
.inv-history-event { font-weight: 600; color: #0f172a; }

.inv-tabs { display: flex; gap: .4rem; margin-bottom: 1rem; flex-wrap: wrap; }
.inv-tab {
  border: 1px solid #cbd5e1; border-radius: 999px; padding: .35rem .8rem; font-size: .8rem;
  font-weight: 600; color: #334155; text-decoration: none; background: #fff;
}
.inv-tab-active { background: #1e293b; color: #fff; border-color: #1e293b; }

.inv-stock-row {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .6rem 0; border-bottom: 1px solid #f1f5f9;
}
.inv-stock-qty { font-weight: 700; font-size: 1.1rem; }
.inv-inline-form { display: inline-flex; gap: .3rem; align-items: center; }
.inv-num-input { width: 4.5rem; }

.inv-scan-video { width: 100%; border-radius: .6rem; background: #000; min-height: 220px; }
.inv-scan-result { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1.1rem; }

fieldset.inv-fieldset { border: 1px solid #e2e8f0; border-radius: .7rem; padding: .8rem; margin-bottom: 1rem; }
fieldset.inv-fieldset legend { font-weight: 700; font-size: .85rem; color: #334155; padding: 0 .3rem; }

/* ------------------------------------------------------------------ */
/* Phase 10 -- Demo Guide and sample dashboard.                        */
/* Admin-only pages, only reachable while demo mode is enabled.        */
/* ------------------------------------------------------------------ */

.demo-section {
  background: #fff; border: 1px solid #e2e8f0; border-radius: .8rem;
  padding: .9rem; margin-bottom: 1rem;
}
.demo-section-warn { background: #fffbeb; border-color: #fde68a; }
.demo-section-muted { background: #f8fafc; }
.demo-section-danger { border-color: #fecaca; background: #fef2f2; }

.demo-prose { font-size: .9rem; color: #334155; line-height: 1.55; margin: .5rem 0; }
.demo-points { margin: .5rem 0; padding-left: 1.1rem; list-style: disc; }
.demo-points li { font-size: .9rem; color: #334155; line-height: 1.55; margin-bottom: .45rem; }

.demo-order { margin: .5rem 0; padding-left: 1.3rem; list-style: decimal; }
.demo-order li { font-size: .9rem; margin-bottom: .35rem; }
.demo-order a { color: #1d4ed8; text-decoration: underline; }

.demo-scenario {
  background: #fff; border: 1px solid #e2e8f0; border-left: 4px solid #1e293b;
  border-radius: .8rem; padding: .9rem; margin-bottom: .75rem;
  /* Anchor links from the "suggested order" list must not land under the
     sticky demo banner. */
  scroll-margin-top: 7rem;
}
.demo-scenario-number {
  font-size: .7rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: #64748b;
}
.demo-scenario-title { font-size: 1.02rem; font-weight: 700; color: #0f172a; margin: .15rem 0 .35rem; }
.demo-scenario-shows { font-size: .9rem; color: #1e293b; font-weight: 500; line-height: 1.5; }
.demo-scenario-links { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: .6rem; }

.demo-deferred { margin: .5rem 0; }
.demo-deferred dt { font-weight: 700; font-size: .88rem; color: #0f172a; margin-top: .6rem; }
.demo-deferred dd { margin: .15rem 0 0; font-size: .87rem; color: #475569; line-height: 1.5; }

.demo-counts { display: flex; flex-wrap: wrap; gap: .4rem; margin: .5rem 0; }
.demo-counts li {
  display: inline-flex; align-items: baseline; gap: .3rem; background: #f1f5f9;
  border-radius: .5rem; padding: .3rem .6rem; font-size: .8rem;
}
.demo-count-value { font-weight: 800; color: #0f172a; }
.demo-count-label { color: #475569; }

.demo-metric-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem; margin-bottom: 1.25rem;
}
@media (min-width: 640px) { .demo-metric-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.demo-metric {
  background: #fff; border: 1px solid #e2e8f0; border-radius: .8rem; padding: .8rem; min-width: 0;
}
.demo-metric-tag {
  display: inline-block; background: #fef3c7; color: #92400e; border-radius: 999px;
  padding: .05rem .5rem; font-size: .65rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase;
}
.demo-metric-value { font-size: 1.9rem; font-weight: 800; color: #0f172a; line-height: 1.1; margin-top: .3rem; }
.demo-metric-label { font-size: .85rem; font-weight: 700; color: #1e293b; }
.demo-metric-detail { font-size: .75rem; color: #64748b; line-height: 1.45; margin-top: .25rem; }

.demo-reset-form { margin-top: .5rem; }
.demo-reset-form .inv-btn { margin-top: .6rem; }

/* ------------------------------------------------------------------ */
/* Phase 10 -- touch-target floor.                                     */
/*                                                                      */
/* Measured on a 390x844 viewport: <select> and <input> controls in the */
/* Phase 7 review/correction forms rendered 20px tall, because the      */
/* utility classes they rely on for padding are missing from the        */
/* vendored purged Tailwind build (see the next section). This rule is  */
/* the robust floor: it does not depend on any utility class being      */
/* present, so a control can never again collapse to an untappable      */
/* height just because app.css was rebuilt without some class. 44px is  */
/* Apple's minimum comfortable target.                                  */
/* ------------------------------------------------------------------ */

input[type="text"], input[type="search"], input[type="number"], input[type="date"],
input[type="password"], input[type="email"], input[type="tel"], select {
  min-height: 44px;
}
textarea { min-height: 4.5rem; }
input[type="checkbox"], input[type="radio"] { min-width: 20px; min-height: 20px; }

/* A standalone link that is really an action (not part of a sentence)
   gets a full-height hit area rather than the 16px its text occupies.
   Applied to the ticket cards' "Open in Zendesk" link and the ticket
   page's "Back to inbox" link, both measured at 16px tall. */
.tap-target,
.inv-help a,
.demo-order a {
  display: inline-flex; align-items: center; min-height: 44px;
}

/* Every disclosure row ("More filters", "Set exact count", "Location
   history", "Switch to bulk"...) measured 20px tall -- a wide but very
   shallow target. Laying the summary out as a flex row with an explicit
   marker gives a 44px hit area and a consistent open/closed affordance;
   the native list-item marker is dropped because a flex box does not
   render one. */
summary {
  display: flex;
  align-items: center;
  gap: .45rem;
  min-height: 44px;
  list-style: none;
}
summary::-webkit-details-marker { display: none; }
summary::before {
  content: "\25B8";           /* small right-pointing triangle */
  flex: 0 0 auto;
  color: #64748b;
  font-size: .8em;
  line-height: 1;
}
details[open] > summary::before { content: "\25BE"; }
/* The account control is a disclosure too, but it is a compact button --
   it must keep its own sizing, not the wide-row treatment above. */
.inv-account-summary::before { content: none; }

/* A checkbox itself can only reasonably be ~20px; what needs to be
   tappable is the label row around it. Progressive enhancement: a
   browser without :has() simply keeps today's behaviour. */
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]) {
  min-height: 44px;
}

/* Post-write confirmation banner (see app/web/templating.py's
   FLASH_MESSAGES). Sits directly under the nav so it is on screen the
   moment the redirect lands, rather than wherever the page happens to
   be scrolled to. */
.app-flash {
  background: #dcfce7;
  border-bottom: 1px solid #86efac;
  color: #14532d;
  font-size: .875rem;
  font-weight: 600;
  padding: .7rem max(.75rem, var(--safe-right)) .7rem max(.75rem, var(--safe-left));
}

/* ------------------------------------------------------------------ */
/* Phase 10 -- utilities missing from the vendored Tailwind build.     */
/*                                                                      */
/* app.css is a purged Tailwind build committed as a vendored asset (no */
/* build step, no CDN -- see static/README.md). It predates several of  */
/* the Phase 7/8/9 templates, so a number of utility classes those      */
/* templates use were never emitted into it. The effect is visible, not */
/* theoretical: status/priority pills lost their background colour      */
/* entirely, form controls lost their padding, bulleted lists lost      */
/* their bullets, and the evidence picker lost its scroll cap.          */
/*                                                                      */
/* These declarations reproduce the standard Tailwind values for        */
/* exactly the classes the templates actually reference. Because        */
/* inventory.css loads after app.css, a future regenerated app.css that */
/* does include them simply wins where the values agree.                */
/* ------------------------------------------------------------------ */

/* Spacing / layout */
.p-2 { padding: .5rem; }
.px-1 { padding-left: .25rem; padding-right: .25rem; }
.px-1\.5 { padding-left: .375rem; padding-right: .375rem; }
.pt-1 { padding-top: .25rem; }
.mb-1 { margin-bottom: .25rem; }
.ml-2 { margin-left: .5rem; }
.mt-0\.5 { margin-top: .125rem; }
.max-h-40 { max-height: 10rem; }
.overflow-y-auto { overflow-y: auto; }
.rounded { border-radius: .25rem; }
.border-t { border-top-width: 1px; }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.font-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
.scroll-mt-20 { scroll-margin-top: 5rem; }
.space-y-1 > :not([hidden]) ~ :not([hidden]) { margin-top: .25rem; }
.space-y-2 > :not([hidden]) ~ :not([hidden]) { margin-top: .5rem; }
.space-y-4 > :not([hidden]) ~ :not([hidden]) { margin-top: 1rem; }

/* Lists -- Tailwind's reset removes markers, so a list without its
   list-style utility reads as an unbroken run of lines. */
.list-disc { list-style-type: disc; }
.list-none { list-style-type: none; }
.list-inside { list-style-position: inside; }

/* Status/priority pill colours -- see app/web/templating.py's
   status_classes()/priority_classes(), whose return values are exactly
   these class names. */
.bg-amber-100 { background-color: #fef3c7; }
.bg-blue-100 { background-color: #dbeafe; }
.bg-green-100 { background-color: #dcfce7; }
.bg-orange-100 { background-color: #ffedd5; }
.bg-purple-100 { background-color: #f3e8ff; }
.bg-slate-200 { background-color: #e2e8f0; }
.bg-violet-100 { background-color: #ede9fe; }
.text-blue-800 { color: #1e40af; }
.text-green-800 { color: #166534; }
.text-orange-800 { color: #9a3412; }
.text-purple-800 { color: #6b21a8; }
.text-violet-800 { color: #5b21b6; }
.text-green-700 { color: #15803d; }
.text-red-800 { color: #991b1b; }

/* Feedback boxes and action buttons */
.bg-red-50 { background-color: #fef2f2; }
.bg-green-50 { background-color: #f0fdf4; }
.bg-blue-700 { background-color: #1d4ed8; }
.bg-green-700 { background-color: #15803d; }
.bg-red-700 { background-color: #b91c1c; }
.bg-violet-600 { background-color: #7c3aed; }
.border-red-200 { border-color: #fecaca; }
.border-red-300 { border-color: #fca5a5; }
.border-green-200 { border-color: #bbf7d0; }
.border-green-300 { border-color: #86efac; }
.border-amber-200 { border-color: #fde68a; }
.border-slate-400 { border-color: #94a3b8; }
.border-violet-300 { border-color: #c4b5fd; }
.hover\:bg-slate-300:hover { background-color: #cbd5e1; }

/* Jumping to a cited comment from an AI analysis's evidence link marked
   nothing, because these two variant classes were never emitted -- so on
   a long ticket you landed near the right place with no idea which
   comment you had been sent to. */
.target\:ring-2:target { box-shadow: 0 0 0 2px #fbbf24; }
.target\:ring-amber-400:target { box-shadow: 0 0 0 2px #fbbf24; }

/* htmx toggles .htmx-request on the element making the request; these
   two rules are what actually hides/reveals a .htmx-indicator around
   it. Not a Tailwind utility -- htmx's own convention -- so it belongs
   here rather than in the generated app.css. */
.htmx-indicator { opacity: 0; transition: opacity 150ms ease-in; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }
