/*
  BARCAT styles. Mobile-first: the phone layout is the default and the
  desktop layout is the special case, because most of the use is someone in a
  storage unit with one hand free.

  Non-negotiables, kept here so they survive future edits:
  - Every target is at least 48px tall. Bigger for the primary action.
  - Focus is a 3px outline with an offset. Never removed, ever.
  - Type in rem, so the browser's font size setting works. Usable at 400% zoom.
  - Status is never colour alone -- there is always a word next to it.
  - Text contrast 4.5:1 or better, in both light and dark.
  - Nothing depends on hover. Touch has no hover.
*/

:root {
  color-scheme: light dark;

  --bg: #ffffff;
  --bg-sunken: #f1f3f5;
  --bg-raised: #ffffff;
  --text: #15181c;
  --text-muted: #495159;
  --border: #bcc2c9;
  --border-strong: #69707a;

  --accent: #0a5aa8;
  --accent-text: #ffffff;
  --accent-quiet: #e6f0fa;

  --danger: #9e1220;
  --danger-quiet: #fdecee;
  --warn: #764600;
  --warn-quiet: #fcf0da;
  --ok: #125c37;
  --ok-quiet: #e0f2e8;

  --radius: 10px;
  --tap: 48px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #13161a;
    --bg-sunken: #0d1013;
    --bg-raised: #1c2026;
    --text: #eef1f4;
    --text-muted: #b2b9c1;
    --border: #3f464e;
    --border-strong: #7b838c;

    --accent: #7ab6f5;
    --accent-text: #0b1117;
    --accent-quiet: #182b3e;

    --danger: #ff9ba2;
    --danger-quiet: #38191d;
    --warn: #efbe76;
    --warn-quiet: #382a13;
    --ok: #7ed7a4;
    --ok-quiet: #143027;
  }
}

*, *::before, *::after { box-sizing: border-box; }
html { font-size: 100%; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg-sunken);
  color: var(--text);
  font: 1.0625rem/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Room for the sticky action bar on phones. */
  padding-bottom: env(safe-area-inset-bottom);
}

img { max-width: 100%; height: auto; display: block; }

/* --- skip link --------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: -9999px;
  background: var(--accent);
  color: var(--accent-text);
  padding: 0.875rem 1.25rem;
  z-index: 200;
  font-weight: 600;
}
.skip-link:focus { left: 0; top: 0; }

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

.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border);
  padding: 0.25rem 0.75rem 0.125rem;
  padding-top: calc(0.25rem + env(safe-area-inset-top));
}
.masthead-inner {
  max-width: 60rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  /* Wraps to a second line on a 320px phone rather than pushing the page
     sideways. A horizontally scrolling page is miserable one-handed. */
  flex-wrap: wrap;
  gap: 0 0.75rem;
  min-height: var(--tap);
}
.wordmark {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  margin-right: auto;
  letter-spacing: 0.02em;
  /* min-width:0 lets a flex item actually shrink; without it the text refuses. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.masthead nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.125rem;
  align-items: center;
}
.masthead nav a {
  max-width: 10rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 23em) {
  .masthead nav a, .masthead nav button, .masthead nav summary { padding: 0 0.5rem; }
}
.masthead nav a, .masthead nav button, .masthead nav summary {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  min-width: var(--tap);
  justify-content: center;
  padding: 0 0.625rem;
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  font: inherit;
  font-weight: 500;
  font-size: 0.9375rem;
  background: none;
  border: none;
  cursor: pointer;
}
.masthead nav a[aria-current="page"] {
  background: var(--accent-quiet);
  color: var(--text);
  font-weight: 700;
}

/* The folded Organizations/Users/Account menu -- a <details> so it needs no
   JavaScript, same idiom as every other disclosure in this app. */
.masthead nav details { position: relative; }
.masthead nav summary { list-style: none; }
.masthead nav summary::-webkit-details-marker { display: none; }
.masthead nav summary::after { content: " \25BE"; }
.masthead nav details[open] > summary::after { content: " \25B4"; }
.masthead nav summary.active {
  background: var(--accent-quiet);
  color: var(--text);
  font-weight: 700;
}
.nav-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.25rem);
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 11rem;
  padding: 0.375rem;
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  z-index: 60;
}
.nav-menu-panel a { max-width: none; justify-content: flex-start; }

main {
  max-width: 60rem;
  margin: 0 auto;
  padding: 1rem 0.875rem 5rem;
}

h1 { font-size: 1.5rem; line-height: 1.2; margin: 0 0 0.25rem; }
h2 { font-size: 1.1875rem; margin: 1.75rem 0 0.5rem; }
h3 { font-size: 1rem; margin: 1.25rem 0 0.375rem; }
.subtitle { color: var(--text-muted); margin: 0 0 1.25rem; }

@media (min-width: 40em) {
  h1 { font-size: 1.875rem; }
  main { padding: 1.5rem 1rem 4rem; }
}

/* --- flash messages ---------------------------------------------------- */

.flash {
  border-radius: var(--radius);
  padding: 0.875rem 1rem;
  margin-bottom: 1rem;
  font-weight: 500;
  border: 2px solid;
}
.flash.ok { background: var(--ok-quiet); border-color: var(--ok); color: var(--ok); }
.flash.alert { background: var(--danger-quiet); border-color: var(--danger); color: var(--danger); }

/* --- panels ------------------------------------------------------------ */

.panel {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  margin-bottom: 1rem;
}
.panel > h2:first-child, .panel > h3:first-child { margin-top: 0; }

/* --- the inventory list ------------------------------------------------ */

.item-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }

@media (min-width: 34em) {
  .item-list { grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }
}

.item-card {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.item-card a.card-link {
  display: flex;
  gap: 0.875rem;
  padding: 0.75rem;
  text-decoration: none;
  color: var(--text);
  align-items: flex-start;
  min-height: var(--tap);
}
.item-card a.card-link:hover .card-title,
.item-card a.card-link:focus-visible .card-title { text-decoration: underline; }

.card-thumb-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  flex: 0 0 auto;
}
.card-thumb-col .badge { margin: 0; }
.card-thumb {
  width: 5rem;
  height: 5rem;
  border-radius: 8px;
  object-fit: cover;
  background: var(--bg-sunken);
  border: 1px solid var(--border);
}
.card-thumb.placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.75rem;
  text-align: center;
  line-height: 1.2;
  padding: 0.25rem;
}
.card-body { min-width: 0; flex: 1; }
.card-title { font-weight: 700; display: block; }
.card-meta { color: var(--text-muted); font-size: 0.9375rem; display: block; }

/* --- badges ------------------------------------------------------------ */

.badge {
  display: inline-block;
  padding: 0.1875rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
  margin: 0.1875rem 0.1875rem 0 0;
}
.badge.ok { background: var(--ok-quiet); color: var(--ok); border-color: var(--ok); }
.badge.warn { background: var(--warn-quiet); color: var(--warn); border-color: var(--warn); }
.badge.alert { background: var(--danger-quiet); color: var(--danger); border-color: var(--danger); }
.badge.quiet { background: var(--bg-sunken); color: var(--text-muted); }

/* --- forms ------------------------------------------------------------- */

.field { margin-bottom: 1rem; }
.field label, .field > .label { display: block; font-weight: 600; margin-bottom: 0.25rem; }
.field .hint { display: block; color: var(--text-muted); font-size: 0.9375rem; margin-bottom: 0.375rem; }

input[type="text"], input[type="password"], input[type="email"], input[type="tel"],
input[type="date"], input[type="number"], input[type="search"], select, textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 0.625rem 0.75rem;
  /* 1rem minimum or iOS zooms the whole page when the field is focused. */
  font: inherit;
  font-size: 1rem;
  color: var(--text);
  background: var(--bg);
  border: 2px solid var(--border-strong);
  border-radius: var(--radius);
}
textarea { min-height: 5.5rem; resize: vertical; }
select { appearance: none; background-image: none; }

input[type="checkbox"] { width: 1.5rem; height: 1.5rem; margin: 0; accent-color: var(--accent); }
.check-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: var(--tap);
  font-weight: 500;
  cursor: pointer;
}

fieldset { border: 1px solid var(--border); border-radius: var(--radius); padding: 0.75rem 1rem 1rem; margin: 0 0 1rem; }
legend { font-weight: 700; padding: 0 0.375rem; }

.field-row { display: grid; gap: 0 1rem; }
@media (min-width: 34em) { .field-row { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); } }

/* --- buttons ----------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--tap);
  padding: 0 1.125rem;
  font: inherit;
  font-weight: 700;
  border-radius: var(--radius);
  border: 2px solid var(--accent);
  background: var(--accent);
  color: var(--accent-text);
  text-decoration: none;
  cursor: pointer;
  text-align: center;
}
.btn.secondary { background: var(--bg-raised); color: var(--text); border-color: var(--border-strong); }
.btn.danger { background: var(--bg-raised); color: var(--danger); border-color: var(--danger); }
.btn.block { display: flex; width: 100%; }
.btn.big { min-height: 3.75rem; font-size: 1.125rem; }
.btn.small { min-height: 40px; padding: 0 0.75rem; font-size: 0.9375rem; font-weight: 600; }

.actions { display: flex; flex-wrap: wrap; gap: 0.625rem; margin-top: 1rem; }
.actions .btn { flex: 1 1 auto; }
@media (min-width: 34em) { .actions .btn { flex: 0 0 auto; } }

/* Two buttons sharing one row, each taking half the width -- used for
   Add device/Add part and for Filter/Search on the inventory page.
   align-items:flex-start so an open <details> next to a plain button
   doesn't stretch the button to match its expanded height. */
.btn-row { display: flex; gap: 0.625rem; align-items: flex-start; }
.btn-row > * { flex: 1 1 auto; min-width: 0; }

/* --- the camera button, the most important control in the app ---------- */

.camera-button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  width: 100%;
  min-height: 4rem;
  border: 3px dashed var(--accent);
  border-radius: var(--radius);
  background: var(--accent-quiet);
  color: var(--text);
  font-weight: 700;
  font-size: 1.125rem;
  cursor: pointer;
  padding: 0.75rem 1rem;
  text-align: center;
}
.camera-button svg { flex: 0 0 auto; }
/* The real file input is hidden but still focusable and still labelled, so
   keyboard and screen reader users get the same control. */
.visually-hidden-input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  overflow: hidden;
}
.visually-hidden-input:focus-visible + .camera-button {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* --- photo gallery ----------------------------------------------------- */

.gallery { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: 0.75rem; }
@media (min-width: 30em) { .gallery { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); } }

.gallery figure { margin: 0; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg-raised); }
.gallery img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--bg-sunken); }
.gallery figcaption { padding: 0.625rem 0.75rem; font-size: 0.9375rem; }
.gallery .photo-actions { display: flex; flex-wrap: wrap; gap: 0.375rem; padding: 0 0.75rem 0.75rem; }

.hero-photo {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  margin-bottom: 1rem;
  background: var(--bg-sunken);
}

/* --- definition lists -------------------------------------------------- */

.spec { display: grid; grid-template-columns: max-content 1fr; gap: 0.375rem 1rem; margin: 0; }
.spec dt { font-weight: 600; color: var(--text-muted); }
.spec dd { margin: 0; word-break: break-word; }

/* --- notes log --------------------------------------------------------- */

.note-log { list-style: none; padding: 0; margin: 0 0 1rem; }
.note-log li { border-left: 4px solid var(--border); padding: 0.5rem 0 0.5rem 0.875rem; margin-bottom: 0.75rem; }
.note-log .byline { display: block; color: var(--text-muted); font-size: 0.875rem; }

/* --- device models and manuals ------------------------------------------ */

.model-list, .manual-list, .item-list {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
}
.model-list li, .manual-list li, .item-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  border-bottom: 1px solid var(--border);
  padding: 0.625rem 0;
}
.model-list li:last-child, .manual-list li:last-child, .item-list li:last-child {
  border-bottom: none;
}
.manual-list form { margin-left: auto; }

/* --- tables (users page) ----------------------------------------------- */

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; background: var(--bg-raised); }
th, td {
  text-align: left;
  padding: 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  /* Containing block for any .visually-hidden label inside. Without this an
     absolutely positioned screen-reader label anchors to the viewport and can
     push the page a few pixels sideways on a narrow phone. */
  position: relative;
}
thead th { border-bottom: 2px solid var(--border-strong); font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }

/* --- links and focus --------------------------------------------------- */

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

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
@media (prefers-color-scheme: dark) {
  :focus-visible { outline-color: #ffd479; }
}

/* --- misc -------------------------------------------------------------- */

.muted { color: var(--text-muted); }
.empty { color: var(--text-muted); padding: 1.5rem 0; text-align: center; }
.count { color: var(--text-muted); font-size: 0.9375rem; margin-bottom: 0.75rem; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* "+ Add a device" / "+ Add a part" -- right under the page heading, side by
   side. Used to be pinned to the bottom of the screen on phones, but that
   sandwiched the page between two fixed bars (the nav above, this below);
   now the nav is the only fixed strip and everything else scrolls as one
   normal page. */
.sticky-add { display: flex; gap: 0.625rem; margin-bottom: 1.25rem; }
.sticky-add .btn { flex: 1 1 0; }
@media (min-width: 34em) {
  .sticky-add .btn { flex: 0 0 auto; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* <details> used as a disclosure button. The marker is hidden because the
   summary is already styled as a button and announced as one. */
summary.btn { list-style: none; cursor: pointer; }
summary.btn::-webkit-details-marker { display: none; }
summary.btn::after { content: " ▾"; }
details[open] > summary.btn::after { content: " ▴"; }

/* The cat, next to the wordmark. Rounded so the white icon square doesn't sit
   as a hard rectangle on a dark background. */
.wordmark-cat {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: #fff;
}

.login-title { display: flex; align-items: center; gap: 0.75rem; }
.login-cat { width: 56px; height: 56px; border-radius: 12px; background: #fff; }

/* The verdict -- what someone decided should happen to this thing. It sits
   above the specification table because it's the actionable part. */
.verdict {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0 0 1rem;
  padding: 0.75rem 0.875rem;
  background: var(--accent-quiet);
  border-left: 5px solid var(--accent);
  border-radius: var(--radius);
  font-weight: 500;
}
.verdict-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
