/* ==========================================================================
   AU Makerspace — Design System
   ========================================================================== */

:root {
  /* Brand (sampled from official logo) — gold + ink only, no synthetic accent */
  --gold: #ac915f;
  --gold-dark: #7a6440; /* darkened from #8a7449 for reliable 4.5:1 text contrast on white */
  --gold-light: #d9c9a3;
  --ink: #231f20;
  --ink-soft: #4a4544;

  /* Neutrals — the site is white/cream throughout, no dark sections */
  --paper: #ffffff;
  --paper-alt: #f6f2ea;
  --white: #ffffff;
  --line: #e2d9c4;

  /* Semantic */
  --text: var(--ink);
  --text-muted: #6b6360;
  --bg: var(--paper);
  --surface: var(--white);
  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --shadow-sm: 0 2px 10px -4px rgba(35, 31, 32, 0.1);
  --shadow: 0 8px 24px -10px rgba(35, 31, 32, 0.16);

  --font-display: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-body: "Inter", "Segoe UI", system-ui, sans-serif;

  --max-width: 1180px;
  color-scheme: light;
}

* {
  box-sizing: border-box;
}

/* A handful of elements set their own unconditional `display` (.field's
   display: grid, for one) which — same specificity, but author styles
   beat the UA stylesheet regardless of source order — would otherwise
   silently defeat the plain `hidden` attribute on those elements. */
[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
  background: var(--bg);
}

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
  text-decoration: none;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.15;
  margin: 0 0 0.5em;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2.2rem, 4.5vw, 3.5rem); font-weight: 700; }
h2 { font-size: clamp(1.6rem, 3vw, 2.3rem); font-weight: 700; }
h3 { font-size: 1.2rem; font-weight: 700; }
p { margin: 0 0 1em; color: var(--text-muted); }

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--gold-dark);
  margin-bottom: 14px;
}
.eyebrow::before {
  content: "";
  width: 20px;
  height: 3px;
  background: var(--ink);
  display: inline-block;
}

/* ---------------- Buttons ---------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.96rem;
  padding: 13px 26px;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
  white-space: nowrap;
}
/* Same tactile press feedback on every button site-wide — reduced-motion
   visitors get none of it, matching how .reveal's scroll-in animation is
   already skipped for them in js/script.js. */
@media (prefers-reduced-motion: no-preference) {
  .btn:active { transform: scale(0.96); }
}

.btn-primary {
  background: var(--ink);
  color: #fff;
}
.btn-primary:hover { background: var(--gold-dark); }

.btn-gold {
  background: var(--gold);
  color: #fff;
}
.btn-gold:hover { background: var(--gold-dark); }

.btn-outline {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}
.btn-outline:hover { background: var(--ink); color: #fff; }

.btn-sm { padding: 10px 18px; font-size: 0.86rem; }

/* ---------------- Header ---------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--paper);
  border-bottom: 2px solid var(--ink);
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
  transition: height 0.2s ease;
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
}
.brand img { height: 32px; width: auto; transition: height 0.2s ease; }

/* Shrinks slightly once the page has scrolled — see js/script.js, which
   toggles this class on scroll. Skipped on the 901px-and-below header
   layout below since that one already sets its own fixed height. */
@media (min-width: 901px) {
  .site-header.is-scrolled .container { height: 60px; }
  .site-header.is-scrolled .brand img { height: 26px; }
}

/* Below 901px: the header is just logo + Reserve button + hamburger, and
   every link (primary and "more" alike, including the hidden admin one)
   lives in this one flat dropdown, opened by .nav-toggle below. Stays in
   the DOM at display:flex (just invisible/non-interactive) rather than
   display:none, so opening it can actually transition instead of
   snapping open. At 901px+ this becomes a real horizontal bar instead —
   see the min-width:901px rules further down, which is also where
   .nav-more turns from "invisible wrapper" (its links just sit inline in
   this same list) into an actual "More" popover menu. */
.nav-links {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: absolute;
  top: 76px;
  left: 0;
  right: 0;
  background: var(--surface);
  border-bottom: 2px solid var(--ink);
  padding: 10px;
  opacity: 0;
  transform: translateY(-8px);
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0.2s;
}
.nav-links.open {
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0s;
}
.nav-links a {
  padding: 8px 14px;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink-soft);
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.nav-links a:hover,
.nav-links a[aria-current="page"] {
  color: var(--ink);
  border-color: var(--gold);
}
.nav-links.open a { padding: 14px 16px; border-bottom: 1px solid var(--line); }

/* .nav-more wraps the secondary links (Meet the Team, FAQs, Show Your
   Creations, Student Jobs, plus the hidden Admin/Material Requests
   links). Below 901px it's `display: contents` — invisible as a box, so
   its <a> children just fall inline into .nav-links' own vertical flex
   flow, same as every other link. The "More" button itself is useless
   there (everything's already listed) so it's hidden outright. */
.nav-more { display: contents; }
.nav-more-toggle { display: none; }
.nav-more-menu { display: contents; }

/* 901px+: a real horizontal nav bar instead of the hamburger dropdown —
   enough width for the 4 primary links + a "More" button next to the
   logo and "Reserve a Visit" without crowding. The hamburger itself is
   hidden; js/script.js's toggle listener simply has nothing to open. */
@media (min-width: 901px) {
  .nav-links {
    position: static;
    flex-direction: row;
    align-items: center;
    gap: 2px;
    background: none;
    border-bottom: none;
    padding: 0;
    opacity: 1;
    transform: none;
    visibility: visible;
    pointer-events: auto;
  }
  .nav-links a { padding: 8px 12px; }

  .nav-more { display: block; position: relative; }
  .nav-more-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    padding: 8px 12px;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.92rem;
    color: var(--ink-soft);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: color 0.15s ease, border-color 0.15s ease;
  }
  .nav-more-toggle span { transition: transform 0.15s ease; }
  .nav-more-toggle:hover,
  .nav-more.open .nav-more-toggle {
    color: var(--ink);
    border-color: var(--gold);
  }
  .nav-more.open .nav-more-toggle span { transform: rotate(180deg); }

  .nav-more-menu {
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 210px;
    background: var(--surface);
    border: 1px solid var(--ink);
    border-radius: var(--radius-sm);
    padding: 8px;
    box-shadow: var(--shadow);
    opacity: 0;
    transform: translateY(-6px);
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.15s ease, transform 0.15s ease, visibility 0s linear 0.15s;
  }
  .nav-more.open .nav-more-menu {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.15s ease, transform 0.15s ease, visibility 0s linear 0s;
  }
  .nav-more-menu a {
    padding: 10px 14px;
    border-radius: var(--radius-sm);
    border-bottom: none;
    white-space: nowrap;
  }
  .nav-more-menu a:hover,
  .nav-more-menu a[aria-current="page"] {
    background: var(--paper-alt);
  }
}

.nav-actions { display: flex; align-items: center; gap: 10px; }

/* Person-icon link to profile.html next to the hamburger toggle — shown
   only when signed in (see updateNavLinks() in js/booking-utils.js). A
   circular outline button rather than a text link/.btn so it stays
   compact next to "Reserve a Visit" at every width, including the
   narrow phone sizes where the Reserve button itself is hidden (see the
   max-width:340px rule below). */
.nav-profile-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid var(--line);
  color: var(--ink);
  background: var(--surface);
  transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.nav-profile-btn:hover,
.nav-profile-btn[aria-current="page"] {
  border-color: var(--gold);
  color: var(--gold-dark);
  background: var(--paper-alt);
}

.nav-toggle {
  display: block;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
}
.nav-toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--ink);
  margin: 5px 0;
  transition: transform 0.25s ease, opacity 0.2s ease;
}
/* script.js sets aria-expanded on this button as it toggles the menu —
   reused here instead of a second class, so the icon and the menu's open
   state can never drift out of sync with each other. */
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Placed after the base .nav-toggle rule above (not inside the earlier
   901px block) so it actually wins the cascade — same selector, same
   specificity, so source order decides, and this needs to be last. */
@media (min-width: 901px) {
  .nav-toggle { display: none; }
}

/* ---------------- Hero ---------------- */
.hero {
  padding: 72px 0 88px;
  border-bottom: 1px solid var(--line);
}
.hero .container {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 56px;
  align-items: center;
}
@media (max-width: 900px) {
  .hero .container { grid-template-columns: 1fr; }
}
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink-soft);
  margin-bottom: 20px;
  padding-bottom: 2px;
  border-bottom: 2px solid var(--gold);
}
.hero-badge .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #2e7d32;
}
.hero-badge .dot.is-closed {
  background: #b23b2e;
}
.hero h1 { margin-bottom: 20px; }
.hero .lead { font-size: 1.12rem; max-width: 46ch; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 28px; }

.hero-visual {
  position: relative;
  border: 1px solid var(--line);
  overflow: hidden;
  aspect-ratio: 4/3.1;
}
.hero-visual img {
  width: 100%; height: 100%; object-fit: cover;
}
.hero-visual-caption {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--ink);
  color: #fff; font-family: var(--font-display); font-weight: 600; font-size: 0.85rem;
  padding: 10px 16px;
}

/* ---------------- Sections ---------------- */
section { padding: 80px 0; }
.section-alt { background: var(--paper-alt); }
.section-head {
  max-width: 640px;
  margin: 0 auto 44px;
  text-align: center;
}
.section-head.left { margin: 0 0 44px; text-align: left; }

/* ---------------- Feature list (replaces boxed-icon cards) ---------------- */
.feature-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  border: 1px solid var(--line);
}
.feature-list .feature {
  padding: 30px 26px;
  border-left: 1px solid var(--line);
  transition: background 0.2s ease;
}
.feature-list .feature:hover {
  background: var(--paper-alt);
}
.feature-list .feature:first-child { border-left: none; }
.feature .feature-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--gold-dark);
  margin-bottom: 14px;
  display: block;
}
.feature h3 { font-size: 1.02rem; margin-bottom: 8px; }
.feature p { margin: 0; font-size: 0.92rem; }
@media (max-width: 900px) {
  .feature-list { grid-template-columns: repeat(2, 1fr); }
  .feature-list .feature:nth-child(2n+1) { border-left: none; }
  .feature-list .feature:nth-child(-n+2) { border-bottom: 1px solid var(--line); }
}
@media (max-width: 560px) {
  .feature-list { grid-template-columns: 1fr; }
  .feature-list .feature { border-left: none !important; border-bottom: 1px solid var(--line); }
  .feature-list .feature:last-child { border-bottom: none; }
}

/* ---------------- Generic card grid (still used on a few pages) ---------------- */
.grid { display: grid; gap: 20px; }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 980px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } .grid-3 { grid-template-columns: repeat(2,1fr); } }
@media (max-width: 620px) { .grid-4, .grid-3, .grid-2 { grid-template-columns: 1fr; } }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-sm);
  border-color: var(--gold);
}
/* Forms/inputs shouldn't lift on hover — that's a card-as-content pattern,
   not a card-as-container-for-a-form pattern. */
form.card:hover, .info-card:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--line);
}
.card .icon { font-size: 1.6rem; margin-bottom: 14px; display: block; }
.card h3 { margin-bottom: 8px; }
.card p { margin: 0; font-size: 0.95rem; }

/* ---------------- Equipment cards ---------------- */
.equip-search { margin-bottom: 16px; }
.equip-search input {
  width: 100%;
  max-width: 420px;
  box-sizing: border-box;
  font-family: var(--font-body);
  font-size: 0.95rem;
  padding: 11px 16px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--line);
  background: var(--surface);
  color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.equip-search input:focus { border-color: var(--gold); outline: none; box-shadow: 0 0 0 3px rgba(172, 145, 95, 0.22); }

.equip-toolbar {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: 32px;
}
.chip {
  border: 1.5px solid var(--ink);
  background: var(--surface);
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 0.86rem;
  font-weight: 600;
  cursor: pointer;
  color: var(--ink);
  transition: all 0.15s ease;
}
.chip.active { background: var(--ink); color: #fff; }

/* Admin page section tabs (admin.html) — one per panel (Reports,
   Machines, Admins, …), swapped by js/admin-tabs.js. Deliberately
   distinct from .chip (used for the small filter toggles WITHIN a
   panel, like "Working/Down") so the two levels of navigation stay
   visually distinguishable rather than blending together. */
.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.admin-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  padding: 10px 14px;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
  white-space: nowrap;
}
.admin-tab:hover { color: var(--ink); background: var(--paper-alt); }
.admin-tab[aria-selected="true"] {
  color: var(--ink);
  border-bottom-color: var(--gold);
}
/* The count text itself (e.g. " (3 in the last 24h)") is set by
   js/admin.js the same plain way as the quick-link badges above this
   bar — just bumped to the tab's own font-weight here so it doesn't
   look like a stray fragment sitting in a tab. */
.admin-tab span:not([hidden]) { font-weight: 700; }
@media (max-width: 700px) {
  .admin-tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* Switching tabs toggles .admin-panel's `hidden` attribute (see
   js/admin-tabs.js) — this just gives the panel that becomes visible a
   brief fade+rise instead of snapping into place. Re-triggers every
   time, since removing/reapplying `hidden` is what un-matches and
   re-matches :not([hidden]) in the first place. */
@keyframes admin-panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: no-preference) {
  .admin-panel:not([hidden]) { animation: admin-panel-in 0.25s ease; }
}

/* Signed-in-as + Sign out sit above the sidebar/content layout at every
   width (not inside the sidebar itself — that's just for the tools and
   section list below it). */
.admin-topbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 28px;
}
.admin-signed-in-as { font-size: 0.92rem; color: var(--text-muted); }

.admin-quicklinks { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 32px; }
.admin-sidebar-divider { display: none; }

/* 960px+: the quick-links and section tabs become a persistent left
   sidebar instead of a button row + a horizontally-scrolling tab bar —
   below this width everything is exactly what it was before (same
   classes, this rule block just doesn't apply), so nothing about the
   already-tested phone/tablet layout changes. */
@media (min-width: 960px) {
  .admin-layout { display: flex; align-items: flex-start; gap: 40px; }
  .admin-sidebar {
    width: 240px;
    flex-shrink: 0;
    position: sticky;
    top: 100px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .admin-main { flex: 1; min-width: 0; }

  .admin-quicklinks { flex-direction: column; flex-wrap: nowrap; gap: 2px; margin-bottom: 0; }
  .admin-side-link {
    justify-content: flex-start;
    width: 100%;
    text-align: left;
    background: none;
    border-color: transparent;
    color: var(--ink-soft);
    padding: 10px 12px;
    transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
  }
  .admin-side-link:hover { background: var(--paper-alt); color: var(--ink); transform: translateX(2px); }

  .admin-sidebar-divider { display: block; height: 1px; background: var(--line); margin: 12px 4px; }

  .admin-tabs {
    flex-direction: column;
    flex-wrap: nowrap;
    overflow-x: visible;
    gap: 2px;
    padding-bottom: 0;
    border-bottom: none;
  }
  .admin-tab {
    width: 100%;
    justify-content: flex-start;
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    border-bottom: none;
    border-left: 3px solid transparent;
    margin-bottom: 0;
    padding: 10px 14px 10px 11px;
  }
  .admin-tab:hover { transform: translateX(2px); }
  .admin-tab[aria-selected="true"] {
    border-bottom-color: transparent;
    border-left-color: var(--gold);
    background: var(--paper-alt);
  }
}

.equip-card[data-machine] { cursor: pointer; }
.equip-card[data-machine]:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.equip-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex; flex-direction: column;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.equip-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-sm);
  border-color: var(--gold);
}
.equip-card .equip-media img {
  transition: transform 0.35s ease;
}
.equip-card:hover .equip-media img {
  transform: scale(1.04);
}
.equip-card .equip-media {
  aspect-ratio: 16/11;
  background: var(--paper-alt);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 2.2rem;
}
.equip-card .equip-media img { width: 100%; height: 100%; object-fit: cover; }
.equip-body { padding: 18px 20px 22px; flex: 1; display: flex; flex-direction: column; }
.equip-tag {
  align-self: flex-start;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--gold-dark);
  margin-bottom: 8px;
}
.equip-body h3 { font-size: 1.02rem; margin-bottom: 6px; }
.equip-body p { font-size: 0.87rem; flex: 1; }

/* Items marked "no photo needed" from Admin > Edit Page Content (a tour,
   a small item not worth a picture, etc. — see js/page-content.js and
   api/admin/content.php's hide-photo action). Drops the whole photo
   area rather than showing an empty or broken image slot, so the card
   just reads as a name and description. */
.equip-card.no-photo .equip-media { display: none; }
.equip-card.no-photo .equip-body { padding-top: 22px; }

/* team.html — staff/student roster cards (js/team.js). Centered,
   circular headshot rather than equip-card's full-width photo, since
   this is a person, not a piece of equipment. */
.team-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px 22px;
  text-align: center;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.team-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-sm); border-color: var(--gold); }
.team-avatar {
  width: 96px;
  height: 96px;
  margin: 0 auto 16px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--paper-alt);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
}
.team-avatar img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.35s ease; }
.team-card:hover .team-avatar img { transform: scale(1.06); }
.team-avatar-placeholder { font-size: 2.4rem; }
.team-card h3 { font-size: 1.08rem; margin-bottom: 2px; }
.team-title { font-size: 0.88rem; font-weight: 600; color: var(--gold-dark); margin-bottom: 2px; }
.team-major { font-size: 0.85rem; color: var(--text-muted); margin-bottom: 10px; }
.team-tags { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-bottom: 10px; }
.team-tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(172, 145, 95, 0.14);
  color: var(--gold-dark);
}
.team-bio { font-size: 0.86rem; color: var(--text); margin: 0; text-align: left; }
.equip-spec {
  font-size: 0.78rem;
  color: var(--text-muted);
  border-top: 1px solid var(--line);
  margin-top: 12px;
  padding-top: 10px;
}

/* ---------------- CTA banner — white, bordered, no glow ---------------- */
.cta-banner {
  background: var(--paper);
  border: 1px solid var(--ink);
  border-top: 4px solid var(--gold);
  padding: 52px;
}
.cta-banner h2 { color: var(--ink); }
.cta-banner p { color: var(--text-muted); }

/* ---------------- Steps ---------------- */
.steps { display: grid; gap: 16px; }
.step {
  display: flex; gap: 18px; align-items: flex-start;
  border: 1px solid var(--line);
  padding: 22px 24px;
}
.step-num {
  flex-shrink: 0;
  width: 34px; height: 34px;
  border: 2px solid var(--ink);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* ---------------- Footer — light, matches rest of site ---------------- */
.site-footer {
  background: var(--paper-alt);
  color: var(--text-muted);
  border-top: 2px solid var(--ink);
  padding: 56px 0 24px;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 32px;
  padding-bottom: 36px;
  border-bottom: 1px solid var(--line);
}
@media (max-width: 760px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
.footer-brand img { height: 28px; margin-bottom: 14px; }
.footer-brand p { color: var(--text-muted); font-size: 0.9rem; max-width: 30ch; }
.footer-col h4 {
  font-family: var(--font-display);
  color: var(--ink); font-size: 0.82rem;
  text-transform: uppercase; letter-spacing: 0.08em;
  margin-bottom: 14px;
}
.footer-col a {
  display: block;
  color: var(--text-muted);
  font-size: 0.92rem;
  margin-bottom: 11px;
  transition: color 0.15s ease;
}
.footer-col a:hover { color: var(--ink); }
.footer-bottom {
  display: flex; justify-content: space-between; align-items: center;
  padding-top: 22px;
  font-size: 0.8rem;
  color: var(--text-muted);
  flex-wrap: wrap; gap: 12px;
}
.social-icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 1.5px solid var(--ink);
  display: flex; align-items: center; justify-content: center;
}

/* ---------------- Page hero (interior pages) ---------------- */
.page-hero {
  padding: 56px 0 48px;
  background: var(--paper-alt);
  border-bottom: 1px solid var(--line);
  text-align: center;
}
.page-hero .eyebrow { justify-content: center; }
.page-hero p { max-width: 60ch; margin: 0 auto; }

/* ---------------- FAQ accordion ---------------- */
.accordion { display: grid; gap: 10px; max-width: 800px; margin: 0 auto; }
.accordion-item {
  background: var(--surface);
  border: 1px solid var(--line);
  overflow: hidden;
}
.accordion-item.open { border-color: var(--ink); }
.accordion-q {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  background: none; border: none; cursor: pointer;
  padding: 18px 22px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--text);
  text-align: left;
}
.accordion-q .plus {
  flex-shrink: 0;
  width: 24px; height: 24px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.2rem;
  color: var(--gold-dark);
  transition: transform 0.2s ease;
}
.accordion-item.open .accordion-q .plus { transform: rotate(45deg); color: var(--ink); }
.accordion-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
  padding: 0 22px;
}
.accordion-item.open .accordion-a { padding-bottom: 18px; }
.accordion-a p { font-size: 0.94rem; }

/* ---------------- Contact / forms ---------------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 48px;
}
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; } }

.info-card {
  border: 1px solid var(--line);
  padding: 20px 22px;
  display: flex; gap: 16px;
  margin-bottom: 14px;
}
.info-card .icon { font-size: 1.3rem; }
.info-card h4 { margin-bottom: 4px; font-family: var(--font-display); font-size: 0.98rem; }
.info-card p { margin: 0; font-size: 0.92rem; }

/* Admin panel lists (Machines, Activity Log) — long lists shouldn't push
   the whole page height, so these scroll in place after ~3 rows instead.
   320px is an approximation (rows vary a bit in height), not an exact
   fit — a partial next card peeking over the edge is a deliberate cue
   that there's more to scroll to. */
.scroll-list {
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 14px 10px 0 14px;
}
.scroll-list .info-card:last-child { margin-bottom: 14px; }

/* Reserve a Machine's calendar view — month grid, day cells clickable
   unless past/weekend/blacked-out. Deliberately plain (a count badge,
   not per-machine color-coding) since there are too many machines for
   distinct colors to stay legible. */
.reserve-calendar {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
.cal-day {
  aspect-ratio: 1/1;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 8px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  font-size: 0.85rem;
  background: var(--surface);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.cal-day:hover { border-color: var(--gold); }
.cal-day[role="button"]:focus-visible { outline: 2px solid var(--gold-dark); outline-offset: 2px; }
.cal-day.is-today { border-color: var(--gold-dark); border-width: 2px; }
.cal-day.is-disabled {
  cursor: default;
  color: var(--text-muted);
  background: var(--paper-alt);
}
.cal-day.is-disabled:hover { border-color: var(--line); }
.cal-day.is-blackout { background: rgba(178, 59, 46, 0.06); }
.cal-day .cal-day-num { font-family: var(--font-display); font-weight: 700; }
.cal-day .cal-day-count { font-size: 0.72rem; color: var(--gold-dark); font-weight: 600; }
.cal-day.is-disabled .cal-day-count { color: var(--text-muted); }
.cal-day-blank { visibility: hidden; }

/* Generic modal — backdrop + centered panel. Not calendar-specific;
   reusable anywhere else a popup is needed later. Opened/closed via the
   `hidden` attribute (see js/reserve.js), so :not([hidden]) re-triggers
   the entrance animation every time it opens, same pattern as the admin
   panel fade-in above. */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(35, 31, 32, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 1000;
}
@media (prefers-reduced-motion: no-preference) {
  @keyframes modal-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes modal-in {
    from { opacity: 0; transform: translateY(10px) scale(0.98); }
    to { opacity: 1; transform: translateY(0) scale(1); }
  }
  .modal-backdrop:not([hidden]) { animation: modal-backdrop-in 0.15s ease; }
  .modal-backdrop:not([hidden]) .modal { animation: modal-in 0.2s ease; }
}
.modal {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 28px;
  max-width: 440px;
  width: 100%;
  max-height: 88vh;
  overflow-y: auto;
}
.modal-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  color: var(--text-muted);
  padding: 4px;
}
.modal-close:hover { color: var(--ink); }

.access-list { display: grid; gap: 12px; margin-top: 8px; }
/* Not display:flex — an <li> with any nested inline tag (e.g. a <strong>
   in one line's wording) would otherwise split into several flex items
   side by side, one per text run, instead of reading as one sentence.
   A dash via ::before + padding-left gets the same look without that
   trap, for this list or any nested markup added to it later. */
.access-list li { list-style: none; position: relative; padding-left: 24px; font-size: 0.93rem; color: var(--text-muted); }
.access-list li::before { content: "—"; position: absolute; left: 0; top: 0; color: var(--gold-dark); font-weight: 700; }

form.card { display: grid; gap: 16px; border: 1px solid var(--line); }
/* A little more breathing room between fields than the default form.card
   gap — this form is short (just email/password) so the fields read as
   cramped at the default spacing in a way a longer form doesn't. */
#admin-auth-form { gap: 22px; }
.field { display: grid; gap: 6px; }
.field label { font-size: 0.84rem; font-weight: 600; color: var(--ink-soft); }
.field input,
.field textarea,
.field select {
  font-family: var(--font-body);
  font-size: 0.95rem;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--text);
  resize: vertical;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(172, 145, 95, 0.22);
}

/* Searchable machine picker (js/machine-picker.js) — a custom combobox
   layered on top of a real (now visually hidden) <select>, so typing
   filters instead of scrolling a long native dropdown. */
.machine-picker { position: relative; }
.machine-picker-input {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--font-body);
  font-size: 0.95rem;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--text);
}
.machine-picker-input:focus { outline: none; border-color: var(--gold); }
.machine-picker-list {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 260px;
  overflow-y: auto;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.machine-picker-option {
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.92rem;
  color: var(--text);
  cursor: pointer;
}
.machine-picker-option.is-highlighted { background: var(--paper-alt); }
.machine-picker-option.is-disabled { color: var(--text-muted); cursor: not-allowed; }
.machine-picker-empty { padding: 10px 12px; font-size: 0.88rem; color: var(--text-muted); }
.form-note { font-size: 0.82rem; color: var(--text-muted); }
.form-note.is-error { color: #b23b2e; font-weight: 600; }
.form-success {
  display: none;
  border: 1px solid var(--ink);
  border-left: 4px solid var(--gold);
  color: var(--ink);
  padding: 14px 18px;
  font-size: 0.92rem;
  font-weight: 600;
}
.form-success.show { display: block; }
@media (prefers-reduced-motion: no-preference) {
  @keyframes form-success-in {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: translateY(0); }
  }
  .form-success.show { animation: form-success-in 0.3s ease; }
}

/* ---------------- Legal pages ---------------- */
.legal-content {
  max-width: 820px;
  margin: 0 auto;
}
.legal-content h2 { margin-top: 2em; font-size: 1.25rem; }
.legal-content h2:first-child { margin-top: 0; }
.legal-content ul { color: var(--text-muted); padding-left: 1.2em; }
.legal-content li { margin-bottom: 0.6em; }
.legal-content p { color: var(--text-muted); }
.legal-content strong { color: var(--text); }

/* ---------------- Misc ---------------- */
.badge-list { display: flex; flex-wrap: wrap; gap: 8px; }
.badge-pill {
  border: 1px solid var(--line);
  padding: 9px 16px;
  border-radius: 999px;
  font-size: 0.86rem;
  font-weight: 600;
}

.status-pill {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1.5px solid var(--ink);
  padding: 8px 16px;
  font-weight: 700;
  font-size: 0.85rem;
}
.status-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: #2e7d32; }

.gallery-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 760px) { .gallery-grid { grid-template-columns: repeat(2,1fr); } }
@media (max-width: 480px) { .gallery-grid { grid-template-columns: 1fr; } }
.gallery-item {
  aspect-ratio: 1/1;
  background: var(--paper-alt);
  display: flex; align-items: center; justify-content: center;
  font-size: 2.2rem;
  border: 1px solid var(--line);
  position: relative;
  overflow: hidden;
}
.gallery-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-item .gallery-caption {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.72), rgba(0,0,0,0));
  color: #fff;
  padding: 24px 10px 8px;
  font-size: 0.78rem;
  line-height: 1.3;
}

/* View-only admins see every admin screen, but any control that would
   let them add/edit/delete something is hidden — the actual boundary is
   server-side (require_full_admin() in includes/auth.php); this is just
   so they aren't shown a button that will only ever 403. */
body.view-only-admin [data-requires-full-admin] { display: none !important; }

.committee-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 900px) { .committee-grid { grid-template-columns: repeat(2,1fr); } }
@media (max-width: 600px) { .committee-grid { grid-template-columns: 1fr; } }

.divider { height: 1px; background: var(--line); margin: 56px 0; border: none; }

/* ---------------- Reservation embed ---------------- */
.reserve-frame-wrap {
  border: 1px solid var(--ink);
  background: var(--paper-alt);
}
.reserve-frame-wrap iframe {
  width: 100%;
  min-height: 720px;
  border: 0;
  display: block;
  background: #fff;
}
.reserve-placeholder {
  min-height: 420px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 48px 24px;
  gap: 14px;
}
.reserve-placeholder .icon { font-size: 2.4rem; }

/* ---------------- Down-for-maintenance overlay ---------------- */
.equip-card.is-down .equip-media { position: relative; }
.equip-card.is-down .equip-media img {
  filter: grayscale(1) brightness(0.55);
}
.equip-card.is-down .down-flag {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.equip-card.is-down .down-flag span {
  background: var(--ink);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 8px 18px;
  border: 1.5px solid #fff;
}
.equip-card.is-down .equip-tag { color: #b23b2e; }
.equip-qty {
  align-self: flex-start;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  border: 1px solid var(--line);
  padding: 2px 8px;
  border-radius: 999px;
  margin-bottom: 8px;
  margin-left: 8px;
}

.skip-link {
  position: absolute; left: -999px; top: 0;
  background: var(--ink); color: #fff; padding: 12px 20px; z-index: 200;
}
.skip-link:focus { left: 0; }

/* ---------------- Motion ----------------
   Everything in here is skipped entirely for visitors who've told their
   OS/browser they want reduced motion — this isn't decorative-only,
   scroll-triggered animation can genuinely cause discomfort for some
   people, so prefers-reduced-motion isn't optional here. */
@media (prefers-reduced-motion: no-preference) {
  /* js/script.js adds .reveal to each <section> in <main> (skipping the
     first one — the hero/page-hero — which fades in immediately below
     instead of waiting for a scroll trigger) and adds .is-visible via
     IntersectionObserver the first time it scrolls into view. */
  .reveal {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 0.7s ease, transform 0.7s ease;
  }
  .reveal.is-visible {
    opacity: 1;
    /* `none`, NOT translateY(0): any transform value — even an identity
       one — makes the section the containing block for position:fixed
       children, so the booking modal's backdrop was sized to the whole
       (very tall) section instead of the screen and the dialog landed off
       to the side of / below what the person was looking at. */
    transform: none;
  }

  @keyframes fadeUpIn {
    from { opacity: 0; transform: translateY(18px); }
    to { opacity: 1; transform: translateY(0); }
  }
  .hero, .page-hero {
    animation: fadeUpIn 0.7s ease both;
  }
  .hero-visual {
    animation: fadeUpIn 0.7s ease 0.15s both;
  }
}

/* ---------------- Material request tracker ---------------- */
.mat-request { margin-bottom: 20px; }
.mat-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; align-items: baseline; margin-bottom: 4px; }
.mat-head h3 { margin: 0; }
.mat-meta { font-size: 0.82rem; color: var(--text-muted); margin: 0 0 10px; }
.mat-items { margin: 12px 0 0; padding-left: 18px; font-size: 0.92rem; }
.mat-items li { margin-bottom: 4px; }
.mat-note { margin: 12px 0 0; padding: 10px 12px; border-radius: 10px; background: rgba(172,145,95,0.12); font-size: 0.88rem; }
.mat-badge { display: inline-block; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 8px; border-radius: 6px; background: rgba(172,145,95,0.14); color: var(--gold-dark); }
.mat-badge.done { background: rgba(46,125,50,0.14); color: #2e7d32; }
.mat-badge.cancelled { background: rgba(178,59,46,0.12); color: #b23b2e; }
.mat-item-row { border: 1px solid var(--line); border-radius: 12px; padding: 12px; margin-bottom: 10px; display: grid; gap: 10px; grid-template-columns: 1fr 90px; }
.mat-item-row .wide { grid-column: 1 / -1; }
.mat-item-row .mat-remove { justify-self: start; }

.track { display: flex; list-style: none; margin: 16px 0 4px; padding: 0; }
.track li { flex: 1; position: relative; text-align: center; font-size: 0.78rem; color: var(--text-muted); padding-top: 30px; }
.track li::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--line); z-index: 1;
}
.track li::after {
  content: ""; position: absolute; top: 10px; left: -50%; width: 100%; height: 2px; background: var(--line);
}
.track li:first-child::after { display: none; }
.track li strong { display: block; color: var(--ink); font-size: 0.82rem; }
.track li small { display: block; font-size: 0.72rem; line-height: 1.3; }
.track li.reached::before { background: var(--gold-dark); border-color: var(--gold-dark); }
.track li.reached::after { background: var(--gold-dark); }
.track li.current::before { box-shadow: 0 0 0 4px rgba(172,145,95,0.28); }
.track li:not(.reached) strong { color: var(--text-muted); font-weight: 500; }
@media (max-width: 560px) {
  .track { flex-direction: column; gap: 14px; }
  .track li { text-align: left; padding: 0 0 0 34px; }
  .track li::before { left: 0; transform: none; }
  .track li::after { top: 22px; left: 10px; width: 2px; height: calc(100% + 0px); }
  .track li:first-child::after { display: block; }
  .track li:last-child::after { display: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .track li::before, .track li::after { transition: background 0.3s ease, border-color 0.3s ease; }
}


/* ---------------- Small-screen safety net ----------------
   Found by sweeping every page at 320-414px wide: long unbreakable strings
   (the makerspace@andersonuniversity.edu address) and form controls with
   an intrinsic minimum width (file pickers) stretched their grid/flex
   parents past the screen, so the whole page scrolled sideways. Letting
   text break anywhere, and letting grid children shrink below their
   content, fixes the whole class of problem in one place. */
p, li, a, h1, h2, h3, h4, label, dd, dt, td, th, blockquote, figcaption { overflow-wrap: anywhere; }
.field, .field > *, .card, .info-card > *, .cta-banner > *, .split-cta > * { min-width: 0; }
.field input, .field select, .field textarea { max-width: 100%; }
input[type="file"] { max-width: 100%; }
img, video, iframe { max-width: 100%; }

.split-cta { display: grid; grid-template-columns: 1.3fr 1fr; gap: 40px; align-items: center; }
@media (max-width: 720px) { .split-cta { grid-template-columns: 1fr; gap: 24px; } }

/* Grid children default to min-width:auto (= their content's minimum),
   and a form's text inputs have a ~250px intrinsic minimum — so a
   one-column grid on a 320px phone was wider than the screen. */
[class*="grid"] > *, .contact-grid > * { min-width: 0; }

/* Checkboxes/radios default to ~13px, too small to tap reliably. */
input[type="checkbox"], input[type="radio"] { width: 20px; height: 20px; accent-color: var(--gold-dark); flex-shrink: 0; cursor: pointer; }

/* ---------------- Header on narrow phones ----------------
   Logo + "Reserve a Visit" + menu button ran into each other below ~400px
   (the button overlapped the wordmark). Tighten the header's own spacing
   and shrink the logo/button; below 340px drop the button entirely (the
   menu has a Reserve link too). */
.brand { min-width: 0; flex: 0 1 auto; }
.brand img { max-width: 100%; }
@media (max-width: 480px) {
  .site-header .container { gap: 8px; padding: 0 16px; height: 68px; }
  .brand img { height: 26px; }
  .nav-actions { gap: 6px; flex-shrink: 0; }
  .nav-actions .btn { padding: 9px 13px; font-size: 0.82rem; }
}
@media (max-width: 340px) {
  .nav-actions .btn-primary { display: none; }
}

/* overflow-wrap is inherited: set once on <body> so EVERY text container
   (spans, divs, table cells, status lines — not just the elements listed in
   the safety net above) can break an unbreakably long name or address
   instead of pushing the page wider than the screen. */
body { overflow-wrap: anywhere; }

/* Calendar on small screens: seven columns must be allowed to shrink below
   their content (minmax(0,1fr)) or the month grid was 958px wide on a
   320px phone and dragged the whole page sideways. Tighter cells, and the
   "booked" word drops away leaving just the count. */
.reserve-calendar { grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-day { min-width: 0; overflow: hidden; }
.cal-day .cal-day-count { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 560px) {
  .reserve-calendar { gap: 3px; }
  .cal-day { padding: 4px; font-size: 0.78rem; }
  .cal-day .cal-day-count { font-size: 0.66rem; }
  .cal-day-word { display: none; }
}

.cal-dow { text-align: center; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); padding-bottom: 2px; min-width: 0; }
@media (max-width: 560px) { .cal-dow { font-size: 0.62rem; letter-spacing: 0; } }

/* Breathing room inside the booking modal (fields ran into each other, and
   the submit button sat directly against the reminder checkbox). */
.modal form { display: grid; gap: 14px; }
.modal form .btn-primary { margin-top: 6px; }

/* Admin list rows (users, machines, reservations, waitlist, errors): the
   text block and the action buttons sat side by side with no wrapping, so
   on a phone the buttons ("Make Admin", "Delete") were pushed past the
   edge of the list and cut off. Let each row wrap, and the button group
   too. */
.info-card { flex-wrap: wrap; }
.info-card > div { min-width: 0; }
.info-card > div:last-child:not(:first-child)[style*="display:flex"] { flex-wrap: wrap; }
.info-card > div > div { min-width: 0; }
.scroll-list { overflow-x: hidden; }
@media (max-width: 560px) {
  .scroll-list .info-card > div:last-child:not(:first-child) { width: 100%; }
}

/* Sign-in / create-account form spacing — fields, messages and the resend
   button were stacked with no gaps, so labels touched the box above them. */
#auth-form { display: grid; gap: 16px; margin-top: 14px; }
#auth-signed-out > p { margin: 0 0 12px; }
#auth-signed-out .form-note { margin: 0 0 10px; }
#auth-resend-btn { margin: 0 0 14px; }

/* Large-text / zoom reflow: with the browser's text size at 200% on a
   phone, buttons stayed on one line and grid children kept their content
   width, pushing the page sideways. Let buttons wrap, and let every form
   control shrink to its container. */
.btn { white-space: normal; max-width: 100%; }
select, input, textarea, button { max-width: 100%; }
.hero .container > *, .hero-content, .hero-content > * { min-width: 0; }
h1, h2, h3 { hyphens: manual; }
[style*="flex-wrap"] > * { max-width: 100%; min-width: 0; }
#report-machine, #report-range, #report-from, #report-to { max-width: 100%; }

/* iOS Safari zooms the whole page in when you tap a text field whose font
   is under 16px (these were 15px), and doesn't zoom back out — found by
   trying the sign-in form on an iPhone simulator. 16px is the threshold;
   !important because a few admin fields set their size inline. */
@media (max-width: 900px), (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
  select,
  textarea { font-size: 16px !important; }
}

/* Notch / Dynamic Island / status bar: with viewport-fit=cover the page
   extends under them, so the sticky header pads itself below the status bar
   (and the sides in landscape) instead of having its top slice hidden while
   scrolling — seen on the iOS 26 Safari simulator. env() is 0 everywhere
   without such a cutout, so this changes nothing on desktop. */
.site-header { padding-top: env(safe-area-inset-top); }
body { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }
.site-footer { padding-bottom: env(safe-area-inset-bottom); }

/* iOS renders <input type="date"> centred and shorter than neighbouring
   fields; left-align it and match the other controls' height. */
input[type="date"], input[type="time"], select { text-align: left; min-height: 46px; }
input[type="date"]::-webkit-date-and-time-value { text-align: left; }

/* Admin sign-in form: same spacing as the member sign-in form. */
#admin-auth-form { display: grid; gap: 16px; margin-top: 16px; }

/* "Had an account on our old website?" callout on the sign-in cards */
.legacy-note {
  background: var(--paper-alt);
  border-left: 4px solid var(--gold);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  margin: 0 0 18px;
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--text);
}
.legacy-note a { color: var(--gold-dark); font-weight: 600; text-decoration: underline; }
