/* Base styles. Components build on the tokens in tokens.css. */

*,
*::before,
*::after {
  box-sizing: border-box;
}

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

/* Base link: brand teal in both themes, visited included, so a link in running text never
   falls back to the browser's blue or purple. The underline stays, so a link is never marked
   by colour alone. Buttons and nav links set their own colour and override this. */
a {
  color: var(--fg-brand);
  text-underline-offset: 2px;
}

a:hover {
  color: var(--fg-brand-strong);
}

a:focus-visible {
  outline: none;
  border-radius: 2px;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.landing {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-6);
  text-align: center;
}

/* Matches the "Firaq." wordmark used everywhere else: Plus Jakarta 800, heading colour, teal dot. */
.landing__brand {
  margin: 0;
  font-family: "Plus Jakarta Sans", var(--font-display), sans-serif;
  font-size: var(--text-display-sm);
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--heading);
}

.landing__dot {
  color: var(--fg-brand);
}

.landing__tagline {
  margin: 0;
  color: var(--color-text-muted);
}

/* The two CTAs sit side by side and wrap on a narrow screen — .landing's own 8px column gap
   is a paragraph gap, too tight to read as a pair of buttons. */
.landing__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

/* ---- Theme toggle (fixed, on every page) ---- */
.theme-toggle {
  /* Sits at the top-right of each page, not pinned across scroll — absolute (not fixed)
     positions it against the document's top, so it scrolls away with the page instead of
     staying stuck over content lower down. */
  position: absolute;
  /* top matches .page's own top padding (--space-8), and the 44px box matches .btn's
     height — both so this lines up with a page__header action button (also pinned to
     the header's top edge, see .page__header) instead of floating at its own offset. */
  top: var(--space-8);
  right: var(--space-4);
  z-index: 50;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  color: var(--heading);
  background: var(--neutral-secondary-medium);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  cursor: pointer;
}

.theme-toggle:hover {
  border-color: var(--border-default-strong);
}

.theme-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px var(--focus-ring);
}

/* Show the sun in dark mode (tap to go light), the moon in light mode (tap to go dark). */
.theme-toggle .i-sun {
  display: none;
}

[data-theme="dark"] .theme-toggle .i-sun {
  display: block;
}

[data-theme="dark"] .theme-toggle .i-moon {
  display: none;
}

/* ---- Admin shell: persistent sidebar + content column ---- */
.admin {
  display: flex;
  align-items: stretch;
  min-height: 100dvh;
  position: relative; /* lift the whole subtree above the aurora */
  z-index: 1;
}

.admin__sidebar {
  width: 236px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-6) var(--space-4);
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100dvh;
}

.admin__brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 0 var(--space-2);
  margin-bottom: var(--space-5);
}

/* In the sidebar the toggle is a row item, not a corner overlay — drop the absolute
   positioning base.html's copy relies on. Kept at 44px so the touch target survives. */
.admin__brand .theme-toggle {
  position: static;
  flex-shrink: 0;
}

/* A sidebar row item under the brand: the "Choose active squad" button (Story 26). The plan
   clock that used to sit here moved to Settings > Subscription. */
.admin__trial-badge {
  align-self: flex-start;
  margin: 0 var(--space-2) var(--space-4);
}

.admin-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  /* Flex children default to min-height:auto, which refuses to shrink below its content —
     that's what let the four <details> groups push .admin-nav__footer off-screen once
     expanded. min-height:0 is the actual fix; overflow-y is what it enables. */
  min-height: 0;
}

.admin-nav__footer {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.admin-nav__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 40px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  font-weight: 600;
  font-size: 0.9375rem;
  text-decoration: none;
}

/* Log out is a one-button form (POST + CSRF token). The form adds no box of its own, and the
   button drops the browser's button chrome so it looks like the links around it. */
.logout-form {
  display: contents;
}

button.admin-nav__link {
  width: 100%;
  border: 0;
  background: none;
  font-family: inherit;
  text-align: start;
  cursor: pointer;
}

.admin-nav__link svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.admin-nav__link:hover {
  background: var(--neutral-secondary-strong);
  color: var(--heading);
}

.admin-nav__link.is-active {
  background: var(--brand-soft);
  color: var(--fg-brand);
}

.admin-nav__link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Per-squad Present links live in a collapsible <details> group. The summary reuses the
   nav-link look; its squad links indent under it so they read as children. */
.admin-nav__group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.admin-nav__summary {
  cursor: pointer;
  list-style: none; /* drop the native disclosure triangle; the chevron replaces it */
  /* Lighter weight than .admin-nav__link so a toggle reads differently from a link that
     actually navigates — today they're visually identical. */
  font-weight: 500;
  color: var(--color-text-muted);
}

.admin-nav__summary::-webkit-details-marker {
  display: none;
}

.admin-nav__chevron {
  margin-left: auto;
  transition: transform 0.15s ease;
}

.admin-nav__group[open] .admin-nav__chevron {
  transform: rotate(180deg);
}

.admin-nav__link--sub {
  min-height: 36px;
  padding-left: var(--space-6);
  font-size: 0.875rem;
  font-weight: 500;
}

/* Settings popover: the footer trigger is a full-width nav link that opens a menu upward
   (Slack-style), since it sits at the bottom of the sidebar. */
.admin-nav__menu {
  display: block;
}

.admin-nav__menu .menu__trigger {
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  font-family: inherit; /* only the family — weight/size come from .admin-nav__link */
  text-align: left;
}

.admin-nav__menu .menu__list--up {
  top: auto;
  bottom: calc(100% + 4px);
  left: 0;
  right: 0;
}

.menu__item.is-active {
  background: var(--brand-soft);
  color: var(--fg-brand);
}

.admin__main {
  flex: 1;
  min-width: 0;
}

/* Dashboard forms are desktop admin, not the touch-first member entry/auth forms — so drop
   the 44px touch height and 16px type for a tighter control that doesn't dwarf its label.
   Scoped to .admin__main so signup/login/standup keep their large touch targets. */
.admin__main .field__input {
  min-height: 38px;
  font-size: 0.9375rem;
}

/* Pages inside the shell fill the content column instead of centering in a narrow page. */
.admin__main .page {
  max-width: none;
  margin: 0;
}

/* Narrow screens: the sidebar folds into a scrollable top bar. */
@media (max-width: 860px) {
  .admin {
    flex-direction: column;
  }
  .admin__sidebar {
    width: auto;
    height: auto;
    position: static;
    /* The desktop rule's align-self: flex-start sizes a column-flex child to its content, so
       the bar grew as wide as all its links and the whole page scrolled sideways. Stretch it
       to the screen and let overflow-x scroll the links inside it. */
    align-self: stretch;
    min-width: 0;
    flex-direction: row;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-4);
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    overflow-x: auto;
  }
  .admin__brand {
    margin: 0 var(--space-2) 0 0;
  }
  .admin-nav {
    flex-direction: row;
    /* Top-bar mode scrolls horizontally on .admin__sidebar itself, not vertically here —
       undo the stacked-sidebar overflow fix so it doesn't clip a row layout. */
    overflow-y: visible;
    min-height: auto;
  }
  .admin-nav__footer {
    margin: 0 0 0 auto;
    flex-direction: row;
    padding-top: 0;
    border-top: none;
  }
  .admin-nav__link span {
    white-space: nowrap;
  }
  /* In the horizontal nav each group is a tap-to-expand summary pill (native <details>);
     just tighten the child indent since there's no vertical column to nest under. */
  .admin-nav__link--sub {
    padding-left: var(--space-3);
  }
  /* From the top bar the settings popover has to open downward, not off the top edge. */
  .admin-nav__menu .menu__list--up {
    top: calc(100% + 4px);
    bottom: auto;
    left: auto;
    right: 0;
  }
}

/* ---- Aurora backdrop (mirrors landing) ---- */
/* A fixed field of soft brand + accent blooms behind every page, so screens read as a
   glossy wash instead of a flat slab. Static (no motion) — page backgrounds are transparent
   so it shows through; opaque cards sit above it. */
.aurora {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.aurora::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(42% 42% at 14% 12%, color-mix(in srgb, var(--brand) 26%, transparent), transparent 62%),
    radial-gradient(40% 40% at 84% 28%, color-mix(in srgb, var(--accent-sky) 22%, transparent), transparent 60%),
    radial-gradient(46% 46% at 50% 82%, color-mix(in srgb, var(--accent-cyan) 22%, transparent), transparent 64%);
  filter: blur(72px);
  opacity: 0.9;
}

[data-theme="dark"] .aurora::before {
  opacity: 0.5;
}

/* Content sits above the aurora. */
main {
  position: relative;
  z-index: 1;
}

/* ---- Auth / centered card layout ---- */
.auth-shell {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
}

.card {
  width: 100%;
  /* Card gradient (cards.md): soft top, a barely-visible slate warmth at the bottom. */
  background: linear-gradient(
    180deg,
    var(--neutral-primary-soft) 0%,
    var(--neutral-primary-soft) 55%,
    color-mix(in srgb, var(--neutral-secondary-medium) 14%, var(--neutral-primary-soft)) 82%,
    color-mix(in srgb, var(--neutral-tertiary-medium) 22%, var(--neutral-primary-soft)) 100%
  );
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  box-shadow: var(--shadow-xs);
}

/* Centered auth screens keep a narrow card; cards on full pages fill their container. */
.auth-shell .card {
  max-width: 420px;
}

/* Two cards on the account page (password, then signed-in browsers): stacked and centred
   together, so the second card doesn't float alone in the shell's flex centring. */
.auth-stack {
  width: 100%;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.auth-stack .card {
  max-width: none;
}

.session-list {
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
  display: flex;
  flex-direction: column;
}

.session-list__item {
  padding: var(--space-4) 0;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.session-list__meta {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.session-list__item .btn {
  align-self: flex-start;
  margin-top: var(--space-2);
}

/* A whole .card that's also a link (the past-sprints list) — resets the browser's default
   link color/underline (a .card is otherwise never an <a>, so nothing else does this) and
   adds a hover/focus affordance so it still reads as clickable. */
.card-link {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: box-shadow 0.15s ease;
}

.card-link:hover {
  box-shadow: var(--shadow-md);
}

.card-link:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.card--center {
  text-align: center;
}

/* Brand wordmark — identical to the landing "Firaq." lockup (Plus Jakarta 800, heading color, teal dot). */
.card__eyebrow {
  margin: 0 0 var(--space-2);
  font-family: "Plus Jakarta Sans", var(--font-display), sans-serif;
  font-weight: 800;
  font-size: 1.375rem;
  letter-spacing: -0.03em;
  color: var(--heading);
}

.card__dot {
  color: var(--fg-brand);
}

.card__title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text);
}

/* Brand left, page title pushed to the top-right of the card, on one baseline. */
.card__topline {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-2);
}

.card__topline .card__eyebrow,
.card__topline .card__title {
  margin: 0;
}

/* The top-right title is a label, not an action — quiet it down so it doesn't read as a
   button competing with the primary CTA below (which carries the real "Log in"). */
.card__topline .card__title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.card__subtitle {
  margin: 0 0 var(--space-6);
  color: var(--color-text-muted);
}

.card__footer {
  margin: var(--space-6) 0 0;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.card__footer a {
  color: var(--fg-brand);
  font-weight: 600;
}

/* ---- Form fields ---- */
.field {
  margin-bottom: var(--space-4);
  text-align: left;
}

.field__label {
  display: block;
  margin-bottom: var(--space-1);
  font-weight: 500;
  font-size: 0.875rem;
  color: var(--color-text);
}

.field__req {
  color: var(--color-error-600);
}

/* Honeypot field (org signup): off-screen for sighted users, and unlike .sr-only it must also
   stay silent for screen readers and out of tab order — a real person, assisted or not, should
   never know it exists. A bot that fills every input on the page still finds and fills it. */
.field--honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.field__input {
  width: 100%;
  /* A single-line field never needs the full width of a wide card — cap it so a short
     value (name, email, URL) sits in a right-sized box, not a slab. Fields that hold long
     content (textarea) opt back out below; short native types (time/date/number) shrink to
     their own intrinsic width. */
  max-width: 24rem;
  min-height: 44px; /* touch target */
  padding: 0 var(--space-3);
  font-family: inherit;
  font-size: var(--text-md);
  color: var(--heading);
  /* Input fill must contrast the card it sits on — never bleed into the surface. */
  background: var(--neutral-secondary-medium);
  border: 1px solid var(--border-default-medium);
  border-radius: var(--radius-md);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* A time picker carries its own natural width — a full box around HH:MM is wasted. */
.field__input[type="time"] {
  width: auto;
  max-width: 100%;
}

/* Date and time fields keep the browser's native picker: phones get their own date wheels, and
   keyboard and screen-reader support come built in. The popup itself can't be restyled from
   CSS; it follows color-scheme (set per theme in tokens.css, so it goes dark with the app) and,
   where the browser supports it, accent-color for the selected day. What CSS can reach, the
   field and its calendar button, follows the Firaq tokens. */
.field__input[type="date"],
.field__input[type="time"] {
  accent-color: var(--color-brand);
  font-variant-numeric: tabular-nums;
  cursor: text;
}

.field__input[type="date"]::-webkit-calendar-picker-indicator,
.field__input[type="time"]::-webkit-calendar-picker-indicator {
  margin-inline-start: var(--space-2);
  padding: 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  opacity: 0.7;
  transition: background-color 0.15s ease, opacity 0.15s ease;
}

.field__input[type="date"]::-webkit-calendar-picker-indicator:hover,
.field__input[type="time"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
  background-color: var(--brand-soft);
}

/* ---- Firaq date picker (desktop; app.js) ----
   On a desktop with a mouse, app.js wraps each date field in .date-field and adds a calendar
   button that opens the Firaq calendar (Cally, styled below through its ::part()s) instead of
   the browser's own popup, which CSS can't reach. The input stays the real field. */
.date-field {
  display: inline-grid;
  vertical-align: middle;
  width: 100%;
  max-width: 24rem; /* the same cap .field__input has on its own */
}

/* In a row of controls the field keeps its own width instead of filling the line. */
.overview-bar .date-field,
.squad-add__row .date-field,
.retro-assign .date-field {
  width: auto;
}

.date-field > .field__input {
  grid-area: 1 / 1;
  width: 100%;
  max-width: none;
  padding-inline-end: 44px; /* room for the calendar button */
}

.date-field > .field__input::-webkit-calendar-picker-indicator {
  display: none; /* our button replaces it */
}

.date-field__button {
  grid-area: 1 / 1;
  justify-self: end;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-inline-end: 6px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
}

.date-field__button:hover,
.date-field__button[aria-expanded="true"] {
  background: var(--brand-soft);
  color: var(--fg-brand);
}

.date-field__button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.date-field__button svg {
  width: 18px;
  height: 18px;
}

/* The popover sits in the top layer; app.js places it under (or above) its field. */
.date-popover {
  position: fixed;
  inset: auto;
  margin: 0;
  padding: var(--space-3);
  width: max-content;
  background: var(--neutral-primary-soft);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
}

.date-calendar {
  --color-accent: var(--brand);
  --color-text-on-accent: var(--text-on-primary);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
}

.date-calendar::part(header) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-2);
}

/* One "October 2026" line (app.js keeps it in sync) replaces Cally's year heading and the
   month's own label below it, so the calendar loses a row. */
.date-calendar__heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.9375rem;
  color: var(--heading);
}

.date-calendar calendar-month::part(heading) {
  display: none;
}

/* Desktop only (touch keeps the native picker), so 28-32px targets clear the 24px AA floor. */
.date-calendar::part(button) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--heading);
  cursor: pointer;
}

.date-calendar::part(button):hover {
  background: var(--brand-soft);
  color: var(--fg-brand);
}

.date-calendar::part(disabled) {
  opacity: 0.4;
  cursor: default;
}

.date-calendar svg {
  width: 14px;
  height: 14px;
}

.date-calendar calendar-month::part(th) {
  height: 24px;
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.date-calendar calendar-month::part(day) {
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--heading);
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
}

.date-calendar calendar-month::part(day):hover {
  background: var(--brand-soft);
  color: var(--fg-brand);
}

.date-calendar calendar-month::part(today) {
  box-shadow: inset 0 0 0 1.5px var(--brand);
  color: var(--fg-brand);
  font-weight: 700;
}

.date-calendar calendar-month::part(selected) {
  background: var(--brand);
  color: var(--text-on-primary);
  font-weight: 700;
}

.date-calendar calendar-month::part(disallowed) {
  background: transparent;
  color: var(--color-text-muted);
  opacity: 0.4;
  cursor: not-allowed;
}

.date-calendar calendar-month::part(day):focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.date-popover__actions {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
}

.date-popover__actions .btn {
  min-height: 30px;
  padding: 0 var(--space-3);
  font-size: 0.8125rem;
}

/* A URL is long content — let it use the full field width instead of the single-line cap. */
.field__input[type="url"] {
  max-width: none;
}

.field__input:focus {
  outline: none;
  border-color: var(--border-brand);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Textarea + select reuse .field__input but need their own vertical rhythm:
   an input is single-line (height 44px, no vertical padding); these aren't. */
.field__textarea {
  min-height: 88px;
  max-width: 100%; /* long-form content wants the room the single-line cap denies */
  padding: var(--space-3);
  line-height: 1.5;
  resize: vertical;
}

.field__select {
  /* Native select honours height via line-height + padding, not min-height alone. */
  width: auto; /* fit the widest option, not the whole card */
  max-width: 100%;
  padding-top: 0;
  padding-bottom: 0;
}

/* A grouped field (multiselect checkboxes) is a fieldset, so strip the default border. */
.field--group {
  border: none;
  padding: 0;
  margin-inline: 0;
}

.field--group .field-check {
  margin-bottom: var(--space-2);
}

.field__help {
  margin: var(--space-1) 0 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Help text carrying a caution (e.g. "anyone with this link can join") — warning-toned and
   icon-led, but still caption weight, since it describes a standing property rather than
   reporting an event the way .alert--warning does. */
.field__help--warn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-warning-600);
}

.field__help--warn svg {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
}

.field__errors {
  margin: var(--space-1) 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  color: var(--color-error-600);
}

.field--error .field__input {
  border-color: var(--color-error-600);
}

.field--error .field__input:focus {
  box-shadow: 0 0 0 3px var(--color-error-50);
}

/* ---- Password show/hide toggle ---- */
.field__input-wrap {
  position: relative;
  max-width: 24rem; /* match the single-line cap so the eye button tracks the input's edge */
}

.field__input--with-toggle {
  padding-right: 44px; /* room for the eye button */
}

.field__toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--color-gray-500);
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.field__toggle:hover {
  color: var(--color-gray-700);
}

.field__toggle:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.field__toggle svg {
  width: 20px;
  height: 20px;
  display: block;
}

/* Default: password hidden -> show the "eye". When showing, swap to "eye-off". */
.field__toggle .icon-eye-off {
  display: none;
}

.field__toggle.is-showing .icon-eye {
  display: none;
}

.field__toggle.is-showing .icon-eye-off {
  display: inline-flex;
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease;
  /* Glint: base shadow + inset top highlight + soft outer glow (buttons.md). */
  box-shadow: var(--shadow-xs), inset var(--color-1-400) 0 6px 0 -5px,
    var(--color-1-700) 0 4px 10px -5px;
}

.btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-xs), 0 0 0 4px var(--focus-ring);
}

.btn--block {
  width: 100%;
}

.btn--primary {
  background: var(--color-brand);
  color: var(--text-on-primary);
}

.btn--primary:hover {
  background: var(--color-brand-hover);
}

.btn--primary:active {
  background: var(--color-brand-active);
}

.btn--secondary {
  background: var(--neutral-secondary-medium);
  color: var(--color-text);
  border-color: var(--color-gray-300);
}

.btn--secondary:hover {
  background: var(--neutral-tertiary-medium);
  color: var(--heading);
}

.btn--danger {
  background: var(--color-error-600);
  color: var(--color-white);
}

.btn--danger:hover {
  background: var(--color-error-700, #b42318);
}

.btn--sm {
  min-height: 36px;
  padding: 0 var(--space-3);
  font-size: 0.875rem;
}

/* ---- Flash toasts: fixed to the bottom, floating above the page, auto-dismissed by JS ---- */
.flashes {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 1000;
  max-width: min(440px, calc(100% - 2 * var(--space-4)));
  display: flex;
  flex-direction: column;
  align-items: flex-end; /* toasts hug their text and stay pinned to the right edge */
  gap: var(--space-2);
  pointer-events: none; /* clicks pass through the gaps; each toast re-enables it for itself */
}

.flashes .alert {
  margin: 0;
  pointer-events: auto;
  box-shadow: 0 10px 30px rgba(2, 6, 23, 0.28);
  animation: toastIn 240ms ease-out;
}

/* JS adds this just before removing the node, so the toast slides out instead of snapping. */
.flashes .alert.is-leaving {
  animation: toastOut 240ms ease-in forwards;
}

@keyframes toastIn {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes toastOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(12px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .flashes .alert,
  .flashes .alert.is-leaving {
    animation: none;
  }
}

/* ---- Tables ---- */
.section__title {
  margin: 0 0 var(--space-4);
  font-size: 1rem;
  font-weight: 600;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.table th,
.table td {
  text-align: left;
  padding: var(--space-3) var(--space-3);
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}

.table thead th {
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.table tbody tr:last-child td {
  border-bottom: none;
}

.table tbody tr:hover td {
  background: var(--color-gray-50);
}

.table__name {
  font-weight: 500;
  white-space: nowrap;
}

.table__muted {
  color: var(--color-text-muted);
}

.table__actions {
  white-space: nowrap;
  text-align: right;
}

.table__actions .inline-form {
  display: inline;
  margin: 0;
}

.table__actions .btn {
  margin-left: var(--space-2);
}

/* Inline row editor: "Edit" is a native details/summary that pops a small form below — no JS. */
.row-edit {
  display: inline-block;
  position: relative;
}

.row-edit > summary {
  list-style: none;
  cursor: pointer;
}

.row-edit > summary::-webkit-details-marker {
  display: none;
}

.row-edit__form {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-1));
  z-index: 20;
  width: 240px;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4);
  text-align: left;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 30px rgba(2, 6, 23, 0.28);
}

.row-edit__form .btn {
  margin: var(--space-2) 0 0;
}

.row-edit__close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  color: var(--color-text-muted);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.row-edit__close:hover {
  color: var(--heading);
  background: var(--neutral-secondary-strong);
}

.row-edit__close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.page__actions {
  display: flex;
  gap: var(--space-2);
}

/* ---- Card head (title + count) ---- */
.card__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.card__head .section__title {
  margin: 0;
}

.count {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-muted);
  background: var(--color-gray-100);
  border-radius: var(--radius-full);
  padding: 2px 8px;
}

/* ---- Badges ---- */
.badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  white-space: nowrap;
}

.badge--member {
  color: var(--color-gray-600);
  background: var(--color-gray-100);
}

.badge--you {
  color: var(--color-text-muted);
  background: transparent;
}

/* ---- Quiet danger button (for in-table actions) ---- */
.btn--danger-outline {
  background: var(--neutral-secondary-medium);
  color: var(--color-error-600);
  border-color: var(--color-gray-300);
}

.btn--danger-outline:hover {
  background: var(--color-error-600);
  color: var(--color-white);
  border-color: var(--color-error-600);
}

/* ---- Alerts ---- */
.alert {
  margin-bottom: var(--space-4);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
}

.alert--error {
  color: var(--color-error-600);
  background: var(--color-error-50);
  border: 1px solid var(--color-error-600);
}

.alert--success {
  color: var(--color-success-600);
  background: var(--color-success-50);
  border: 1px solid var(--color-success-600);
}

.alert--info {
  color: var(--color-primary-700);
  background: var(--color-primary-25);
  border: 1px solid var(--color-primary-200);
}

.alert--warning {
  color: var(--color-warning-600);
  background: var(--color-warning-50);
  border: 1px solid var(--color-warning-600);
}

/* ---- HTMX loading state ----
   The "Saving…" label is hidden until htmx marks the in-flight request, then swaps with
   the normal label. hx-disabled-elt greys the button so a double-submit can't fire. */
.htmx-indicator {
  display: none;
}

.htmx-request .htmx-indicator {
  display: inline;
}

.htmx-request .btn__label {
  display: none;
}

button[disabled] {
  opacity: 0.7;
  cursor: default;
}

/* ---- Checkbox row ---- */
.field-check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  font-size: 0.875rem;
  color: var(--color-text);
  cursor: pointer;
}

/* The consent sentence wraps over several lines, so the box sits at the first line. */
.field-check--consent {
  align-items: flex-start;
  margin-bottom: var(--space-2);
}

.field-check--consent a {
  color: var(--color-brand);
  text-decoration: underline;
}

.field-check input {
  width: 18px;
  height: 18px;
  accent-color: var(--color-brand);
}

/* ---- Signed-in page layout ---- */
.page {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--space-8) var(--space-6);
}

.page--wide {
  max-width: 960px;
}

.page__header {
  display: flex;
  /* flex-start, not center: a two-line title+subtitle block would otherwise push a
     right-aligned action's vertical center down with it. Pinning both to the header's
     top edge keeps the action's position independent of title height, and matches the
     theme toggle's own top offset (see .theme-toggle) so the two align. */
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  /* Reserve room for the theme toggle (44px, right: var(--space-4)) so a right-aligned
     header action never renders under it. Needed everywhere, not just standalone pages:
     .page's centered max-width keeps clear at most widths, but .admin__main .page
     removes that cap entirely (see above), so an admin page's header can sit at any
     width right up against the toggle with nothing else to stop the overlap. */
  padding-right: calc(44px + var(--space-4) + var(--space-3));
}

.page__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.page__subtitle {
  margin: var(--space-1) 0 0;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

/* ---- Squad today view ---- */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.entry-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04);
}

/* Blockers first AND visible: a left rule in the Error colour, paired with the badge so
   it's never colour-only. */
.entry-card--blocked {
  border-left-color: var(--color-error-600);
}

.entry-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.entry-card__name {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 600;
}

.badge--blocker {
  color: var(--color-error-600);
  background: var(--color-error-50);
}

/* In the overview table the blocker badge sits inline after the name, so give it room;
   the squad view places it in a flex row with its own gap, so don't add margin there. */
.table__name .badge--blocker {
  margin-left: var(--space-2);
}

/* Overview status pills — never colour-only, each carries its own label text.
   submitted -> Success, missing -> Warning, off/weekend -> neutral gray. */
.badge--submitted {
  color: var(--color-success-600);
  background: var(--color-success-50);
}

.badge--missing {
  color: var(--color-warning-600);
  background: var(--color-warning-50);
}

.badge--off,
.badge--weekend {
  color: var(--color-gray-600);
  background: var(--color-gray-100);
}

/* Cross-squad dependency flag (Story 13) — a blocker naming another squad. Warning-toned:
   worth a look, not itself an error the way a blocker badge is. */
.badge--dependency {
  color: var(--color-warning-600);
  background: var(--color-warning-50);
}

/* Blocker lifecycle state (Story 22) — never colour-only, each badge carries its own label
   text (see admin/overview.html). Open is the most urgent (error), owned means someone's on
   it (brand), escalated means it needs attention up a level (warning). */
.badge--open {
  color: var(--color-error-600);
  background: var(--color-error-50);
}

.badge--owned {
  color: var(--color-primary-700);
  background: var(--color-primary-25);
}

.badge--escalated {
  color: var(--color-warning-600);
  background: var(--color-warning-50);
}

/* ---- Admin overview ---- */
.overview-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}

.overview-bar__label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

.overview-bar__date {
  width: auto;
  min-height: 36px;
}

.count--warning {
  color: var(--color-warning-600);
  background: var(--color-warning-50);
}

/* KPI stat tiles — the dashboard's at-a-glance row above the per-squad detail. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.stat {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-xs);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.stat__value {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--heading);
}

.stat__of {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.stat__label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--heading);
}

.stat__sub {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Accent per metric — a left rule + coloured value, always paired with the label text
   (never colour-only). */
.stat--success {
  border-left-color: var(--color-success-600);
}
.stat--success .stat__value {
  color: var(--color-success-600);
}
.stat--warning {
  border-left-color: var(--color-warning-600);
}
.stat--warning .stat__value {
  color: var(--color-warning-600);
}
.stat--danger {
  border-left-color: var(--color-error-600);
}
.stat--danger .stat__value {
  color: var(--color-error-600);
}
.stat--brand {
  border-left-color: var(--color-brand);
}
.stat--brand .stat__value {
  color: var(--color-brand);
}

/* ---- Trend tiles (Story 12): one sparkline per metric per squad. Single-series, so a
   fixed brand stroke (not a categorical hue) is enough — the number beside it is the
   direct label, no legend needed. ---- */
.trend-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-4);
}

.trend-tile {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
}

.trend-tile__label,
.trend-tile__foot {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.trend-tile__label {
  font-weight: 600;
}

.trend-tile__value {
  margin: var(--space-1) 0 0;
  font-family: var(--font-display);
  font-size: var(--text-display-sm);
  font-weight: 700;
  line-height: 1.1;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}

.trend-tile__delta {
  margin: var(--space-1) 0 var(--space-3);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.trend-tile__delta--good {
  color: var(--color-success-600);
}

.trend-tile__delta--bad {
  color: var(--color-error-600);
}

.trend-tile__foot {
  margin-top: var(--space-2);
}

/* The sparkline stretches to the tile (preserveAspectRatio="none"); non-scaling-stroke keeps
   every stroke, and the zero-length end line that draws the dot, at its set width. */
.spark {
  display: block;
  width: 100%;
  height: 44px;
  overflow: visible;
}

.spark__line,
.spark__base,
.spark__end {
  vector-effect: non-scaling-stroke;
  fill: none;
}

.spark__line {
  stroke: var(--color-brand);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.spark__area {
  fill: var(--color-brand);
  opacity: 0.12;
}

.spark__base {
  stroke: var(--color-border);
  stroke-width: 1;
}

.spark__end {
  stroke: var(--color-brand);
  stroke-width: 7;
  stroke-linecap: round;
}

/* ---- Member dashboard: status hero + ceremony tiles ---- */
.dash-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-bottom: var(--space-6);
  padding: var(--space-6) var(--space-8);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.dash-hero__eyebrow {
  display: block;
  margin-bottom: var(--space-1);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--color-text-muted);
}

.dash-hero__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--heading);
}

.dash-hero__sub {
  margin: var(--space-1) 0 0;
  color: var(--color-text-muted);
}

.dash-hero__cta .btn {
  white-space: nowrap;
}

/* State accents — left rule + text label carries the meaning (never colour-only). */
.dash-hero--done {
  border-left-color: var(--color-success-600);
}
.dash-hero--todo {
  border-left-color: var(--color-brand);
}
.dash-hero--off,
.dash-hero--rest {
  border-left-color: var(--border-default-strong);
}

/* Member home (dashboard.html): quiet top bar, the task, a stats strip, the squad panel. */
.dash-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
  /* The theme toggle sits fixed in the top-right corner (base.html); keep the links clear. */
  padding-right: 56px;
}

.dash-bar__squad {
  padding: 2px var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.dash-bar__links {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-left: auto;
}

.dash-bar__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
  cursor: pointer;
}

.dash-bar__link:hover {
  color: var(--color-text);
  background: var(--brand-soft);
}

.dash-bar__link:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

/* Member pages (_macros.member_header): the home bar, then a plain title and subtitle. */
.member-header {
  margin-bottom: var(--space-6);
}

.member-header .page__title {
  margin: 0;
}

.dash-greeting {
  margin-bottom: var(--space-6);
}

.dash-greeting .page__title {
  margin: 0;
}

.dash-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}

@media (max-width: 860px) {
  .dash-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}

.dash-main {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.dash-main .dash-hero {
  display: block;
  margin: 0;
}

.dash-hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.dash-hero__cta form {
  margin: 0;
}

.dash-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.dash-stats__item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-5);
}

.dash-stats__item + .dash-stats__item {
  border-left: 1px solid var(--color-border);
}

.dash-stats__label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.dash-stats__value {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}

.dash-stats__value--alert {
  color: var(--color-error-600);
}

.dash-stats__of {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.dash-squad {
  padding: var(--space-4) 0 var(--space-2);
}

.dash-squad__title {
  margin: 0 var(--space-5) var(--space-2);
}

.dash-links {
  margin: 0;
  padding: 0;
  list-style: none;
}

.dash-links li + li {
  border-top: 1px solid var(--color-border);
}

.dash-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 56px;
  padding: var(--space-3) var(--space-5);
  color: var(--heading);
  text-decoration: none;
}

.dash-link:hover {
  background: var(--brand-soft);
}

.dash-link:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.dash-link__icon {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  color: var(--color-brand);
}

.dash-link__icon svg {
  width: 18px;
  height: 18px;
}

.dash-link__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dash-link__title {
  font-weight: 600;
}

.dash-link__sub {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.btn--ghost {
  background: none;
  border-color: transparent;
  box-shadow: none;
  color: var(--color-text-muted);
}

.btn--ghost:hover {
  color: var(--heading);
  background: var(--neutral-secondary-strong);
}

.overview-squad__links {
  margin-left: auto;
  display: flex;
  gap: var(--space-4);
}

.overview-squad__link {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-brand);
  text-decoration: none;
}

.overview-squad__link:hover {
  text-decoration: underline;
}

/* One row of card actions: Save + test reminder grouped left, Delete pushed right. */
.squad-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.squad-actions .inline-form {
  margin: 0;
}

/* Configure / Run / Start, one grid instead of three separate .squad-actions rows — three
   stacked bordered rows read as three unrelated sections and triple the vertical space the
   same buttons need. The shared label column also lines every row of buttons up at one x. */
/* Squads page (admin/squads.html): one expandable card per squad. The summary row is the
   toggle (name, member count, status badges, chevron); the body holds the controls. */
.squad-cards {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.squad-card {
  padding: 0;
}

.squad-card__summary {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  min-height: 64px;
  padding: var(--space-4) var(--space-6);
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius-lg);
}

.squad-card__summary::-webkit-details-marker {
  display: none;
}

.squad-card__summary::marker {
  content: "";
}

.squad-card__summary:hover {
  background: var(--brand-soft);
}

.squad-card__summary:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.squad-card__name {
  margin: 0;
}

.squad-card__badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.squad-card__chevron {
  flex: none;
  width: 20px;
  height: 20px;
  margin-left: auto;
  color: var(--color-text-muted);
  transform: rotate(-90deg);
  transition: transform 0.15s ease;
}

.squad-card[open] .squad-card__chevron {
  transform: none;
}

.squad-card[open] .squad-card__summary {
  border-bottom: 1px solid var(--color-border);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.squad-card__body {
  padding: var(--space-6);
}

@media (prefers-reduced-motion: reduce) {
  .squad-card__chevron {
    transition: none;
  }
}

.squad-ceremonies {
  display: grid;
  grid-template-columns: max-content 1fr;
  align-items: center;
  column-gap: var(--space-4);
  row-gap: var(--space-3);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.squad-ceremonies__label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.squad-ceremonies__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.squad-ceremonies__row .inline-form {
  margin: 0;
}

/* Narrow: the label sits above its row rather than squeezing the buttons into a sliver. */
@media (max-width: 640px) {
  .squad-ceremonies {
    grid-template-columns: 1fr;
    row-gap: var(--space-2);
  }
  .squad-ceremonies__label {
    margin-top: var(--space-2);
  }
}

/* The invite block follows the ceremony grid directly, so it needs its own breathing room —
   .field's default margin is tuned for stacked form fields, not a section change. */
.squad-invite {
  margin-top: var(--space-5);
}

/* The destructive action sits apart from the safe ones. */
.squad-actions .btn--danger-outline {
  margin-left: auto;
}

/* ---- Holidays add row ---- */
.holiday-add {
  display: flex;
  gap: var(--space-3);
  align-items: flex-end;
  flex-wrap: wrap;
}

.holiday-add .field {
  margin-bottom: 0;
  flex: 1;
  min-width: 160px;
}

/* The submit button sits beside labeled fields but has no label of its own — without a
   same-height spacer above it, align-items: flex-end still bottom-aligns it in principle,
   but any sub-pixel difference between the button's and a native date input's rendered
   height (browser-dependent) shows up as a visible offset. A field-shaped wrapper with a
   hidden spacer label keeps the button's box structurally identical to its siblings, so
   alignment can't drift with them. */
.holiday-add .field--button {
  flex: 0 0 auto;
}

.field__label--spacer {
  visibility: hidden;
}

/* Inputs fill their column in the row (including the date picker, which would otherwise
   shrink to its intrinsic width and leave the field box half-empty). */
.holiday-add .field__input {
  width: 100%;
  max-width: none;
}

/* ---- Participation bars ---- */
/* Participation page (admin/participation.html): compact squad cards in a grid. */
.part-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: var(--space-4);
}

.part-card {
  padding: var(--space-4) var(--space-5);
}

.part-card__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
}

.part-card__name {
  margin: 0;
}

.part-card__total {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.part-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

.part-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 3rem;
  align-items: center;
  gap: var(--space-3);
  min-height: 36px;
  font-size: var(--text-sm);
  border-top: 1px solid var(--color-border);
}

.part-row__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.part-row__num {
  text-align: right;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.part-row__num--none {
  color: var(--color-warning-600);
  font-weight: 600;
}

/* Overview squad cards reuse the participation card: a row with status badges and an action,
   and a full-width bar of one block per person expected today. */
.part-row--status {
  grid-template-columns: minmax(0, 1fr) auto 6.5rem;
  min-height: 44px;
}

.part-row__badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-1);
}

.part-row__action {
  display: flex;
  justify-content: flex-end;
}

.part-days--fill {
  margin: var(--space-1) 0 var(--space-3);
}

.part-days--fill .part-days__day {
  flex: 1;
  width: auto;
  height: 6px;
  border-radius: 3px;
}

/* One block per working day so far; a filled block is a day submitted. */
.part-days {
  display: flex;
  gap: 3px;
}

.part-days__day {
  width: 14px;
  height: 8px;
  border-radius: 2px;
  border: 1px solid var(--color-border);
  background: var(--neutral-primary-soft);
}

.part-days__day.is-on {
  border-color: var(--color-success-600);
  background: var(--color-success-600);
}

.part__num {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.part-bar {
  width: 100%;
  min-width: 120px;
  height: 10px;
  background: var(--color-gray-100);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.part-bar__fill {
  display: block;
  height: 100%;
  background: var(--color-success-600);
  border-radius: var(--radius-full);
}

/* Zero submissions: a thin warning sliver so the row reads as "nothing yet", not empty. */
.part-bar__fill--none {
  width: 4px !important;
  background: var(--color-warning-600);
}

/* ---- Present mode (screen-shared at standup) ---- */
.present {
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--space-8) var(--space-6);
}

.present__header {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  margin-bottom: var(--space-8);
  /* Same reserve as .page__header, and for the same reason: the theme toggle sits
     absolute top-right, and .present has less padding (--space-6) than the toggle's
     footprint, so its own right-aligned content (.present__exit) can render underneath
     it without this. */
  padding-right: calc(44px + var(--space-4) + var(--space-3));
}

.present__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 2.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.present__date {
  margin: 0;
  color: var(--color-text-muted);
  font-size: 1.125rem;
}

.present__exit {
  margin-left: auto;
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
}

.present__exit:hover {
  color: var(--color-text);
}

.present__empty {
  font-size: 1.5rem;
  color: var(--color-text-muted);
}

.present__stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.present-card {
  border: 1px solid var(--color-border);
  border-left: 6px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-8);
}

.present-card--blocked {
  border-left-color: var(--color-error-600);
}

.present-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.present-card__name {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 700;
}

.present-card__answers {
  margin: 0;
  display: grid;
  gap: var(--space-4);
}

.present-answer {
  margin: 0;
}

.present-answer__label {
  margin: 0 0 var(--space-1);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.present-answer--attention .present-answer__label {
  color: var(--color-error-600);
}

.present-answer__value {
  margin: 0;
  font-size: 1.375rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

.card--blockers {
  border-left: 4px solid var(--color-error-600);
}

.blocker-row {
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-error-600);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}

/* AI digest card (Story 10). No coloured edge: the status badge already carries the signal,
   and a red edge on every squad read as an alarm. */
.digest-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}

.digest-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.modal--digest {
  width: min(44rem, calc(100vw - var(--space-8)));
}

.digest-actions {
  display: flex;
  gap: var(--space-2);
}


.blocker-row__head {
  display: flex;
  align-items: center;
  /* Name, squad, state, age and dependency badges: wrap on a phone instead of pushing the
     page sideways. */
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.blocker-row__who {
  font-weight: 600;
}

.blocker-row__detail {
  margin: 0 0 var(--space-3);
  display: grid;
  gap: var(--space-2);
}

.blocker-row__actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.dashboard__off {
  margin: 0 0 var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  color: var(--color-gray-600);
  background: var(--color-gray-100);
}

/* ---- Blocker field (the "I'm blocked" checkbox + reveal) ---- */
.blocker-field .field-check {
  margin-bottom: var(--space-2);
}

.blocker-field__detail {
  margin-top: var(--space-2);
  padding-left: calc(18px + var(--space-2)); /* line up under the checkbox label text */
}

.blocker-field__detail[hidden] {
  display: none;
}

/* ---- Actions dropdown menu ---- */
.menu {
  position: relative;
  display: inline-block;
}

.menu__list {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 20;
  min-width: 160px;
  padding: var(--space-1);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(16, 24, 40, 0.12);
  text-align: left;
}

.menu__list[hidden] {
  display: none;
}

.menu__list form {
  margin: 0;
}

/* Native <dialog> modal (e.g. admin/members.html "Add member") — the browser gives Esc-to-
   close, a backdrop, and focus trapping for free, so no JS modal framework is needed. */
.modal {
  width: min(32rem, calc(100vw - var(--space-8)));
  max-height: calc(100vh - var(--space-8));
  overflow: auto;
  padding: var(--space-6);
  background: var(--neutral-primary-soft);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
}

.modal::backdrop {
  background: rgb(15 23 42 / 0.5);
}

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

/* Confirm/cancel footer. Right-aligned so the destructive button isn't where the eye lands
   first, and reversed on narrow screens where the buttons go full width. */
/* A popup is already narrow, so its fields take the full width instead of the page cap. */
.modal .field__input {
  max-width: none;
}

.modal .field + .modal__actions {
  margin-top: var(--space-6);
}

.modal__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-3);
}

.modal__actions .inline-form {
  margin: 0;
}

.modal__close {
  background: none;
  border: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: var(--space-1);
}

.modal__close:hover {
  color: var(--color-text);
}

.menu__item {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-family: inherit;
  font-size: 0.875rem;
  text-align: left;
  color: var(--color-text);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
}

.menu__item:hover {
  background: var(--neutral-secondary-strong);
  color: var(--heading);
}

.menu__item--danger {
  color: var(--color-error-600);
}

.menu__item--danger:hover {
  background: var(--color-error-50);
}

/* ---- Form-builder ---- */
.card--muted {
  background: var(--color-gray-50);
}

.field-controls {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.field-controls .inline-form {
  margin: 0;
}

/* ---- Squad control panel ---- */
.squad-add__row {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
}

.squad-add__row .field__input {
  flex: 1;
  max-width: none; /* fill the row up to its button; the single-line cap is for standalone fields */
}

.squad-add__row .btn {
  white-space: nowrap;
}

.squad-rename {
  margin-bottom: var(--space-6);
}

.squad-settings {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-5);
}

/* Reminder + standup times sit side by side on a roomy screen, stack on a narrow one. */
.squad-settings__times {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.squad-settings__times .field {
  /* Each time picker is only as wide as HH:MM needs — two compact controls side by side,
     not two half-form slabs. */
  flex: 0 0 auto;
}

.entry-card__answers {
  margin: 0;
  display: grid;
  gap: var(--space-3);
}

.answer {
  margin: 0;
}

.answer__label {
  margin: 0 0 2px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.answer__value {
  margin: 0;
  white-space: pre-wrap; /* preserve line breaks in long-text answers */
  word-break: break-word;
}

/* An answered attention field (a blocker) stands out within the card. */
.answer--attention .answer__label {
  color: var(--color-error-600);
}

.answer__empty {
  color: var(--color-gray-400);
}

/* ---------- Retro board (Story 8) ---------------------------------------------------------- */

/* Visually hidden but read by screen readers (the per-column add labels). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Columns wrap to as many as fit, each a readable min width — works on a phone and a screen-
   share alike without a JS layout. */
.retro-columns {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-4);
}

.retro-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--color-gray-50);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}

/* The carry-over (action) column reads as the one that matters across sprints. */
.retro-col--action {
  border-left: 4px solid var(--color-primary-700);
}

.retro-col__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.retro-col__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
}

.retro-col__count {
  margin-left: auto;
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.retro-items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.retro-item {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

/* A checked-off action item stays visible (history) but recedes. */
.retro-item--done {
  opacity: 0.6;
}

.retro-item--done .retro-item__text {
  text-decoration: line-through;
}

.retro-item__body {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}

.retro-item__text {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
}

.retro-item__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.retro-item__author {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  margin-right: auto;
}

.retro-item__due {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.retro-assign {
  margin: var(--space-2) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* The vote toggle: a small pill that fills in when you've voted (never colour-only — the
   pressed state also changes the border and weight). */
.vote {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 28px;
  padding: 0 var(--space-2);
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  cursor: pointer;
}

.vote--on {
  color: var(--text-on-primary);
  background: var(--color-primary-700);
  border-color: var(--color-primary-700);
}

.retro-item__edit {
  display: inline;
}

.retro-item__editlink {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  cursor: pointer;
}

.retro-edit {
  margin: var(--space-2) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.retro-add {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Present mode: the same board, bigger and quieter, for screen-share. */
.present-retro {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--space-6);
}

.present-retro__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
}

.present-retro__items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.present-retro__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-3);
  align-items: baseline;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}

.present-retro__item--done {
  opacity: 0.6;
}

.present-retro__item--done .present-retro__text {
  text-decoration: line-through;
}

.present-retro__votes {
  font-weight: 700;
  color: var(--color-primary-700);
}

.present-retro__text {
  font-size: 1.25rem;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
}

.present-retro__author {
  grid-column: 2;
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.present-retro__empty {
  margin: 0;
  color: var(--color-text-muted);
}

/* Present mode's review step (Story 23): last sprint's actions, before any new column. */
.present-review {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.present-review__summary {
  margin: 0;
  font-size: 1.125rem;
  color: var(--color-text-muted);
}

.present-review__items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.present-review__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}

.present-review__item--done {
  opacity: 0.6;
}

.present-review__item--done .present-review__text {
  text-decoration: line-through;
}

.present-review__text {
  flex: 1;
  /* Matches .present-retro__text: the review is the first thing screen-shared in the same
     room as the board, so it can't be a notch smaller than what follows it. */
  font-size: 1.25rem;
  white-space: pre-wrap;
  word-break: break-word;
}

.present-review__meta {
  flex-shrink: 0;
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

/* ---- Planning poker (Story 11) ---- */
.poker-queue {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.poker-story {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}

/* A header groups sub-stories and carries no vote of its own — its own tint marks it as
   structural, not another card to play. */
.poker-story--header {
  background: var(--color-gray-50);
}

.poker-story__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.poker-story__text {
  margin: 0;
  font-weight: 600;
  white-space: pre-wrap;
  word-break: break-word;
}

.poker-subqueue {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: var(--space-3) 0 0 var(--space-4);
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.poker-subqueue .poker-story {
  padding: var(--space-3);
}

.poker-story__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* The hand of cards: one button per value in the sequence, a fixed small deck rather than a
   flexed row, so the deck reads the same regardless of how many stories are on the board. */
.poker-cards {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.poker-card {
  flex-shrink: 0;
  width: 40px;
  height: 56px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-weight: 700;
  color: var(--heading);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.poker-card:hover {
  border-color: var(--color-brand);
}

.poker-card--mine {
  color: var(--text-on-primary);
  background: var(--color-brand);
  border-color: var(--color-brand);
}

.poker-story__count {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.poker-votes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.poker-votes__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  background: var(--color-gray-50);
  border-radius: var(--radius-full);
  font-size: 0.875rem;
}

.poker-votes__value {
  font-weight: 700;
  color: var(--color-brand);
}

.poker-votes__who {
  color: var(--color-text-muted);
}

.poker-votes__empty {
  margin: 0;
  color: var(--color-text-muted);
}

.poker-story__admin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
}

.poker-estimate {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.poker-estimate .field__input {
  min-height: 36px;
  max-width: 12rem;
}

/* Admin builder: a sub-story row indented under its parent, same shape as the top-level card
   but visually nested via the left border + padding, not a second layout. */
.poker-admin-subqueue {
  margin-top: var(--space-4);
  padding-left: var(--space-5);
  border-left: 2px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.poker-admin-subrow {
  padding-top: var(--space-3);
}

.poker-admin-subrow:not(:first-child) {
  border-top: 1px solid var(--color-border);
}

/* Present mode: the same queue, bigger and quieter, for screen-share. */
.present-poker {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 720px;
  margin: 0 auto;
}

.present-poker__story {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}

.present-poker__story--header {
  background: var(--color-gray-50);
}

.present-poker__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
}

.present-poker__subitems {
  list-style: none;
  margin: 0;
  padding: var(--space-3) 0 0 var(--space-4);
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.present-poker__subitem {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: 1.0625rem;
}

.present-poker__votes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.present-poker__vote {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--color-gray-50);
  border-radius: var(--radius-full);
  font-size: 1.0625rem;
}

.present-poker__value {
  font-weight: 700;
  color: var(--color-brand);
}

.present-poker__waiting,
.present-poker__empty {
  margin: 0;
  color: var(--color-text-muted);
}

/* 44px tap target for a checkbox row (WCAG 2.5.5 target size); the weekday picker needs it. */
.field-check--tap {
  min-height: 44px;
}

/* ---- Legal documents (/terms, /privacy) ---- */
.legal__meta {
  margin-bottom: var(--space-6);
}

.legal__body {
  line-height: 1.7;
  /* A long email or URL must wrap instead of scrolling the page sideways on a phone. */
  overflow-wrap: anywhere;
}

.legal__body h2 {
  font-size: 1.25rem;
  margin: var(--space-8) 0 var(--space-3);
}

.legal__body p,
.legal__body ul {
  margin: 0 0 var(--space-4);
}

.legal__body ul {
  padding-inline-start: var(--space-6);
}

.legal__body a {
  color: var(--color-brand);
  text-decoration: underline;
}

/* ---- Legal editor: toolbar + live preview (/gadm/legal) ---- */
.legal-editor__tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

/* display:flex above would override the hidden attribute, so restate it. */
.legal-editor__tools[hidden],
.legal-editor__preview[hidden] {
  display: none;
}

.legal-editor__help {
  margin-bottom: var(--space-3);
}

.legal-editor__help summary {
  cursor: pointer;
  min-height: 24px;
}

.legal-editor__grid {
  display: grid;
  gap: var(--space-4);
}

.legal-editor__grid > * {
  min-width: 0;
}

.legal-editor__preview {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  max-height: 36rem;
  overflow: auto;
}

.legal-editor__preview h3 {
  margin: 0 0 var(--space-3);
}

/* Side by side only where both columns stay readable. */
@media (min-width: 1024px) {
  .legal-editor__grid:has(.legal-editor__preview:not([hidden])) {
    grid-template-columns: 1fr 1fr;
  }
}

.legal-editor__grid textarea {
  width: 100%;
}

/* The Settings menu in the dashboard header: wide enough that each label fits on one line. */
.menu--settings .menu__list {
  min-width: 16rem;
}

.menu--settings .menu__item {
  white-space: nowrap;
}

/* Sections inside the Organization settings popup: separated by a rule, not nested cards. */
.settings-section {
  padding: var(--space-4) 0;
}

.settings-section + .settings-section {
  border-top: 1px solid var(--color-border);
}

/* Collapsible cards in a popup (the account popup's Display name and Password). Native
   <details>, so they work without JavaScript. Each one reads as a card: a titled header row
   with a chevron, and the form opens underneath it. */
.settings-card {
  background: var(--neutral-primary-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-3);
  overflow: hidden;
}

.settings-card__summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 48px;
  padding: var(--space-4);
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}

.settings-card__summary::-webkit-details-marker {
  display: none;
}

.settings-card__summary::marker {
  content: "";
}

.settings-card__hint {
  margin-left: auto;
  font-weight: 400;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 14rem;
}

.settings-card__summary::after {
  content: "▾";
  flex: none;
  transition: transform 150ms ease;
}

.settings-card[open] > .settings-card__summary::after {
  transform: rotate(180deg);
}

.settings-card[open] > .settings-card__summary {
  border-bottom: 1px solid var(--color-border);
}

.settings-card__summary:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.settings-card__body {
  padding: var(--space-4);
}

/* Wider popup for tables (Members, Holidays). */
.modal--wide {
  width: min(56rem, calc(100vw - var(--space-8)));
}

/* Popup layout (Members, Holidays): a toolbar row, then titled sections with room between them.
   Each section title sits on its own line with its count beside it, so nothing runs together. */
.popup-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-6);
}

.popup-toolbar .table__muted {
  margin: 0;
  flex: 1 1 18rem;
}

.popup-section {
  margin-bottom: var(--space-8);
}

.popup-section__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.popup-section__title {
  margin: 0 0 var(--space-3);
}

.popup-section__head .popup-section__title {
  margin: 0;
}

.popup-section .table {
  margin-top: var(--space-2);
}

/* Working days as one row of seven segments. A day is a real checkbox, visually hidden; its
   label is the button. The chosen days light up in the brand colour, and the focus ring shows
   on the segment the keyboard is on. Each segment is at least 44px tall (WCAG 2.2 AA target). */
/* The fieldset keeps the same left edge and vertical rhythm as the fields above it. */
.day-segments {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.day-segments > legend {
  padding: 0;
  margin-bottom: var(--space-2);
}

.day-segments__row {
  display: flex;
  gap: var(--space-2);
}

.day-segments .field__help {
  margin-top: var(--space-3);
}

.day-segment {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border-strong, var(--color-border));
  border-radius: var(--radius-md);
  background: var(--neutral-primary-soft);
  color: var(--color-text);
  font-weight: 600;
  cursor: pointer;
  user-select: none;
}

.day-segment input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.day-segment:has(input:focus-visible) {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.day-segment input:checked ~ .day-segment__label {
  color: var(--text-on-primary);
}

.day-segment:has(input:checked) {
  background: var(--color-brand);
  border-color: var(--color-brand);
}

.day-segment:hover {
  background: var(--neutral-secondary-strong);
}

.day-segment:has(input:checked):hover {
  background: var(--color-brand);
}

/* Every scroll container gets a thin, quiet scrollbar. The default one on Windows is a thick
   bar with arrow buttons, and it showed on every popup and panel that ran past its height. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}

/* Settings popup (auth/_settings_popup.html). One fixed size for every tab, so switching tabs
   never resizes the popup: the width is the widest layout, and the body scrolls inside it. */
.settings-popup {
  --settings-popup-width: min(56rem, calc(100vw - var(--space-8)));
  width: var(--settings-popup-width);
  height: min(40rem, calc(100vh - var(--space-8)));
  padding: 0;
  flex-direction: column;
  overflow: hidden;
}

/* Flex only while open: a bare display rule overrides the browser's display: none on a closed
   <dialog>, which left both popups rendered at the bottom of every page. */
.settings-popup[open] {
  display: flex;
}

.settings-popup__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-6) var(--space-4);
}

.settings-popup__title {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: 600;
}

.settings-popup__subtitle {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.settings-popup__layout {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
}

/* Tabs as a vertical list down the left, the way GitHub and Stripe lay out settings. */
.settings-tabs {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3);
  border-right: 1px solid var(--color-border);
  overflow-y: auto;
}

.settings-tab {
  flex: none;
  min-height: 44px;
  padding: var(--space-2) 0;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font: inherit;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
  white-space: nowrap;
  text-align: left;
  border-radius: var(--radius-sm);
}

.settings-tab:hover {
  color: var(--color-text);
}

.settings-tab[aria-selected="true"] {
  color: var(--color-text);
  border-bottom-color: var(--color-brand);
}

.settings-tabs .settings-tab {
  border-bottom: 0;
  border-left: 2px solid transparent;
  margin-bottom: 0;
  width: 100%;
  padding: var(--space-2) var(--space-3);
}

.settings-tabs .settings-tab[aria-selected="true"] {
  border-left-color: var(--color-brand);
  background: var(--brand-soft);
}

@media (max-width: 40rem) {
  .settings-popup__layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }

  .settings-tabs {
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
    border-right: 0;
    border-bottom: 1px solid var(--color-border);
    scrollbar-width: none;
  }

  .settings-tabs .settings-tab {
    width: auto;
    border-left: 0;
    border-bottom: 2px solid transparent;
  }

  .settings-tabs .settings-tab[aria-selected="true"] {
    border-bottom-color: var(--color-brand);
    background: none;
  }
}

.settings-tab:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.settings-popup__body {
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-6);
}

.settings-tabpanel[hidden] {
  display: none;
}

/* Present popup (admin/_present_popup.html): the Settings shell, sized to its short squad
   list instead of the fixed Settings height. Each squad is one large row that opens its
   full-screen present page. */
.present-popup {
  /* fit-content, not auto: a modal <dialog> is pinned top and bottom, so auto stretches it. */
  height: fit-content;
  max-height: min(40rem, calc(100vh - var(--space-8)));
}

.present-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.present-squad {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  min-height: 56px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
}

.present-squad:hover {
  border-color: var(--color-brand);
  background: var(--brand-soft);
}

.present-squad:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.present-squad__name {
  flex: 1;
  font-weight: 600;
}

/* Settings > Subscription (admin/_subscription_panel.html): plan summary, usage, then
   features grouped by included and not included. */
.plan-summary {
  padding: var(--space-5);
  margin-bottom: var(--space-8);
}

.plan-summary__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.plan-summary__label,
.plan-features__group {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.plan-summary__name {
  margin: var(--space-1) 0 0;
}

.plan-summary__note {
  margin: var(--space-4) 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.plan-usage {
  padding: var(--space-4);
}

.plan-usage__row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  font-weight: 600;
}

.plan-usage__meter {
  display: block;
  width: 100%;
  height: 8px;
  margin-top: var(--space-3);
  accent-color: var(--color-brand);
}

.plan-features__group {
  padding: var(--space-4) var(--space-4) 0;
}

.plan-features {
  margin: 0;
  padding: var(--space-2) var(--space-4) var(--space-3);
  list-style: none;
}

.plan-features__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 40px;
}

.plan-features__item .badge {
  margin-left: auto;
}

.plan-features__icon {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--color-text-muted);
}

.plan-features__icon--on {
  color: var(--color-success-600);
}

.present-squad__go {
  width: 18px;
  height: 18px;
  color: var(--color-brand);
}

/* Settings rows (the large products' layout): title and help on the left, the control on the
   right, separated by a rule. A section's action sits in a footer at the bottom, right-aligned.
   Under 40rem the two columns stack. */
.settings-card__body {
  display: block;
  padding: 0 var(--space-4);
}

.setting-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: var(--space-6);
  padding: var(--space-5) 0;
}

.setting-row + .setting-row {
  border-top: 1px solid var(--color-border);
}

.setting-row__title {
  margin: 0;
  font-weight: 600;
}

.setting-row__help,
.setting-row__note {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.setting-row__control {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.setting-row__control .field {
  margin: 0;
}

/* On/off switch: a visually hidden checkbox (role="switch") with a styled track and thumb. The
   thumb slides when checked; the focus ring sits on the track. */
.switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
  cursor: pointer;
}

.switch input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.switch__track {
  position: relative;
  flex: none;
  width: 44px;
  height: 24px;
  border-radius: var(--radius-full);
  background: var(--neutral-tertiary-medium);
  transition: background-color 150ms ease;
}

.switch__track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--neutral-primary-soft);
  box-shadow: var(--shadow-sm);
  transition: transform 150ms ease;
}

.switch input:checked + .switch__track {
  background: var(--color-brand);
}

.switch input:checked + .switch__track::after {
  transform: translateX(20px);
}

.switch input:focus-visible + .switch__track {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.switch__label {
  font-weight: 500;
}

@media (prefers-reduced-motion: reduce) {
  .switch__track,
  .switch__track::after {
    transition: none;
  }
}

.setting-footer {
  display: flex;
  justify-content: flex-end;
  padding: var(--space-4) 0 var(--space-5);
  border-top: 1px solid var(--color-border);
}

@media (max-width: 40rem) {
  .setting-row {
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }
}

/* Toast: a short confirmation after a popup action. Fixed to the bottom right, above the page and
   any open popup, and gone after four seconds. */
.toast {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 1000;
  max-width: 22rem;
  padding: var(--space-3) var(--space-4);
  border: 1px solid;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  font-weight: 500;
  animation: toast-in 150ms ease-out;
}

.toast--success {
  color: var(--color-success-600);
  background: var(--color-success-50);
  border-color: var(--color-success-600);
}

.toast--error {
  color: var(--color-error-600);
  background: var(--color-error-50);
  border-color: var(--color-error-600);
}

.toast--info {
  color: var(--color-text);
  background: var(--neutral-primary-soft);
  border-color: var(--color-border);
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .toast {
    animation: none;
  }
}

