/* Mobile-first. The primary client is a phone that has just scanned a QR code.
 *
 * Palette follows www.ladisk.si: brand red #CF1D2D, light band #F8F8F8. The
 * site uses the red strictly as rules and accents — a 2px border under the
 * navbar, 2px bands around headings, the footer's top rule, nav hover/active —
 * and never as a fill; its buttons and body links stay blue. That is copied
 * deliberately rather than tidied up, because here it also keeps saturated red
 * free to mean *overdue*, which is the one colour signal this app cannot
 * afford to blur.
 */

:root {
  color-scheme: light;

  --brand: #cf1d2d;       /* ladisk.si rules and accents */
  --brand-ink: #cf1d2d;   /* brand red as text — darkened in dark mode */
  --bg: #ffffff;
  --band: #f8f8f8;        /* ladisk.si heading/thumbnail band */
  --fg: #1a1d21;
  --muted: #5c6672;
  --line: #dfe3e8;
  --accent: #14507d;      /* interactive fills: buttons, links, selection */
  --accent-ink: #ffffff;  /* text on top of an --accent fill */
  --field: #ffffff;
  --ok: #1f7a4d;
  --ok-bg: #e7f5ee;
  --warn: #8a5a00;
  --warn-bg: #fdf3e0;
  --bad: #a02020;
  --bad-bg: #fbeaea;
  --locked-bg: #eef0f3;
  --radius: 8px;
}

/* The dark palette is written twice on purpose: once for an explicit choice,
   once for the system preference when no explicit choice was made. CSS has no
   way to share one declaration block between a selector and a media query, and
   duplicating ten lines beats a build step or a light-dark() dependency. Keep
   the two blocks identical. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --brand: #e8505f;
  --brand-ink: #f08a95;
  --bg: #16181c;
  --band: #1e2126;
  --fg: #e8eaed;
  --muted: #9aa4b0;
  --line: #2c3138;
  --accent: #6fb3e8;
  --accent-ink: #10131a;
  --field: #1e2126;
  --ok: #6ed69f;
  --ok-bg: #1a3326;
  --warn: #e8bd6f;
  --warn-bg: #3a2c0f;
  --bad: #f08a8a;
  --bad-bg: #3a1d1d;
  --locked-bg: #262a30;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --brand: #e8505f;
    --brand-ink: #f08a95;
    --bg: #16181c;
    --band: #1e2126;
    --fg: #e8eaed;
    --muted: #9aa4b0;
    --line: #2c3138;
    --accent: #6fb3e8;
    --accent-ink: #10131a;
    --field: #1e2126;
    --ok: #6ed69f;
    --ok-bg: #1a3326;
    --warn: #e8bd6f;
    --warn-bg: #3a2c0f;
    --bad: #f08a8a;
    --bad-bg: #3a1d1d;
    --locked-bg: #262a30;
  }
}

* { box-sizing: border-box; }

/* The UA rule for [hidden] is display:none at low specificity, so any element
   rule that sets display beats it. `button { display: inline-block }` did
   exactly that, which is why the language picker's no-JavaScript "Go" fallback
   stayed on screen after the script hid it — on every viewport, not just this
   one. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
}

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

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

/* --- top bar --------------------------------------------------------- */
/* The 2px red underline is ladisk.si's most recognisable element. */
.topbar {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem .75rem;
  align-items: center;
  justify-content: space-between;
  padding: .6rem 1rem;
  /* Notched phones: keep the bar clear of the rounded corners. */
  padding-left: max(1rem, env(safe-area-inset-left));
  padding-right: max(1rem, env(safe-area-inset-right));
  background: var(--band);
  border-bottom: 2px solid var(--brand);
}
.brand {
  display: inline-flex; align-items: center; gap: .5rem;
  font-weight: 600; text-decoration: none; color: var(--fg);
}
.brand:hover { color: var(--brand-ink); }
.brand-logo { height: 2.2rem; width: auto; display: block; }

/* The wordmark's "www." and ".si" are near-black, so on a dark bar they vanish
   and only the red waveform survives. A light chip keeps the logo exactly as
   drawn; filtering or inverting it would wreck the brand red. Written twice for
   the same reason as the palette above — explicit choice, then system default. */
:root[data-theme="dark"] .brand-logo {
  background: #fff;
  border-radius: 4px;
  padding: 2px 4px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo {
    background: #fff;
    border-radius: 4px;
    padding: 2px 4px;
  }
}
/* On a phone the brand takes the first row and the whole of nav the second, so
   nav must fit 358 px on its own — it did not, and the language select and theme
   toggle were pushed off-screen entirely. */
.topbar nav {
  display: flex; gap: 1rem; align-items: center;
  flex-wrap: wrap; min-width: 0;
}
.topbar nav a, .topbar nav button, .topbar nav summary { white-space: nowrap; }
.topbar nav a { color: var(--fg); text-decoration: none; font-size: .95rem; }
@media (max-width: 40rem) {
  .topbar { gap: .35rem .6rem; }
  .topbar nav { gap: .75rem; width: 100%; justify-content: flex-start; }
  /* Truncated to "ad..." at this width — noise, and the name is on Mine. */
  .whoami { display: none; }
  .brand-logo { height: 1.9rem; }
  .brand span { font-size: .95rem; }
}
.topbar nav a:hover { color: var(--brand-ink); text-decoration: underline; }
.inline { display: inline; margin: 0; }
/* Signed-in identity: present, but never competing with the nav links. */
.whoami {
  color: var(--muted); font-size: .85rem;
  max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.linkish {
  background: none; border: 0; padding: 0;
  color: inherit; font: inherit; font-size: .95rem; cursor: pointer;
}
.topbar .linkish:hover { color: var(--brand-ink); text-decoration: underline; }

/* Language picker. Narrow, and it must not inherit the full-width rule that
   applies to every other select on the site. */
.lang-form { display: flex; gap: .3rem; align-items: center; margin: 0; min-width: 0; }
.lang-form select {
  width: auto; max-width: 7.5rem; padding: .25rem 1.4rem .25rem .4rem;
  /* 16px, not smaller: iOS Safari zooms the whole page when a control with a
     font under 16px takes focus, and the user has to pinch back out. */
  font-size: 1rem; border-radius: var(--radius);
}
@media (max-width: 40rem) { .lang-form select { max-width: 5.5rem; } }
.lang-go { padding: .2rem .5rem; font-size: .85rem; }

/* For labels that screen readers need and sighted users do not. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Light/dark switch. One button cycling auto -> light -> dark; the icon shows
   the current state, not the state clicking would move to. Which glyph is
   visible is decided in CSS from data-mode, so the button is never blank. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; padding: 0;
  background: none; border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); cursor: pointer;
}
.theme-toggle:hover { border-color: var(--brand); color: var(--brand-ink); }
.theme-toggle svg {
  display: none; width: 1.15rem; height: 1.15rem;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.theme-toggle[data-mode="auto"] .i-auto,
.theme-toggle[data-mode="light"] .i-light,
.theme-toggle[data-mode="dark"] .i-dark { display: block; }

footer {
  max-width: 60rem;
  margin: 2rem auto 0;
  padding: 1rem;
  color: var(--muted);
  font-size: .85rem;
  border-top: 2px solid var(--brand);
}

/* --- messages -------------------------------------------------------- */
.messages { list-style: none; margin: 0; padding: .5rem 1rem; }
.msg { padding: .6rem .8rem; border-radius: var(--radius); margin-bottom: .4rem; }
.msg.success { background: var(--ok-bg); color: var(--ok); }
.msg.error { background: var(--bad-bg); color: var(--bad); }
.msg.warning { background: var(--warn-bg); color: var(--warn); }

/* --- status pills ---------------------------------------------------- */
.pill {
  display: inline-block;
  padding: .3rem .7rem;
  border-radius: 999px;
  font-size: .8rem;
  line-height: 1.35;
  font-weight: 600;
  white-space: nowrap;
}
.pill.available { background: var(--ok-bg); color: var(--ok); }
.pill.out { background: var(--warn-bg); color: var(--warn); }
.pill.overdue { background: var(--bad-bg); color: var(--bad); }
.pill.locked { background: var(--locked-bg); color: var(--muted); }

/* --- forms and buttons ----------------------------------------------- */
label { display: block; font-weight: 600; font-size: .9rem; margin-bottom: .2rem; }
/* Broad, not per-type: allauth renders email and password fields we do not
   author ourselves, and they must not fall back to browser defaults. */
input:not([type=checkbox]):not([type=radio]):not([type=submit]),
select, textarea {
  width: 100%;
  padding: .55rem .6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font: inherit;
  background: var(--field);
  color: inherit;
}
.field { margin-bottom: .9rem; }
.help { color: var(--muted); font-size: .85rem; font-weight: normal; }
.errorlist { color: var(--bad); font-size: .85rem; margin: .25rem 0 0; padding-left: 1rem; }

button, .button {
  display: inline-block;
  padding: .6rem 1rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-ink);
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
button.secondary, .button.secondary {
  background: transparent; color: var(--accent);
}
/* .linkish and .theme-toggle are buttons only in the HTML sense. */
button.linkish { padding: 0; font-weight: inherit; }

/* --- equipment detail ------------------------------------------------ */
/* Echoes ladisk.si's .title-heading: a light band ruled in brand red. */
.item-head {
  background: var(--band);
  border-top: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  padding: .6rem .8rem;
  margin-bottom: 1rem;
}
.item-head h1 { margin: .2rem 0; font-size: 1.4rem; }
.pubid { font-family: ui-monospace, "SF Mono", Menlo, monospace; color: var(--muted); }

.status-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .9rem;
  margin-bottom: 1.25rem;
}
/* Checking out is the reason this page exists, so when it is possible the card
   carries a brand-red edge and reads as the page's subject rather than one
   panel among several. */
.status-card.primary {
  border-left: 4px solid var(--brand);
  background: var(--band);
  padding: 1.1rem;
}
.checkout-form { margin-top: 1rem; }
.checkout-fields { display: grid; gap: .9rem; }
@media (min-width: 34rem) {
  .checkout-fields { grid-template-columns: 2fr 1fr; align-items: start; }
}
.checkout-note { margin: .2rem 0 1rem; }
.checkout-note summary {
  cursor: pointer; font-size: .9rem; color: var(--accent);
  width: max-content; padding: .2rem 0;
}
.checkout-note textarea { margin-top: .4rem; }
/* The one action people came here for: full width on a phone, hard to miss. */
.primary-action {
  width: 100%; padding: .85rem 1rem; font-size: 1.05rem;
}
@media (min-width: 34rem) { .primary-action { width: auto; min-width: 14rem; } }

/* Preferences live below the list and read as a separate thing: own rule, own
   heading, muted panel. Above the list they looked like a filter on it. */
.settings {
  margin-top: 2.5rem;
  border-top: 1px solid var(--line);
  padding-top: 1rem;
}
.settings h2 { font-size: 1.05rem; margin: 0 0 .6rem; color: var(--muted); }
.default-location {
  display: flex; gap: .8rem; align-items: flex-end; flex-wrap: wrap;
  background: var(--band);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: .8rem;
}
.default-location .field { margin: 0; flex: 1 1 16rem; }


/* Staff menu. <details> so it opens without JavaScript; the script in base.html
   only adds close-on-outside-click, which is a nicety rather than the mechanism. */
.menu { position: relative; }
.menu > summary {
  cursor: pointer; list-style: none; font-size: .95rem;
  display: inline-flex; align-items: center; gap: .35rem;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary::after { content: "▾"; font-size: .7rem; color: var(--muted); }
.menu > summary:hover { color: var(--brand-ink); }
.menu > ul {
  position: absolute; right: 0; top: calc(100% + .45rem); z-index: 20;
  min-width: 12rem; max-width: calc(100vw - 2rem); margin: 0; padding: .25rem;
  list-style: none; background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 6px 20px rgb(0 0 0 / .18);
}
/* On a phone the button sits at the left of its row, so anchoring the panel's
   right edge to it threw the panel off the left of the screen. Position it
   against the bar instead and let it span the width — the containing block is
   whichever ancestor is positioned, so .menu has to go static for that. */
@media (max-width: 40rem) {
  .topbar { position: relative; }
  .menu { position: static; }
  .menu > ul {
    left: 1rem; right: 1rem; max-width: none;
    top: calc(100% + .3rem);
  }
}
.menu > ul a {
  display: flex; justify-content: space-between; gap: .5rem;
  padding: .45rem .6rem; border-radius: var(--radius);
  text-decoration: none; color: var(--fg); font-size: .9rem; white-space: nowrap;
}
.menu > ul a:hover { background: var(--band); color: var(--brand-ink); }

.badge {
  display: inline-block; min-width: 1.25rem; padding: 0 .35rem;
  border-radius: 999px; background: var(--brand); color: #fff;
  font-size: .75rem; font-weight: 700; text-align: center; line-height: 1.35;
}

.approvals li {
  display: flex; gap: .5rem .8rem; align-items: center;
  justify-content: space-between; flex-wrap: wrap;
}
.staff-toggle { display: flex; gap: .5rem; align-items: center; margin: 0; }
.staff-toggle label {
  display: flex; gap: .4rem; align-items: center;
  margin: 0; font-weight: 500; font-size: .9rem; cursor: pointer;
  /* A bare checkbox is a poor thumb target; the label makes the whole thing one. */
  padding: .5rem .2rem;
}
.staff-toggle input { width: 1.15rem; height: 1.15rem; accent-color: var(--accent); }
/* :not(.pill) matters. This targets the name/meta wrapper, but a pill is also a
   direct span child of the same li, and `.approvals li > span` outranks `.pill`
   — so the pills silently inherited .7rem/.2rem and looked squeezed sideways
   however much padding .pill asked for. */
.approvals li > span:not(.pill) { padding: .7rem .2rem; }
.approvals button { padding: .35rem .8rem; font-size: .9rem; }

.row-actions { white-space: nowrap; }
.row-actions a { margin-right: .7rem; font-size: .9rem; }
.status-card dl { margin: .6rem 0 0; display: grid; grid-template-columns: auto 1fr; gap: .3rem .8rem; }
.status-card dt { color: var(--muted); font-size: .9rem; }
.status-card dd { margin: 0; }

table.specs { width: 100%; border-collapse: collapse; }
table.specs th, table.specs td {
  text-align: left;
  padding: .45rem .5rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  font-size: .95rem;
}
table.specs th { width: 40%; color: var(--muted); font-weight: 600; }
table.specs td { white-space: pre-line; }

/* --- allauth pages --------------------------------------------------- */
main form p { margin: 0 0 .9rem; }
main form p label { display: block; }
.socialaccount_providers { list-style: none; padding: 0; margin: 1rem 0; }
.socialaccount_providers a { font-weight: 600; }

/* --- index: sidebar + results ---------------------------------------- */
main.wide { max-width: 76rem; }

/* Phone order: search first, then a compact category list, then the results.
   The sidebar used to sit above everything and eat 45vh before you could reach
   the search box — on the page whose whole purpose is finding something. */
.layout { display: flex; flex-direction: column; gap: 1rem; }
.filters { order: 1; }
.sidebar { order: 2; }
.results { order: 3; }
@media (min-width: 52rem) {
  .layout {
    display: grid;
    grid-template-columns: 17rem 1fr;
    grid-template-areas: "side filters" "side results";
    gap: 0 2rem;
    align-items: start;
  }
  .sidebar { grid-area: side; }
  .filters { grid-area: filters; }
  .results { grid-area: results; }
}

/* The category list is always expanded. On a phone it is capped and scrolls in
   place rather than pushing the results off the bottom of the screen. */
.sidebar {
  margin-bottom: 0;
  max-height: 14rem;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .4rem;
  -webkit-overflow-scrolling: touch;
}
@media (min-width: 52rem) {
  .sidebar {
    position: sticky; top: 1rem;
    max-height: calc(100vh - 2rem);
    border: 0; padding: 0;
  }
}

.sidebar summary {
  cursor: pointer; padding: .45rem .5rem .45rem 1.2rem; border-radius: var(--radius);
  font-weight: 600; font-size: .9rem; position: relative;
  display: flex; justify-content: space-between; gap: .5rem; align-items: baseline;
}
.sidebar summary::-webkit-details-marker { display: none; }
.sidebar summary::marker { content: ""; }
/* Own triangle, so it points the same way in every browser. */
.sidebar summary::before {
  content: "▾"; position: absolute; left: .35rem;
  font-size: .7rem; color: var(--muted);
}
.sidebar details:not([open]) > summary::before { content: "▸"; }
.sidebar summary:hover { background: var(--band); color: var(--brand-ink); }

.sidebar ul { list-style: none; margin: 0; padding: 0; }
.sidebar details ul { margin-left: .6rem; border-left: 1px solid var(--line); padding-left: .4rem; }

a.cat {
  display: flex; justify-content: space-between; gap: .5rem; align-items: baseline;
  padding: .4rem .5rem; border-radius: var(--radius);
  text-decoration: none; color: var(--fg); font-size: .9rem;
}
a.cat:hover { background: var(--band); color: var(--brand-ink); }
a.cat.active { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
a.cat.all { font-weight: 600; }
a.cat.sub { font-size: .87rem; }
.count { color: var(--muted); font-size: .8rem; font-variant-numeric: tabular-nums; }
a.cat.active .count { color: inherit; opacity: .8; }

.filters { display: grid; gap: .6rem; margin-bottom: 1rem; }
@media (min-width: 40rem) { .filters { grid-template-columns: 2fr 1fr 1fr 1fr auto; align-items: end; } }
@media (min-width: 52rem) and (max-width: 68rem) {
  .filters { grid-template-columns: 1fr 1fr; }
}

.item-list { list-style: none; margin: 0; padding: 0; }
.item-list li { border-bottom: 1px solid var(--line); }
.item-list a {
  display: flex; gap: .6rem; justify-content: space-between; align-items: baseline;
  padding: .7rem .2rem; text-decoration: none; color: inherit;
}
.item-list a:hover { background: var(--band); }

/* "Mine" rows carry an action, so the link cannot wrap the whole row. On a
   phone the three parts wrap onto two lines instead of being squeezed flat. */
.mine-list li { display: flex; gap: .5rem .7rem; align-items: center; flex-wrap: wrap; }
.mine-list li a { flex: 1 1 100%; display: block; }
.mine-list form { margin-left: auto; }
.mine-list button { padding: .45rem .9rem; white-space: nowrap; }
@media (min-width: 40rem) {
  .mine-list li a { flex: 1 1 auto; }
}
.item-list .name { font-weight: 600; }
.item-list .meta { display: block; color: var(--muted); font-size: .85rem; font-weight: normal; }
/* The category leads the meta line: with 404 items in one list, "which kind of
   thing is this" is the first question, and the brand red separates it from the
   grey identifiers that follow without looking like a link. */
.cat-tag { color: var(--brand-ink); font-weight: 600; }

.empty { color: var(--muted); padding: 2rem 0; text-align: center; }


/* --- phone sizing ------------------------------------------------------ */
/* The primary client is a phone that has just scanned a QR code, so these are
   corrections measured against a 390 px viewport rather than guesses. */
@media (max-width: 40rem) {
  main { padding: .75rem .9rem 3rem; }
  h1 { font-size: 1.45rem; margin: .3rem 0 .6rem; }
  h2 { font-size: 1.15rem; }

  /* Comfortable thumb targets. 44 px is the figure both platforms publish. */
  button, .button { min-height: 2.75rem; }
  .item-list a { padding: .85rem .2rem; }
  .menu > ul a { padding: .7rem .6rem; }

  /* A spec table with a long value must scroll inside itself rather than
     making the whole page scroll sideways. */
  table.specs { display: block; overflow-x: auto; white-space: normal; }
  table.specs th { width: 40%; }

  /* Nothing may push the document wider than the screen. */
  body { overflow-x: hidden; }
}

/* Never let a control fall below 16px on a touch screen: iOS zooms the page in
   on focus and does not zoom back out. */
@media (max-width: 40rem) and (pointer: coarse) {
  input:not([type=checkbox]):not([type=radio]):not([type=submit]),
  select, textarea { font-size: 16px; }
}
