:root {
  color-scheme: light;
  --ink: #18202f;
  --muted: #667085;
  --line: #d7dee8;
  --panel: #ffffff;
  --surface: #f4f7fb;
  --accent: #0f766e;
  --accent-dark: #0b5f59;
  --navy: #17325d;
  --navy-soft: #edf3fb;
  --gold: #b7791f;
  --warn: #8a5200;
  --warn-bg: #fff4db;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.shell {
  min-height: 100vh;
  padding: 22px;
}

.app-header,
.workspace {
  max-width: 1180px;
  margin: 0 auto;
}

.app-header {
  padding: 6px 2px 18px;
}

.header-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.eyebrow {
  margin: 0;
  color: var(--accent-dark);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0;
  text-transform: uppercase;
}

.version-pill {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 7px;
  border: 1px solid #c8d8e9;
  border-radius: 999px;
  background: white;
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
}

h1,
h2 {
  margin: 0;
  line-height: 1.2;
}

h1 {
  color: var(--navy);
  font-size: 32px;
}

.header-copy {
  max-width: 620px;
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.45;
}

h2 {
  font-size: 19px;
}

.panel,
.result {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 14px 30px rgba(23, 50, 93, 0.07);
}

.panel {
  padding: 18px;
}

.workflow-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.workflow-strip div {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 42px;
  padding: 9px 10px;
  border: 1px solid #c8d8e9;
  border-radius: 8px;
  background: #f8fbff;
  color: var(--navy);
  font-weight: 800;
}

.workflow-strip strong {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: var(--navy);
  color: white;
  font-size: 12px;
}

.workflow-strip span {
  font-size: 13px;
}

.control-strip {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 0.55fr);
  gap: 16px;
  align-items: stretch;
}

.grid,
.upload-grid,
.meet-list,
.instruction-grid,
.result-stats {
  display: grid;
  gap: 14px;
}

.grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
}

.entry-grid {
  grid-template-columns: minmax(0, 1fr) minmax(220px, 0.6fr);
}

.primary-entry {
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfe;
}

.upload-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: 14px;
}

.section-header,
.result-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.current-meets,
.how-to-use,
.advanced-options,
.upload-section,
.contact-section {
  margin-top: 20px;
}

.how-to-use,
.advanced-options,
.upload-section,
.contact-section {
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.section-copy {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.4;
}

.current-meets {
  padding: 18px;
  border: 1px solid #aec8de;
  border-radius: 8px;
  background: linear-gradient(180deg, #f9fbfe 0%, #f2f7fb 100%);
}

.primary-current-meets {
  margin-top: 16px;
}

/* First-run banner: same highlighted-box treatment as .current-meets (soft blue gradient +
   border) so it reads as part of the same visual language, but sits above the form as a plain
   block -- never fixed/sticky -- so it can't compete with #downloadDock's fixed bottom bar. */
.onboarding-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  padding: 14px 16px;
  border: 1px solid #aec8de;
  border-radius: 8px;
  background: linear-gradient(180deg, #f9fbfe 0%, #f2f7fb 100%);
  box-shadow: 0 10px 24px rgba(23, 50, 93, 0.06);
}

.onboarding-banner-text {
  margin: 0;
  max-width: 640px;
  color: var(--navy);
  font-size: 14px;
  font-weight: 650;
  line-height: 1.45;
}

.onboarding-banner-text strong {
  color: var(--accent-dark);
}

.onboarding-banner-dismiss {
  flex-shrink: 0;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--navy);
  font: inherit;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
}

.onboarding-banner-dismiss:hover {
  border-color: #9cc8bd;
}

.instruction-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 12px;
}

.how-to-use summary,
.advanced-options summary,
.upload-section summary,
.contact-section summary,
.past-meets summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0 0;
  min-height: 44px;
  color: var(--navy);
  cursor: pointer;
  list-style: none;
  font-weight: 800;
}

.advanced-options summary,
.upload-section summary,
.contact-section summary,
.past-meets summary {
  padding: 0;
}

.how-to-use summary::-webkit-details-marker,
.advanced-options summary::-webkit-details-marker,
.upload-section summary::-webkit-details-marker,
.contact-section summary::-webkit-details-marker,
.past-meets summary::-webkit-details-marker {
  display: none;
}

.how-to-use summary::after,
.advanced-options summary::after,
.upload-section summary::after,
.contact-section summary::after,
.past-meets summary::after {
  content: "+";
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: white;
  color: var(--accent-dark);
  font-size: 16px;
}

.how-to-use[open] summary::after,
.advanced-options[open] summary::after,
.upload-section[open] summary::after,
.contact-section[open] summary::after,
.past-meets[open] summary::after {
  content: "-";
}

.how-to-use summary small,
.advanced-options summary small,
.upload-section summary small,
.contact-section summary small,
.past-meets summary small {
  color: var(--muted);
  font-size: 13px;
  font-weight: 650;
}

.advanced-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-top: 14px;
}

.upload-panel {
  margin-top: 14px;
}

.upload-submit-group {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}

.upload-requirement-hint {
  color: var(--muted);
  font-size: 12px;
  font-weight: 650;
  text-align: right;
}

.upload-requirement-hint.active-error {
  color: var(--warn);
  font-weight: 800;
}

.field-error-hint {
  margin: 8px 0 0;
  color: var(--warn);
  font-size: 12px;
  font-weight: 800;
}

.contact-panel {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #f8fbff;
}

.contact-panel h2 {
  font-size: 17px;
}

.contact-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.contact-actions .secondary-button {
  border: 1px solid var(--line);
  text-decoration: none;
}

.instruction-card {
  min-height: 132px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfe;
}

.instruction-card span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: var(--navy);
  color: white;
  font-size: 13px;
  font-weight: 800;
}

.instruction-card h3 {
  margin: 10px 0 4px;
  font-size: 15px;
}

.instruction-card p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.45;
}

.meet-list {
  grid-template-columns: repeat(2, minmax(320px, 1fr));
  margin-top: 12px;
}

/* A lone ready current meet only fills column 1 of the 2-column grid, leaving column 2 empty.
   That leftover space cramps the card's height, and .meet-card's align-items: stretch then
   stretches the "Use this meet" button to match while it stays intrinsically narrow, wrapping its
   text. Scoped to #currentMeetList only -- #pastMeetList already has a fine single-item layout
   and shares the .meet-list class, so this must not touch it. */
#currentMeetList > .meet-card:only-child {
  grid-column: 1 / -1;
}

.featured-meet {
  margin-top: 14px;
}

.meet-card,
.empty-state,
.file-input,
fieldset,
.result-stats div {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfe;
}

.meet-card {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 16px;
  padding: 16px;
  background: white;
}

.featured-meet-card {
  align-items: center;
  padding: 18px;
  border-color: #d1a94c;
  background: linear-gradient(180deg, #fffaf0 0%, #ffffff 72%);
  box-shadow: 0 12px 28px rgba(183, 121, 31, 0.1);
}

.featured-meet-card .primary {
  min-width: 180px;
}

.meet-action-button {
  gap: 8px;
}

.meet-card.is-busy {
  border-color: #73b9ad;
  box-shadow: 0 12px 28px rgba(15, 118, 110, 0.12);
}

.meet-card.is-ready {
  border-color: #9cc8bd;
}

.meet-card.is-error {
  border-color: #f1a56d;
}

.meet-card.is-empty {
  border-color: #e5bd70;
  background: #fff8e9;
}

.meet-card-pending {
  border-color: #d9c088;
  background: #fffdf8;
}

.meet-pending-note {
  color: #73510c;
}

.past-meets-pointer {
  color: var(--accent-dark);
  font-weight: 800;
  text-decoration: underline;
  white-space: nowrap;
}

.past-meet-card {
  opacity: 0.82;
}

.past-meet-row {
  align-items: center;
  padding: 12px 16px;
}

.past-meet-row h3 {
  font-size: 15px;
}

.past-meet-row-meta {
  margin: 2px 0 0;
  font-size: 13px;
}

.past-meet-row .meet-action-button {
  flex: 0 0 auto;
}

.meet-card-main {
  min-width: 0;
}

.meet-title-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.meet-card h3 {
  margin: 0;
  font-size: 18px;
}

.featured-meet-card h3 {
  color: var(--navy);
  font-size: 22px;
}

.featured-meta,
.meet-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.featured-meta {
  margin-bottom: 8px;
}

.featured-meta span,
.meet-facts span {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
}

.featured-meta span {
  background: #fff0c7;
  color: #7c4d00;
}

.meet-facts {
  margin-top: 8px;
}

.meet-facts span {
  background: #f3f6fb;
  color: #43505e;
}

.meet-note {
  max-width: 620px;
  margin: 7px 0 0;
  color: #5b4620;
  font-size: 14px;
  line-height: 1.4;
}

.meet-readiness,
.meet-rules {
  margin-top: 12px;
}

.meet-readiness > strong,
.meet-rules > strong {
  display: block;
  margin-bottom: 7px;
  color: var(--navy);
  font-size: 13px;
}

.meet-readiness ul,
.meet-rules ul {
  display: grid;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.meet-readiness ul {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.meet-readiness li {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr);
  gap: 4px 7px;
  align-items: center;
  min-height: 44px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #f8fbff;
}

.meet-readiness li span {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: #a7b2c1;
}

.meet-readiness li strong,
.meet-readiness li em {
  min-width: 0;
  font-size: 12px;
  line-height: 1.2;
}

.meet-readiness li strong {
  color: var(--ink);
}

.meet-readiness li em {
  grid-column: 2;
  color: var(--muted);
  font-style: normal;
  font-weight: 750;
}

.meet-readiness .readiness-ready span {
  background: var(--accent);
}

.meet-readiness .readiness-missing {
  border-color: #e5bd70;
  background: #fff8e9;
}

.meet-readiness .readiness-missing span {
  background: var(--gold);
}

.meet-readiness .readiness-optional span {
  background: #8aa3bd;
}

.meet-rules ul {
  max-width: 680px;
}

.meet-rules li {
  padding-left: 12px;
  border-left: 3px solid #c8d8e9;
  color: #43505e;
  font-size: 13px;
  line-height: 1.4;
}

.meet-detail-toggle {
  margin-top: 12px;
}

.meet-detail-toggle summary {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 44px;
  color: var(--navy);
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
  list-style: none;
}

.meet-detail-toggle summary::-webkit-details-marker {
  display: none;
}

.meet-detail-toggle summary::after {
  content: "\25be";
  font-size: 9px;
}

.meet-detail-toggle[open] summary {
  margin-bottom: 10px;
}

.meet-detail-toggle[open] summary::after {
  content: "\25b4";
}

.meet-progress {
  display: grid;
  gap: 10px;
  margin-top: 12px;
  padding: 11px;
  border: 1px solid #c8d8e9;
  border-radius: 8px;
  background: #f8fbff;
}

.meet-progress-main {
  display: flex;
  align-items: flex-start;
  gap: 9px;
}

.meet-progress-main strong,
.meet-progress-main span {
  display: block;
}

.meet-progress-main strong {
  color: var(--navy);
  font-size: 14px;
}

.meet-progress-main span {
  margin-top: 2px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.35;
}

.progress-steps,
.inline-ready-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.progress-steps span {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 9px;
  border-radius: 999px;
  background: white;
  color: #43505e;
  font-size: 12px;
  font-weight: 800;
}

.progress-steps span:first-child {
  background: #dff5ef;
  color: var(--accent-dark);
}

.inline-download-primary,
.inline-secondary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 12px;
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
}

.inline-download-primary {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: white;
}

.inline-secondary-button {
  border: 1px solid var(--line);
  background: white;
  color: var(--navy);
}

.muted {
  margin: 4px 0 0;
  color: var(--muted);
}

.status-pill,
.doc-tags span {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
}

.status-pill {
  background: #eef3fb;
  color: var(--navy);
}

.doc-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.doc-tags span {
  background: #e4f3f0;
  color: var(--accent-dark);
}

.past-meets {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid #dbe5ef;
}

.empty-state {
  padding: 14px;
  color: var(--muted);
  font-weight: 650;
}

label span,
legend {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 750;
}

label span small {
  color: var(--muted);
  font-size: 12px;
  font-weight: 650;
}

.state-field,
.file-field,
.check-option-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.term-hint {
  margin-top: 2px;
}

.term-hint summary {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* Text/icon stay their original compact size (align-items: center just adds breathing room
     above/below) -- this only exists to bring the tap target up to a reasonable minimum. */
  min-height: 44px;
  color: var(--accent-dark);
  font-size: 12px;
  font-weight: 750;
  cursor: pointer;
  list-style: none;
}

.term-hint summary::-webkit-details-marker {
  display: none;
}

.term-hint summary::before {
  content: "?";
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
}

.term-hint p {
  max-width: 460px;
  margin: 6px 0 0;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #f8fbff;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

.field-heading {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  margin-bottom: 6px;
}

.field-heading span {
  margin: 0;
}

.swimmer-list {
  display: grid;
  gap: 8px;
}

.swimmer-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 34px;
  gap: 8px;
}

input[type="text"],
input:not([type]) {
  width: 100%;
}

input {
  font: inherit;
}

input[name="swimmer_name"],
input[name="swimmer_names"],
input[name="state"] {
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
}

.add-swimmer-button,
.icon-button {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--navy);
  font: inherit;
  font-weight: 750;
  cursor: pointer;
}

.add-swimmer-button {
  justify-self: start;
  min-height: 44px;
  margin-top: 8px;
  padding: 0 11px;
  font-size: 13px;
}

.icon-button {
  height: 44px;
  padding: 0;
  font-size: 20px;
  line-height: 1;
}

.family-options,
.relay-options {
  display: grid;
  gap: 8px;
  margin: 14px 0 0;
  padding: 12px;
}

.relay-options {
  grid-column: 1 / -1;
}

.relay-option-list {
  display: grid;
  gap: 8px;
}

.check-option {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: flex-start;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: white;
}

.check-option input {
  margin-top: 3px;
}

.check-option strong,
.check-option small {
  display: block;
}

.check-option strong {
  font-size: 14px;
}

.check-option small {
  margin-top: 3px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.35;
}

.file-input {
  display: block;
  min-height: 96px;
  padding: 12px;
}

.file-input small {
  display: block;
  margin: -2px 0 8px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.35;
}

.file-input input {
  width: 100%;
  font-size: 13px;
}

.calendar-options {
  display: grid;
  gap: 8px;
  margin: 14px 0 0;
  padding: 12px;
}

.calendar-option {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: flex-start;
  min-height: 74px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: white;
  cursor: pointer;
}

.calendar-option input {
  margin-top: 3px;
}

.calendar-option strong,
.calendar-option small {
  display: block;
}

.calendar-option strong {
  font-size: 14px;
}

.calendar-option small {
  margin-top: 3px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.35;
}

.calendar-option em {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--navy-soft);
  color: var(--navy);
  font-size: 11px;
  font-style: normal;
  font-weight: 800;
}

.calendar-option.recommended {
  border-color: #a5c7d6;
  background: #f6fbfb;
}

.primary,
.downloads a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--accent);
  color: white;
  font: inherit;
  font-weight: 750;
  text-decoration: none;
  cursor: pointer;
}

.primary:hover,
.downloads a:hover {
  background: var(--accent-dark);
}

.primary:disabled {
  cursor: not-allowed;
  opacity: 0.78;
}

.mini-spinner {
  display: inline-block;
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  border: 2px solid rgba(15, 118, 110, 0.22);
  border-top-color: currentColor;
  border-radius: 999px;
  animation: spin 0.75s linear infinite;
}

.ready-dot,
.error-dot,
.empty-dot {
  display: inline-block;
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  margin-top: 2px;
  border-radius: 999px;
}

.ready-dot {
  background: var(--accent);
}

.error-dot {
  background: #d97706;
}

.empty-dot {
  background: var(--gold);
}

.status {
  position: sticky;
  top: 8px;
  z-index: 12;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  margin: 14px 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: white;
  font-weight: 650;
  box-shadow: 0 10px 24px rgba(23, 50, 93, 0.09);
}

.status::before {
  content: "";
  display: none;
  width: 16px;
  height: 16px;
  border: 2px solid #b7c5d6;
  border-top-color: var(--accent);
  border-radius: 999px;
}

.status-busy {
  border-color: #9cc8bd;
  color: var(--navy);
}

.status-busy::before {
  display: inline-block;
  animation: spin 0.8s linear infinite;
}

.status-success {
  border-color: #9cc8bd;
  background: #f4fbf9;
  color: var(--accent-dark);
}

.status-error {
  border-color: #f1c76d;
  background: var(--warn-bg);
  color: var(--warn);
}

.status-empty {
  border-color: #e5bd70;
  background: var(--warn-bg);
  color: var(--warn);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.result {
  padding: 18px;
}

.hidden {
  display: none !important;
}

.result-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.result-actions {
  align-items: flex-start;
}

.downloads {
  display: grid;
  gap: 10px;
  justify-items: end;
}

.download-group {
  display: grid;
  gap: 6px;
  justify-items: end;
}

.download-group h3 {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
}

.download-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

/* .download-group defaults to justify-items: end for the short link rows above; the copy field
   here needs the full row width instead, so this group opts back into a stretched layout. */
.subscribe-group {
  justify-items: stretch;
  gap: 10px;
}

.subscribe-note {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
  text-align: right;
}

.subscribe-row {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfe;
}

.subscribe-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--ink);
  font: inherit;
  font-weight: 750;
  text-decoration: none;
  cursor: pointer;
}

.subscribe-link:hover {
  border-color: #9cc8bd;
}

.subscribe-copy-label {
  color: var(--muted);
  font-size: 12px;
}

.subscribe-copy-field {
  display: flex;
  gap: 6px;
  width: 100%;
}

.subscribe-copy-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
}

.subscribe-copy-button {
  flex-shrink: 0;
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--navy);
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
}

.subscribe-copy-button:hover {
  border-color: #9cc8bd;
}

.download-dock {
  position: fixed;
  left: 12px;
  right: 12px;
  /* env() falls back to 0px on every non-notched device/browser, so this is a no-op there --
     on an iPhone with a home indicator (and only once the page opts into edge-to-edge rendering
     via viewport-fit=cover, see index.html) it keeps the dock clear of that gesture bar instead
     of sitting flush against/under it. Not verifiable without a real device -- flagged for
     manual check. */
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  z-index: 20;
  display: none;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border: 1px solid #9cc8bd;
  border-radius: 8px;
  /* Fully opaque, not translucent: at short/landscape viewport heights the dock can land over
     page text (e.g. the workflow-strip steps), and a translucent background let that text bleed
     through -- looked like a rendering glitch, not a deliberate frosted-glass effect. */
  background: var(--panel);
  box-shadow: 0 14px 30px rgba(23, 50, 93, 0.2);
}

.download-dock.dock-busy {
  border-color: #73b9ad;
}

.download-dock.dock-busy .download-dock-copy strong::before {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-right: 7px;
  border: 2px solid rgba(15, 118, 110, 0.22);
  border-top-color: var(--accent);
  border-radius: 999px;
  content: "";
  vertical-align: -2px;
  animation: spin 0.75s linear infinite;
}

.download-dock.dock-error {
  border-color: #f1a56d;
}

.download-dock.dock-empty {
  border-color: #e5bd70;
}

.download-dock-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.download-dock strong {
  color: var(--navy);
  font-size: 14px;
}

.download-dock span {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.35;
}

.download-dock-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.download-dock-primary,
.download-dock button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 12px;
  border-radius: 6px;
  font: inherit;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
}

.download-dock-primary {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: white;
}

.download-dock button {
  border: 1px solid var(--line);
  background: white;
  color: var(--navy);
}

.downloads a.secondary,
.secondary-button {
  border-color: var(--line);
  background: white;
  color: var(--ink);
}

.secondary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 14px;
  border-radius: 6px;
  font: inherit;
  font-weight: 750;
  cursor: pointer;
}

.secondary-button:disabled {
  color: var(--muted);
  cursor: default;
}

.result-stats {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: 14px;
}

.result-stats div {
  padding: 12px;
}

.result-stats strong {
  display: block;
  color: var(--navy);
  font-size: 24px;
}

.result-stats span {
  color: var(--muted);
  font-size: 13px;
  font-weight: 750;
}

.warnings {
  margin-top: 14px;
}

.warning {
  padding: 10px 12px;
  border: 1px solid #f1c76d;
  border-radius: 6px;
  background: var(--warn-bg);
  color: var(--warn);
  font-weight: 650;
}

.table-wrap {
  width: 100%;
  margin-top: 16px;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
}

table {
  width: 100%;
  min-width: 940px;
  border-collapse: collapse;
  background: white;
}

th,
td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
  font-size: 14px;
}

th {
  background: #eef3f8;
  color: #43505e;
  font-size: 12px;
  text-transform: uppercase;
}

td strong {
  display: block;
}

.swimmer-chip {
  display: inline-flex;
  margin-bottom: 4px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--navy-soft);
  color: var(--navy);
  font-size: 12px;
  font-weight: 800;
}

/* Motivational-tier tokens (B/BB/A/AA/AAA/AAAA) inside a benchmark line, colored low-to-high with
   this app's own palette. --gold/--warn were considered and rejected: both already mean "needs
   attention" elsewhere in this app (.readiness-missing/.empty-dot use --gold; error/active states
   use --warn), so using either for a swimmer's BEST result would fight the app's own vocabulary.
   --muted/--navy/--accent carry no such conflict: each covers two adjacent tiers (normal weight,
   then bold) before the scale steps to the next color, and --accent-dark -- the app's own "most
   emphasized" variant of its ready/good color -- marks AAAA alone as the standout at the top,
   rather than sharing a color with AAA the way every other pair does. "below B" is not a separate
   case: it shares B's styling because the literal "B" substring inside "below B" is what the
   token regex actually matches. */
.tier-B {
  color: var(--muted);
  font-weight: 650;
}
.tier-BB {
  color: var(--navy);
  font-weight: 650;
}
.tier-A {
  color: var(--navy);
  font-weight: 800;
}
.tier-AA {
  color: var(--accent);
  font-weight: 650;
}
.tier-AAA {
  color: var(--accent);
  font-weight: 800;
}
.tier-AAAA {
  color: var(--accent-dark);
  font-weight: 800;
}

@media (max-width: 860px) {
  .shell {
    padding: 12px;
  }

  .section-header,
  .result-header,
  .meet-card,
  .contact-panel,
  .onboarding-banner {
    flex-direction: column;
    align-items: stretch;
  }

  .onboarding-banner-dismiss {
    width: 100%;
  }

  .control-strip,
  .grid,
  .upload-grid,
  .meet-list,
  .instruction-grid,
  .advanced-grid,
  .result-stats {
    grid-template-columns: 1fr;
  }

  .workflow-strip {
    grid-template-columns: 1fr;
  }

  .workflow-strip div {
    min-height: 38px;
  }

  .meet-readiness ul {
    grid-template-columns: 1fr;
  }

  .featured-meet-card .primary {
    min-width: 0;
  }

  .primary,
  .secondary-button {
    width: 100%;
  }

  .result-actions,
  .downloads,
  .contact-actions {
    justify-content: flex-start;
  }

  .contact-actions {
    display: grid;
  }

  .downloads,
  .download-group,
  .download-links {
    justify-items: stretch;
    justify-content: stretch;
    width: 100%;
  }

  .download-links {
    display: grid;
  }

  .downloads a {
    width: 100%;
  }

  .subscribe-row {
    align-items: stretch;
  }

  .subscribe-note {
    text-align: left;
  }

  .subscribe-copy-field {
    flex-direction: column;
  }

  .download-dock:not(.hidden) {
    display: grid;
  }

  .download-dock {
    grid-template-columns: 1fr;
  }

  .download-dock-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .download-dock-primary,
  .download-dock button,
  .inline-download-primary,
  .inline-secondary-button {
    width: 100%;
  }

  .table-wrap {
    overflow-x: visible;
    border: none;
    border-radius: 0;
    background: transparent;
  }

  table {
    min-width: 0;
  }

  /* Visually hidden, NOT display:none -- display:none (and visibility:hidden) both remove an
     element from the accessibility tree entirely, which would take the column headers ("Day",
     "Event", "Window", ...) away from screen reader users along with the table's own visual
     header row. The per-cell data-label::before captions below are a sighted-only substitute
     (CSS generated content isn't reliably exposed to every screen reader), so this keeps the
     real header text available as a fallback -- read once, up front -- while staying invisible
     and out of the way for sighted users converting to the stacked-card layout below. */
  thead {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  tbody {
    display: grid;
    gap: 10px;
  }

  tr {
    display: flex;
    flex-direction: column;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: white;
  }

  td {
    display: block;
    padding: 0;
    border-bottom: none;
    font-size: 13px;
  }

  td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 2px;
    color: var(--muted);
    font-size: 10px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }

  td[data-col="event"] {
    order: 1;
    padding-bottom: 6px;
    font-size: 15px;
  }

  td[data-col="day"] {
    order: 2;
    color: var(--navy);
    font-size: 12px;
    font-weight: 800;
  }

  td[data-col="window"] {
    order: 3;
    margin-bottom: 8px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--line);
    color: var(--navy);
    font-size: 13px;
    font-weight: 750;
  }

  td[data-col="event"]::before,
  td[data-col="day"]::before,
  td[data-col="window"]::before {
    content: none;
  }

  td[data-col="seed"] {
    order: 4;
    padding-top: 4px;
  }

  td[data-col="benchmark"] {
    order: 5;
    padding-top: 8px;
  }

  td[data-col="source"] {
    order: 6;
    padding-top: 8px;
    color: var(--muted);
    font-size: 12px;
  }
}

/* ---------------------------------------------------------------------------
   Officials' badge cards (/officials)
   --------------------------------------------------------------------------- */

.nav-back {
  margin: 10px 0 0;
  font-size: 14px;
}

.nav-back a,
.nav-officials a {
  color: var(--accent-dark);
  font-weight: 750;
  text-decoration: none;
}

.nav-back a:hover,
.nav-officials a:hover {
  text-decoration: underline;
}

.nav-officials {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: 14px;
}

.officials-field {
  display: block;
  max-width: 560px;
  margin: 14px 0 12px;
}

.officials-field > span {
  display: block;
  margin-bottom: 6px;
  color: var(--navy);
  font-size: 13px;
  font-weight: 800;
}

.officials-field select {
  width: 100%;
  min-height: 42px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--ink);
  font: inherit;
}

.sessions-table td[data-col="session"] {
  color: var(--navy);
  font-weight: 800;
}

.sessions-table td[data-col="interval"] {
  color: var(--muted);
  font-size: 12px;
}

.session-card-link {
  color: var(--accent-dark);
  font-weight: 750;
  text-decoration: none;
  white-space: nowrap;
}

.session-card-link:hover {
  text-decoration: underline;
}

@media (max-width: 860px) {
  .sessions-table td[data-col="session"] {
    padding-bottom: 6px;
    font-size: 15px;
  }

  .sessions-table td[data-col="card"] {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--line);
  }
}

/* Officials: watched-swimmer highlighting. Reuses the family page's .swimmer-list/.swimmer-row/
   .icon-button/.add-swimmer-button rules for the name inputs; only the pieces with no existing
   equivalent are defined here. */

.swimmer-highlight {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.swimmer-highlight .swimmer-fieldset {
  max-width: 560px;
  margin-top: 12px;
}

.highlight-summary {
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid #e5d089;
  border-radius: 6px;
  background: #fdf6df;
  color: var(--ink);
  font-size: 13px;
  line-height: 1.5;
}

.sessions-table td[data-col="starred"] {
  white-space: nowrap;
}

.starred-count {
  color: #8a6100;
  font-weight: 800;
}

.sessions-table tr.has-starred td[data-col="session"] {
  box-shadow: inset 3px 0 0 #d9a520;
}

/* Officials: print-sheet download + the "only my swimmers" session filter. Reuses the family
   page's .check-option for the toggle itself; only the wrapper and hint are new. */

.download-hint {
  display: block;
  max-width: 340px;
  margin-top: 6px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
  text-align: right;
}

.highlight-filter {
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fbfcfe;
}

.highlight-filter .check-option {
  margin: 0;
}

/* Officials: "Print Copies" panel (layout=handout) -- one session repeated N times. Reuses
   .officials-field for the two inputs and .secondary-button for the download link. */

.print-copies {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.print-copies-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 12px;
}

.print-copies-fields .officials-field {
  flex: 1 1 200px;
  max-width: 240px;
  margin: 0;
}

#copiesCount {
  width: 100%;
  min-height: 42px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--ink);
  font: inherit;
}

#copiesEstimate {
  margin: 10px 0 12px;
  font-size: 13px;
}

.secondary-button.is-disabled {
  pointer-events: none;
  opacity: 0.5;
}

/* Officials: shareable ?meet_id= link. Same readonly-input + Copy-button shape as app.js's
   subscribe-link copy control, so the clipboard-unavailable fallback (select the field, copy by
   hand) behaves identically on both pages. */

.share-link {
  margin-top: 12px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fbfcfe;
}

.share-link-label {
  display: block;
  margin-bottom: 6px;
  color: var(--navy);
  font-size: 13px;
  font-weight: 800;
}

.share-link-field {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.share-link-input {
  flex: 1 1 280px;
  min-height: 40px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: white;
  color: var(--ink);
  font: inherit;
  font-size: 13px;
}

.share-link-hint {
  display: block;
  margin-top: 6px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}
