/* Huntsville Hamfest 2026 — offline schedule
   System fonts only, no external requests. */

/* Dark is the default. The theme button flips data-theme between the two
   explicit states — there is deliberately no "follow the system" third state. */
:root, :root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0b1220;
  --bg-2: #111b2e;
  --card: #16223a;
  --card-hi: #1d2c49;
  --line: #26375a;
  --line-soft: #1d2b47;
  --text: #e8eefc;
  --text-dim: #9fb0d0;
  --text-faint: #6d7f9f;
  --accent: #4da3ff;
  --accent-ink: #06101f;

  --c-forum: #4da3ff;
  --c-fdia: #35d0a5;
  --c-social: #ffab4d;
  --c-logistics: #9aa6bd;
  --c-exam: #b98bff;
  --c-youth: #ff7ab3;
  --c-air: #4fd6e6;
  --c-prize: #ffd447;

  --radius: 14px;
  --shadow: 0 1px 2px rgb(0 0 0 / .3), 0 8px 24px rgb(0 0 0 / .22);
  --tap: 44px;
}

:root[data-theme="light"] {
  color-scheme: light;

  --bg: #f4f6fb;
  --bg-2: #ffffff;
  --card: #ffffff;
  --card-hi: #eef3fc;
  --line: #d5dded;
  --line-soft: #e4eaf5;
  --text: #101a2c;
  --text-dim: #4d5f7d;
  --text-faint: #7d8ca6;
  --accent: #0b62d6;
  --accent-ink: #ffffff;
  --c-forum: #0b62d6;
  --c-fdia: #067a5c;
  --c-social: #b25f00;
  --c-logistics: #5c6a82;
  --c-exam: #6d3fc4;
  --c-youth: #c02a70;
  --c-air: #0b7c8c;
  --c-prize: #8a6a00;
  --shadow: 0 1px 2px rgb(16 26 44 / .06), 0 6px 20px rgb(16 26 44 / .08);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  padding-bottom: env(safe-area-inset-bottom);
  overflow-wrap: break-word;
}

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

/* ───────────────────────── top bar ───────────────────────── */

/* Fixed, not sticky, and the space it occupies is reserved as body padding that
   never changes. Collapsing the controls therefore has zero effect on document
   flow — nothing shifts, so nothing needs a scroll correction, so there is no
   feedback loop to make it flicker at the threshold. */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line-soft);
  padding: 10px 14px 8px;
  padding-top: max(10px, env(safe-area-inset-top));
}

.topbar-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  max-width: 1100px;
  margin: 0 auto;
}

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

.brand h1 {
  margin: 0;
  font-size: clamp(1.15rem, 4.5vw, 1.5rem);
  letter-spacing: -.02em;
  line-height: 1.15;
}

.sub {
  margin: 2px 0 0;
  font-size: .74rem;
  color: var(--text-faint);
  line-height: 1.35;
}

.icon-btn {
  flex: none;
  width: var(--tap);
  height: var(--tap);
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-dim);
  font-size: 1.15rem;
  cursor: pointer;
}
.icon-btn:hover { background: var(--card-hi); color: var(--text); }

/* day tabs */
.days {
  display: flex;
  gap: 6px;
  margin: 10px auto 0;
  max-width: 1100px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.days::-webkit-scrollbar { display: none; }

.day-tab {
  flex: 1 0 auto;
  min-width: 74px;
  min-height: var(--tap);
  padding: 6px 12px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-dim);
  cursor: pointer;
  font: inherit;
  line-height: 1.2;
  text-align: center;
  transition: background .12s, color .12s, border-color .12s;
}
.day-tab b { display: block; font-size: .95rem; color: var(--text); }
.day-tab span { display: block; font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; }
.day-tab.on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.day-tab.on b, .day-tab.on span { color: var(--accent-ink); }
.day-tab.today::after {
  content: "";
  display: block;
  width: 5px; height: 5px;
  margin: 3px auto 0;
  border-radius: 50%;
  background: currentColor;
}

/* controls */
.controls { max-width: 1100px; margin: 8px auto 0; }

/* Once you scroll past End of day the schedule controls are just clutter over the
   reference sections, so the header drops to the title bar alone. Collapsed with
   `display:none` rather than an animated height — the topbar is sticky, so its
   flow box shrinking would shove the page content upward. app.js compensates the
   scroll position by the exact height lost, which only works on an instant change. */
.topbar.compact .controls { display: none; }

.search-wrap { position: relative; }

#search {
  width: 100%;
  min-height: var(--tap);
  padding: 8px 38px 8px 12px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font: inherit;
}
#search::placeholder { color: var(--text-faint); }
#search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.clear-btn {
  position: absolute;
  right: 4px; top: 50%;
  transform: translateY(-50%);
  width: 36px; height: 36px;
  border: 0; border-radius: 10px;
  background: transparent;
  color: var(--text-dim);
  font-size: 1.4rem; line-height: 1;
  cursor: pointer;
}

.filters {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.filters::-webkit-scrollbar { display: none; }
.filters.second { margin-top: 6px; }

.chip {
  flex: none;
  min-height: 34px;
  padding: 4px 11px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-dim);
  font: inherit;
  font-size: .82rem;
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.chip:hover { background: var(--card-hi); }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--cc, var(--text-dim)); flex: none; }
.chip[aria-pressed="true"] {
  background: color-mix(in srgb, var(--cc, var(--accent)) 20%, var(--card));
  border-color: var(--cc, var(--accent));
  color: var(--text);
}
.chip-star[aria-pressed="true"] { --cc: var(--c-prize); }
.chip .count {
  font-size: .7rem;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--line);
  color: var(--text-dim);
}

/* ───────────────────────── schedule ───────────────────────── */

#main { max-width: 1100px; margin: 0 auto; padding: 14px; }

.slot { margin-bottom: 18px; }

/* Explicit day boundaries so it's obvious where the timed schedule starts and
   stops, and where the untimed info below it begins. */
.day-edge {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 2px 0;
}
.day-edge .tagline {
  flex: none;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.day-edge .name {
  font-size: .95rem;
  font-weight: 650;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.day-edge .rule { flex: 1; height: 1px; background: var(--line); }

.day-edge.start { margin: 0 0 12px; }
.day-edge.start .tagline { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }

.day-edge.end { margin: 0 0 26px; }
.day-edge.end .name { color: var(--text-faint); font-weight: 500; }

.slot-head {
  position: sticky;
  top: var(--stick, 172px);
  z-index: 10;
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 5px 2px;
  margin-bottom: 6px;
  background: linear-gradient(var(--bg) 72%, transparent);
}
.slot-head h2 {
  margin: 0;
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.slot-head .rule { flex: 1; height: 1px; background: var(--line-soft); }

.cards { display: grid; gap: 8px; }
@media (min-width: 760px) {
  .cards { grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
}

.card {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 10px;
  padding: 11px 12px 11px 15px;
  border: 1px solid var(--line-soft);
  border-left: 4px solid var(--cc);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  width: 100%;
}
.card:hover { background: var(--card-hi); }
.card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.card.pinned { border-color: color-mix(in srgb, var(--cc) 55%, var(--line-soft)); }

.card-main { grid-column: 1; min-width: 0; }

.card h3 {
  margin: 0 0 3px;
  font-size: .97rem;
  line-height: 1.3;
  letter-spacing: -.005em;
}

.card .who {
  margin: 0 0 3px;
  font-size: .82rem;
  color: var(--text-dim);
}

.card .meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  font-size: .74rem;
  color: var(--text-faint);
}

.card .time {
  font-variant-numeric: tabular-nums;
  color: var(--cc);
  font-weight: 600;
}
/* unknown start time — amber, matching the `time TBD` tag on scheduled events */
.card .time.tbd { color: var(--c-prize); }

.card .where {
  margin: 4px 0 0;
  font-size: .77rem;
  color: var(--text-faint);
}


.tag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: .67rem;
  letter-spacing: .03em;
  text-transform: uppercase;
  border: 1px solid color-mix(in srgb, var(--cc) 45%, transparent);
  color: var(--cc);
  background: color-mix(in srgb, var(--cc) 12%, transparent);
}
.tag.plain { --cc: var(--text-faint); }
.tag.warn { --cc: var(--c-prize); }

.star {
  grid-column: 2;
  grid-row: 1 / -1;
  align-self: start;
  width: 38px; height: 38px;
  margin: -3px -4px 0 0;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-faint);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.star:hover { background: color-mix(in srgb, var(--c-prize) 15%, transparent); }
.star.on { color: var(--c-prize); }

.card.past { opacity: .48; }
.card.live {
  border-color: var(--c-fdia);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--c-fdia) 35%, transparent), var(--shadow);
}
.live-badge {
  color: var(--c-fdia);
  font-weight: 700;
  font-size: .7rem;
  letter-spacing: .06em;
}

.conflict {
  grid-column: 1 / -1;
  margin-top: 5px;
  font-size: .73rem;
  color: var(--c-social);
}

.empty {
  padding: 34px 16px;
  text-align: center;
  color: var(--text-faint);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}

/* ───────────────────────── panels ───────────────────────── */

.panel {
  margin-top: 26px;
  padding: 14px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--bg-2);
}
.panel h2 { margin: 0 0 4px; font-size: 1rem; }
.panel-note { margin: 0 0 10px; font-size: .8rem; color: var(--text-faint); }

/* matches the schedule's card grid so these read as events, not list items */
.tbd-list { display: grid; gap: 8px; align-items: start; }
@media (min-width: 760px) {
  .tbd-list { grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
}

/* align-items:start so each card hugs its content — otherwise the short Admission
   card stretches to match the tall prize-rules card beside it and leaves a void. */
.ref-list { display: grid; gap: 10px; align-items: start; }
@media (min-width: 760px) { .ref-list { grid-template-columns: 1fr 1fr; } }

.ref {
  padding: 12px 13px;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--card);
  min-width: 0;
}
.ref.wide { grid-column: 1 / -1; }

.ref h3 {
  margin: 0 0 9px;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.ref-note {
  margin: 10px 0 0;
  padding-top: 9px;
  border-top: 1px solid var(--line-soft);
  font-size: .78rem;
  line-height: 1.5;
  color: var(--text-faint);
}

/* stat tiles — admission prices */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(94px, 1fr)); gap: 7px; }
.stat {
  padding: 9px 10px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: var(--bg-2);
}
.stat .v { display: block; font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; }
.stat .k { display: block; margin-top: 2px; font-size: .7rem; color: var(--text-faint); }

/* frequency table — too wide for a phone, so it scrolls inside its own box
   rather than letting the page scroll sideways */
.rtable-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rtable { width: 100%; min-width: 780px; border-collapse: collapse; font-size: .84rem; }
.rtable th {
  text-align: left;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 0 12px 6px 0;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.rtable td {
  padding: 6px 12px 6px 0;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
.rtable tr:last-child td { border-bottom: 0; }

/* callsign, frequency, offset, tone — all read better aligned and monospaced */
.rtable td:nth-child(-n + 4) {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .82rem;
  white-space: nowrap;
}
.rtable td:nth-child(1) { color: var(--text); }
.rtable td:nth-child(2) { color: var(--c-air); }
.rtable td:nth-child(3),
.rtable td:nth-child(4) { color: var(--text-dim); }
.rtable td:nth-child(5) { white-space: nowrap; color: var(--text-dim); }
.rtable td:nth-child(6) { white-space: nowrap; color: var(--text-faint); }
.rtable td:nth-child(7) { color: var(--text-faint); font-size: .79rem; min-width: 200px; }

/* rule list */
.rlist { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
/* when a list trails another body, e.g. the ticket rules under the price tiles */
.rlist.after-body { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line-soft); }
.rlist li {
  display: grid;
  grid-template-columns: 16px 1fr;
  gap: 8px;
  font-size: .84rem;
  line-height: 1.45;
  color: var(--text-dim);
}
.rlist li::before { content: "•"; color: var(--text-faint); text-align: center; }
.rlist li.warn { color: var(--text); }
.rlist li.warn::before { content: "!"; color: var(--c-prize); font-weight: 700; }

/* label / value pairs */
.facts { margin: 0; display: grid; gap: 7px; }
.facts > div {
  display: grid;
  grid-template-columns: minmax(88px, 34%) 1fr;
  gap: 10px;
  font-size: .82rem;
  line-height: 1.45;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--line-soft);
}
.facts > div:last-child { border-bottom: 0; padding-bottom: 0; }
.facts dt { color: var(--text-faint); }
.facts dd { margin: 0; color: var(--text-dim); }

.foot {
  margin-top: 26px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: .8rem;
  color: var(--text-dim);
}
.foot p { margin: 0 0 7px; }
/* deliberately no divider — this reads as part of the disclaimer block above it */
.foot .byline { color: var(--text-dim); }
.foot .dim { color: var(--text-faint); font-size: .74rem; }
.foot code {
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: var(--card);
  padding: 1px 5px;
  border-radius: 5px;
}

/* ───────────────────────── detail sheet ───────────────────────── */

.sheet { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-end; justify-content: center; }
@media (min-width: 640px) { .sheet { align-items: center; padding: 20px; } }

/* Required: a normal author `display` declaration outranks the UA stylesheet's
   `[hidden] { display: none }` (origin beats specificity), so without this the
   sheet stays on screen permanently and cannot be dismissed. */
.sheet[hidden] { display: none; }

.sheet-backdrop { position: absolute; inset: 0; background: rgb(3 8 18 / .6); }

.sheet-card {
  position: relative;
  width: 100%;
  max-width: 620px;
  max-height: 86vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 20px 18px calc(24px + env(safe-area-inset-bottom));
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -8px 40px rgb(0 0 0 / .4);
}
@media (min-width: 640px) { .sheet-card { border-radius: 18px; } }

.sheet-close {
  position: absolute;
  top: 10px; right: 10px;
  width: 38px; height: 38px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  color: var(--text-dim);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}

.sheet-card h2 {
  margin: 0 8px 8px 0;
  padding-right: 34px;
  font-size: 1.18rem;
  line-height: 1.28;
  letter-spacing: -.01em;
}

.sheet-when {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--cc);
  margin: 0 0 10px;
}

.sheet-rows { display: grid; gap: 7px; margin: 0 0 14px; }
.sheet-row { display: grid; grid-template-columns: 74px 1fr; gap: 10px; font-size: .87rem; }
.sheet-row dt { color: var(--text-faint); font-size: .77rem; padding-top: 2px; }
.sheet-row dd { margin: 0; }

.sheet-desc {
  margin: 0 0 14px;
  font-size: .92rem;
  line-height: 1.6;
  color: var(--text-dim);
  white-space: pre-wrap;
}

.sheet-note {
  margin: 0 0 14px;
  padding: 9px 11px;
  border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--c-social) 40%, transparent);
  background: color-mix(in srgb, var(--c-social) 10%, transparent);
  font-size: .84rem;
  line-height: 1.5;
}

.sheet-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.btn {
  min-height: var(--tap);
  padding: 8px 15px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: .88rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn:hover { background: var(--card-hi); }
/* size only — the icons carry their own fill/stroke, see ICON in app.js */
.btn .i { width: 16px; height: 16px; flex: none; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.primary:hover { filter: brightness(1.08); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

/* Build-time pre-rendered schedule. Present in dist/index.html so crawlers and
   no-JS visitors get the real content; app.js replaces #schedule on load, so this
   is only ever visible for that first paint. See build.mjs. */
.prerender .pr-day { margin: 0 0 28px; }
.prerender .pr-day > h2 {
  font-size: 1rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--dim);
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
  margin: 0 0 12px;
}
.prerender .pr-event {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card);
  padding: 12px 14px;
  margin: 0 0 8px;
}
.prerender .pr-event h3 { margin: 0 0 4px; font-size: .98rem; }
.prerender .pr-event p { margin: 2px 0; font-size: .86rem; color: var(--dim); }
.prerender .pr-when { color: var(--accent) !important; font-variant-numeric: tabular-nums; }
.prerender .pr-desc { color: var(--text) !important; line-height: 1.5; }
