/* Skipton AC Portal - minimal shared stylesheet.
   Self-hosted (served by WhiteNoise) rather than a CDN, and no inline
   <style>/style="" anywhere in the templates, per the CSP in
   config/settings/base.py (style-src 'self', no unsafe-inline). */

:root {
  --colour-text: #1a1a1a;
  --colour-muted: #5a5a5a;
  --colour-bg: #ffffff;
  --colour-bg-alt: #f4f5f7;
  --colour-border: #d7d9dd;
  /* Skipton AC's brand blue, as confirmed from skiptonac.co.uk's theme
     stylesheet, is #0D85CC. Used directly here would only give ~4.0:1
     contrast against white (fails WCAG AA's 4.5:1 for normal text -
     APPLICATION_SPEC.md #36 "adequate contrast" - for header/nav text,
     links, and button labels, all of which use this colour). --colour-primary
     is therefore a darkened shade of the same hue (~5.6:1 against white)
     so it still reads as "the club blue" while meeting that requirement.
  */
  --colour-primary: #0a6ea3;
  --colour-primary-contrast: #ffffff;
  --colour-danger: #9b1c1c;
  --colour-success: #1e6b3c;
  --colour-warning: #92400e;
  --focus-ring: #0a6ea3;
  /* Reused everywhere a rounded corner or drop shadow appears, so the
     whole app reads as one consistent visual language rather than each
     component picking its own radius/elevation. */
  --radius: 0.375rem;
  --radius-sm: 0.25rem;
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 8px 24px rgba(15, 23, 42, 0.12);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--colour-text);
  background: var(--colour-bg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: var(--colour-primary);
  transition: color 0.15s ease, opacity 0.15s ease;
}

:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* --focus-ring is the same blue as .site-header's background - without
   this, a keyboard-focused link sitting directly on that background
   would get an outline the same colour as what it's on and effectively
   disappear (APPLICATION_SPEC.md #36 "clear focus state"). Scoped to
   just the items that actually sit on the blue bar itself - the
   dropdown popovers below it are white, where the default blue outline
   already contrasts fine. */
.site-nav > .brand:focus-visible,
.site-nav > ul > li > a:focus-visible,
.site-nav > ul > li > details > summary:focus-visible {
  outline-color: var(--colour-primary-contrast);
}

h1, h2, h3 {
  line-height: 1.25;
  font-weight: 700;
  margin: 0 0 0.75rem;
  letter-spacing: -0.01em;
}

h1 { font-size: 1.75rem; }
h2 { font-size: 1.35rem; margin-top: 2rem; }
h3 { font-size: 1.1rem; margin-top: 1.5rem; }

p { margin: 0 0 1rem; }

.site-header {
  background: var(--colour-primary);
  color: var(--colour-primary-contrast);
  box-shadow: var(--shadow-sm);
  position: relative;
  z-index: 20;
}

.site-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.85rem 1rem;
}

.site-nav .brand {
  color: var(--colour-primary-contrast);
  font-weight: 700;
  text-decoration: none;
  font-size: 1.15rem;
  letter-spacing: -0.01em;
}

.site-nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  align-items: center;
}

.site-nav a, .site-nav .link-button {
  color: var(--colour-primary-contrast);
  text-decoration: none;
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.6rem;
  opacity: 0.9;
}

.site-nav a:hover, .site-nav .link-button:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.12);
  text-decoration: none;
}

.site-nav a[aria-current="page"] {
  opacity: 1;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.16);
}

/* Native <details>/<summary> dropdown - no JS needed, keyboard-accessible
   (Tab to focus, Enter/Space to toggle) by default. */
.nav-dropdown {
  position: relative;
}

.nav-dropdown summary {
  cursor: pointer;
  list-style: none;
  color: var(--colour-primary-contrast);
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.6rem;
  opacity: 0.9;
  transition: opacity 0.15s ease, background 0.15s ease;
}

.nav-dropdown summary::-webkit-details-marker {
  display: none;
}

.nav-dropdown summary:hover,
.nav-dropdown[open] summary {
  opacity: 1;
  background: rgba(255, 255, 255, 0.12);
}

.nav-dropdown summary[aria-current="page"] {
  opacity: 1;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.16);
}

.nav-dropdown summary::after {
  content: "\25BE";
  margin-left: 0.35rem;
  font-size: 0.7em;
  vertical-align: 1px;
}

.nav-dropdown[open] summary::after {
  content: "\25B4";
}

.nav-dropdown > ul {
  display: none;
}

.nav-dropdown[open] > ul {
  display: block;
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 10;
  min-width: 12rem;
  margin: 0;
  padding: 0.4rem 0;
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  animation: nav-dropdown-in 0.12s ease-out;
}

@keyframes nav-dropdown-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.nav-dropdown > ul li {
  display: block;
}

.nav-dropdown > ul a,
.nav-dropdown > ul .link-button {
  display: block;
  padding: 0.5rem 1rem;
  color: var(--colour-text);
  white-space: nowrap;
  text-align: left;
  width: 100%;
  opacity: 1;
  border-radius: 0;
}

.nav-dropdown > ul a:hover,
.nav-dropdown > ul .link-button:hover {
  background: var(--colour-bg-alt);
  opacity: 1;
  text-decoration: none;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

.site-main {
  max-width: 48rem;
  margin: 0 auto;
  padding: 2rem 1rem 3rem;
}

label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.35rem;
  font-size: 0.925rem;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="search"],
textarea,
select {
  width: 100%;
  max-width: 28rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-sm);
  font: inherit;
  background: var(--colour-bg);
  color: var(--colour-text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input[type="text"]:hover,
input[type="email"]:hover,
input[type="password"]:hover,
input[type="search"]:hover,
textarea:hover,
select:hover {
  border-color: var(--colour-muted);
}

input[type="text"]:focus-visible,
input[type="email"]:focus-visible,
input[type="password"]:focus-visible,
input[type="search"]:focus-visible,
textarea:focus-visible,
select:focus-visible {
  border-color: var(--focus-ring);
  box-shadow: 0 0 0 3px rgba(10, 110, 163, 0.15);
}

button,
input[type="submit"],
a.button {
  display: inline-block;
  padding: 0.55rem 1.1rem;
  background: var(--colour-primary);
  color: var(--colour-primary-contrast);
  border: 1px solid var(--colour-primary);
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
}

button:hover, input[type="submit"]:hover, a.button:hover {
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  filter: brightness(1.08);
}

button:active, input[type="submit"]:active, a.button:active {
  transform: translateY(1px);
}

button.secondary, a.button.secondary {
  background: var(--colour-bg);
  color: var(--colour-primary);
  border-color: var(--colour-border);
}

button.secondary:hover, a.button.secondary:hover {
  background: var(--colour-bg-alt);
  border-color: var(--colour-primary);
  filter: none;
}

button.danger, a.button.danger {
  background: var(--colour-danger);
  color: var(--colour-primary-contrast);
  border-color: var(--colour-danger);
}

button.danger:hover, a.button.danger:hover {
  box-shadow: var(--shadow-sm);
  filter: brightness(1.1);
}

table {
  width: 100%;
  border-collapse: collapse;
  margin: 1rem 0;
  font-size: 0.95rem;
}

th, td {
  text-align: left;
  padding: 0.6rem 0.7rem;
  border-bottom: 1px solid var(--colour-border);
}

th {
  background: var(--colour-bg-alt);
  font-weight: 600;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--colour-muted);
}

tbody tr {
  transition: background 0.1s ease;
}

tbody tr:hover {
  background: var(--colour-bg-alt);
}

.messages {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Bare (not nested under .messages) so every static callout that reuses
   these two classes together on one element - <p class="messages
   message">, a handful of these across the app - actually gets this
   box styling too, not just the real toast <li>s below. */
.message {
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-sm);
  margin-bottom: 0;
  background: var(--colour-bg-alt);
  border: 1px solid var(--colour-border);
  border-left-width: 4px;
}

.message.success {
  border-color: var(--colour-success);
  border-left-color: var(--colour-success);
  background: #eaf5ee;
}

.message.error {
  border-color: var(--colour-danger);
  border-left-color: var(--colour-danger);
  background: #fbecec;
}

.message.warning {
  border-color: var(--colour-warning);
  border-left-color: var(--colour-warning);
  background: #fdf3e3;
}

.message.info {
  border-color: var(--colour-primary);
  border-left-color: var(--colour-primary);
  background: #eaf3fa;
}

/* Real toast notifications (templates/base.html's Django-messages loop)
   only - a floating, positioned, animated, dismissable overlay. Layered
   on top of the shared .message box styling above via an additional
   class, never by hijacking .messages/.message themselves, since those
   two are also reused elsewhere as permanent inline callouts that must
   never float or auto-dismiss. */
.toast-container {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: min(24rem, calc(100vw - 2rem));
  list-style: none;
  padding: 0;
  margin: 0;
}

.toast {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  box-shadow: var(--shadow-md);
  animation: toast-in 0.25s ease-out;
}

/* Success/info are transient confirmations - fine to disappear on their
   own. Error/warning often carry something worth actually reading and
   acting on later (e.g. "won't take effect until restart"), so they
   stay until closed rather than vanishing on a timer. */
.toast.success,
.toast.info {
  animation:
    toast-in 0.25s ease-out,
    toast-out 0.3s ease-in 6s forwards;
}

.toast:hover {
  animation-play-state: paused;
}

.toast-close {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  padding: 0;
  color: inherit;
  opacity: 0.6;
  flex-shrink: 0;
}

.toast-close:hover {
  opacity: 1;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateX(1rem); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes toast-out {
  to { opacity: 0; transform: translateX(1rem); pointer-events: none; }
}

@media (max-width: 40rem) {
  .toast-container {
    left: 1rem;
    right: 1rem;
    max-width: none;
  }
}

.badge {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--colour-bg-alt);
  border: 1px solid var(--colour-border);
}

.muted { color: var(--colour-muted); }

/* Flags an under-18 (or age-unknown) attendee's name at a glance
   (events/_event_attendees_table.html) - same red as .badge.error,
   plain text rather than a pill since this sits on a person's name, not
   a short status word. */
.text-danger {
  color: var(--colour-danger);
  font-weight: 600;
}

/* A shield emoji needs no extra sizing on most platforms, but a couple
   of points of left margin keeps it from crowding the column header
   when a row has no other content next to it. */
.guardian-icon {
  margin-left: 0.15rem;
}

.inline-form { display: inline; }

.input-with-button {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.input-with-button input {
  flex: 1 1 auto;
}

.preview-panel {
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  padding: 1.1rem;
  background: var(--colour-bg-alt);
}

.preview-panel pre, .preview-panel code {
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-sm);
}

.preview-panel pre { padding: 0.75rem; overflow-x: auto; }
.preview-panel code { padding: 0.1rem 0.3rem; }

textarea[readonly] { background: var(--colour-bg-alt); }

/* Home dashboard (home.html, on the wide 72rem container): a row of
   single-number tiles, then a row of detail cards. auto-fit (not
   auto-fill) so whichever cards a user's permissions leave stretch to
   fill the row instead of leaving empty slots - four of each across at
   full width, fewer as the window narrows. */
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
}

.dashboard-grid + .dashboard-grid {
  margin-top: 1rem;
}

/* dense: at two columns, a one-column card (Integration Health) fills
   the gap the double-width events card leaves beside Membership
   Summary. The cards are independent, so the visual reorder is safe. */
.dashboard-details {
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  grid-auto-flow: row dense;
}

/* Cards in a row stretch to the tallest - keep each "View all" link
   on the bottom edge rather than floating mid-card. */
.dashboard-details .dashboard-card > a:last-child {
  margin-top: auto;
}

/* A long title wraps onto two lines in some tiles and not others -
   pushing the number and link to the bottom keeps the numbers level. */
.dashboard-stat .dashboard-metric {
  margin-top: auto;
}

/* Only once there's room for two 16rem columns (plus the gap and
   .site-main's 1rem side padding) - spanning two in a one-column grid
   would add a phantom column and overflow. */
@media (min-width: 35rem) {
  .dashboard-card-wide {
    grid-column: span 2;
  }
}

/* Upcoming events as date | title rows, so each fits on one line. */
.dashboard-events {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1rem;
  margin: 0;
}

.dashboard-events dt {
  color: var(--colour-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.dashboard-events dd {
  margin: 0;
}

.dashboard-card {
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  padding: 1.1rem;
  background: var(--colour-bg-alt);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.dashboard-card h2 {
  margin: 0;
  font-size: 0.95rem;
  color: var(--colour-muted);
}

.dashboard-card .dashboard-metric {
  font-size: 2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.dashboard-card ul {
  margin: 0;
  padding-left: 1.1rem;
}

.dashboard-card .dashboard-subheading {
  margin: 0.25rem 0 0;
  font-size: 0.85rem;
}

/* Label/count rows (e.g. Membership Summary's member-type breakdown) -
   label left, count right-aligned, rather than "<count> <label>" prose. */
.dashboard-breakdown {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.2rem 1rem;
  margin: 0;
}

.dashboard-breakdown dt,
.dashboard-breakdown dd {
  margin: 0;
}

.dashboard-breakdown dd {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.badge.enabled {
  border-color: var(--colour-success);
  background: #eaf5ee;
}

.badge.disabled {
  border-color: var(--colour-border);
  color: var(--colour-muted);
}

.badge.error {
  border-color: var(--colour-danger);
  background: #fbecec;
  color: var(--colour-danger);
}

.badge.warning {
  border-color: var(--colour-warning);
  background: #fdf3e3;
  color: var(--colour-warning);
}

.dashboard-card .dashboard-integration-list {
  list-style: none;
  padding-left: 0;
}

.dashboard-integration-list li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.2rem 0;
}

.pagination {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 1.5rem;
}

/* A GET-form search/filter toolbar above a list table (first use: the
   Members page). Overrides the global label/input block-stacking rules
   scoped to just this container, so each field sits in its own compact
   column and the whole row wraps naturally at narrow widths - no media
   query needed, same "let flex-wrap do the responsive work" approach
   already used by .site-nav/.integration-tabs. */
.list-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem 1rem;
  padding: 1rem;
  margin: 1rem 0 1.5rem;
  background: var(--colour-bg-alt);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
}

.list-toolbar .field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0;
}

.list-toolbar label {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--colour-muted);
}

.list-toolbar input,
.list-toolbar select {
  width: auto;
  max-width: none;
}

.list-toolbar .field-search {
  flex: 1 1 13rem;
}

.list-toolbar .field-search input {
  width: 100%;
}

.list-toolbar-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  /* Pins the buttons to the row's trailing edge while there's room,
     and simply drops to its own line once the fields wrap. */
  margin-left: auto;
}

/* Sortable column headers - deliberately NOT the global link colour
   (th already carries its own muted/uppercase treatment; a bare <a>
   would otherwise turn every header bright blue and break the look
   every other table in the app shares). Blue is reserved for the
   column actually being sorted by, so it reads as a state, not noise. */
th a.sort-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: inherit;
  text-decoration: none;
}

th a.sort-link:hover,
th a.sort-link:focus-visible {
  color: var(--colour-primary);
}

th a.sort-link.active {
  color: var(--colour-primary);
}

.sort-arrow {
  font-size: 0.7em;
}

/* Checkbox multi-select (first use: Member Type on the Members page) -
   a native <details>/<summary> disclosure, same "no JS needed to
   open/close" approach as .nav-dropdown above, just styled as a form
   control (bordered box, not the dark nav bar) since it lives inside a
   light .list-toolbar. static/js/list-filters.js only adds the one
   thing <details> can't do on its own: keeping the summary's text in
   sync with which boxes are ticked. */
.multiselect {
  position: relative;
}

.multiselect summary {
  cursor: pointer;
  list-style: none;
  width: auto;
  min-width: 10rem;
  padding: 0.55rem 1.9rem 0.55rem 0.7rem;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-sm);
  background: var(--colour-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%235a5a5a' d='M1 1l5 5 5-5'/%3E%3C/svg%3E") no-repeat right 0.7rem center;
  background-size: 0.7rem;
  transition: border-color 0.15s ease;
}

.multiselect summary::-webkit-details-marker {
  display: none;
}

.multiselect summary:hover {
  border-color: var(--colour-muted);
}

.multiselect[open] summary,
.multiselect summary:focus-visible {
  border-color: var(--focus-ring);
  box-shadow: 0 0 0 3px rgba(10, 110, 163, 0.15);
  outline: none;
}

.multiselect-panel {
  position: absolute;
  top: calc(100% + 0.3rem);
  left: 0;
  z-index: 10;
  min-width: 100%;
  max-height: 16rem;
  overflow-y: auto;
  padding: 0.4rem 0;
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}

.multiselect-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  padding: 0.4rem 0.8rem;
  font-weight: 400;
  font-size: 0.9rem;
  text-transform: none;
  letter-spacing: normal;
  color: var(--colour-text);
  white-space: nowrap;
  cursor: pointer;
}

.multiselect-option:hover {
  background: var(--colour-bg-alt);
}

.multiselect-option input {
  margin: 0;
}

/* Any list-filter results container (static/js/list-filters.js) swaps
   its contents on every instant search/filter tick - a faint dim while a
   request is in flight gives quiet feedback without a spinner. */
.list-results[aria-busy="true"] {
  opacity: 0.6;
  transition: opacity 0.1s ease;
}

.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  max-width: 72rem;
  margin: 2rem auto 0;
  padding: 1rem 1rem 2rem;
  border-top: 1px solid var(--colour-border);
  color: var(--colour-muted);
  font-size: 0.9rem;
}

.site-footer a { color: var(--colour-muted); }

.site-footer-right {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-left: auto;
}

.changelog-entry {
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--colour-border);
}

.changelog-entry:last-child { border-bottom: none; }

.changelog-entry h2 {
  margin-top: 0;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}

.changelog-date {
  font-weight: 400;
  font-size: 0.85rem;
}

.changelog-entry ul { margin: 0.5rem 0 0; padding-left: 1.25rem; }
.changelog-entry li { margin-bottom: 0.3rem; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

fieldset.radio-group {
  border: none;
  padding: 0;
  margin: 0 0 1rem;
}

fieldset.radio-group legend {
  font-weight: 600;
  margin-bottom: 0.25rem;
  padding: 0;
}

fieldset.radio-group label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: 400;
  margin-right: 1.5rem;
}

/* Wider container for pages that need more than one column, or a table/
   toolbar with real room to breathe - opt in via {% block main_class %}
   wide{% endblock %}, everything else keeps the narrower default width
   above unchanged. Matches .site-nav/.site-footer's own 72rem exactly,
   so a wide page's content lines up edge-to-edge with the header/footer
   bars above and below it, instead of reading as narrower than them. */
.site-main.wide { max-width: 72rem; }

/* CSS-only vertical tabs (radio + label + general-sibling selector) -
   this codebase has no JS beyond one clipboard-copy script (see
   templates/base.html's Admin dropdown for the same <details>-based
   philosophy), so a tabbed layout has to work without any script.
   Every input is a plain sibling of .tab-nav/.tab-panels rather than
   nested next to its own label, specifically so the ~ combinator below
   can reach both the matching label (active-tab highlight) and the
   matching panel (visibility) from the same flat structure. */
.integration-tabs {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 2rem;
  margin-top: 1.5rem;
}

.integration-tabs .tab-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.tab-nav {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 0 0 13rem;
}

.tab-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  font-weight: 600;
  color: var(--colour-text);
  transition: background 0.15s ease, border-color 0.15s ease;
}

.tab-label:hover {
  background: var(--colour-bg-alt);
}

.tab-panels {
  flex: 1 1 auto;
  min-width: 0;
}

.tab-panel {
  display: none;
}

.tab-panel h2 {
  margin-top: 0;
}

#tab-wordpress:checked ~ .tab-nav .tab-label[for="tab-wordpress"],
#tab-email:checked ~ .tab-nav .tab-label[for="tab-email"],
#tab-sms:checked ~ .tab-nav .tab-label[for="tab-sms"],
#tab-spond:checked ~ .tab-nav .tab-label[for="tab-spond"] {
  background: var(--colour-bg-alt);
  border-color: var(--colour-border);
  color: var(--colour-primary);
}

#tab-wordpress:focus-visible ~ .tab-nav .tab-label[for="tab-wordpress"],
#tab-email:focus-visible ~ .tab-nav .tab-label[for="tab-email"],
#tab-sms:focus-visible ~ .tab-nav .tab-label[for="tab-sms"],
#tab-spond:focus-visible ~ .tab-nav .tab-label[for="tab-spond"] {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

#tab-wordpress:checked ~ .tab-panels #panel-wordpress,
#tab-email:checked ~ .tab-panels #panel-email,
#tab-sms:checked ~ .tab-panels #panel-sms,
#tab-spond:checked ~ .tab-panels #panel-spond {
  display: block;
}

@media (max-width: 40rem) {
  .integration-tabs {
    flex-direction: column;
    gap: 0.5rem;
  }

  .tab-nav {
    flex-direction: row;
    flex-wrap: wrap;
    flex-basis: auto;
    width: 100%;
  }
}
