/* VYBE.FIT — the one design system.
 *
 * Used by the marketing site (vybe.fit), the club and member portal
 * (<club>.vybe.fit and app.vybe.fit) and the platform console (mc.vybe.fit).
 * The public site's own stylesheet, public/assets/vybe.css, is the source of
 * these tokens; they are repeated here on purpose so the three surfaces can
 * never drift apart.
 *
 * Josh, 2026-09-13: the whole platform follows the www branding, and it has to
 * look like a full platform, not an admin tool.
 *
 * Light theme only. That is a hard rule across everything Josh ships.
 *
 * A club supplies a logo, one accent colour and a hero image; those flow into
 * --accent and the slots that use it. Everything else — layout, type, motion —
 * is always VYBE.FIT.
 */

:root {
  color-scheme: light;

  --ground: #fffaf6;
  --card: #ffffff;
  --ink: #1c1633;
  --ink2: #5c5773;
  --ink3: #9a95ad;
  --line: #f0e7e1;
  --line-soft: #f7f1ec;

  --coral: #ff4d6d;
  --orange: #ff8c42;
  --sun: #ffc93c;
  --mint: #1fc8a0;
  --sky: #3fb6ff;
  --violet: #7c5cff;

  --hot: linear-gradient(100deg, var(--coral), var(--orange) 50%, var(--sun));
  --cool: linear-gradient(120deg, var(--violet), var(--sky) 55%, var(--mint));

  /* A club may replace this one colour. Nothing else. */
  --accent: var(--coral);

  --display: "Unbounded", "Arial Rounded MT Bold", "Segoe UI", system-ui, sans-serif;
  --body: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --radius: 26px;
  --radius-sm: 14px;
  --shadow: 0 1px 2px rgba(28,22,51,.04), 0 12px 40px -12px rgba(28,22,51,.14);
  --shadow-lift: 0 2px 4px rgba(28,22,51,.05), 0 24px 60px -20px rgba(28,22,51,.26);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--ground);
  color: var(--ink);
  font: 16px/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; }

h1, h2, h3 { font-family: var(--display); font-weight: 700; letter-spacing: .005em; margin: 0; }
h1 { font-size: clamp(1.5rem, 3.4vw, 2.1rem); }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 14px; color: var(--ink2); }

/* ---------------------------------------------------------------- the aura
   The drifting colour behind everything, exactly as on the public site. It is
   decoration only, so it never takes a click. */
.aura { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.aura i {
  position: absolute; border-radius: 50%; filter: blur(80px); opacity: .42;
  animation: drift 22s ease-in-out infinite alternate;
}
.aura i:nth-child(1) { width: 44vmax; height: 44vmax; background: #ffd0d9; top: -20vmax; left: -14vmax; }
.aura i:nth-child(2) { width: 36vmax; height: 36vmax; background: #ffe3b8; top: 4vmax;  right: -16vmax; animation-duration: 26s; animation-delay: -6s; }
.aura i:nth-child(3) { width: 32vmax; height: 32vmax; background: #d6f5ec; bottom: -18vmax; left: 16vmax; animation-duration: 30s; animation-delay: -12s; }
@keyframes drift {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(4vmax, 3vmax) scale(1.08); }
  100% { transform: translate(-3vmax, 5vmax) scale(.96); }
}
@media (prefers-reduced-motion: reduce) {
  .aura i { animation: none; }
}

/* ------------------------------------------------------------- the top bar */
.app-bar {
  position: sticky; top: 0; z-index: 30;
  background: rgba(255,250,246,.78);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line);
}
/* ⚠️ min-height, NOT height. A fixed height does not contain anything taller
   than itself — it lets it spill out below the bar, which is exactly what the
   signed-in person's two lines did: the word CLUB ADMIN hung underneath the
   border, outside the bar entirely. */
.app-bar .wrap { display: flex; align-items: center; gap: 14px; min-height: 68px; flex-wrap: nowrap; }

.wrap { width: 100%; max-width: 1240px; margin: 0 auto; padding-inline: clamp(18px, 4vw, 36px); }

.brand { display: flex; align-items: center; gap: 10px; font-family: var(--display); font-weight: 800; font-size: 1.12rem; }
.brand .mark {
  width: 32px; height: 32px; border-radius: 10px; background: var(--hot);
  display: grid; place-items: center; flex: none;
  box-shadow: 0 6px 18px -6px rgba(255,77,109,.6);
}
.brand .mark svg { width: 19px; height: 19px; display: block; }
.brand .dot { background: var(--hot); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* Which club you are looking at. On the console it says so in words, because
   an operator working across clubs must never have to guess. */
.club-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px 6px 7px; border-radius: 999px;
  background: var(--card); box-shadow: inset 0 0 0 1.5px var(--line);
  font-size: .85rem; font-weight: 600; color: var(--ink2); white-space: nowrap;
}
.club-chip .swatch { width: 16px; height: 16px; border-radius: 6px; background: var(--accent); flex: none; }

.club-chip.console { background: var(--ink); color: #fff; box-shadow: none; }
.club-chip.console .swatch { background: var(--cool); }

/* ⚠️⚠️ THE LINKS MUST NEVER WRAP. Without this, "Your classes" broke across two
   lines INSIDE its pill and the pill swelled into a lozenge twice the height of
   everything beside it. A row of navigation is a row: when it stops fitting it
   should slide, not grow.

   min-width:0 on a flex child is what actually permits it to shrink below its
   content and scroll. Without it the nav simply refuses to be narrower than the
   sum of its links and pushes everything else off the edge. */
/* ⚠️⚠️ TWO SEPARATE FAULTS LIVED IN THIS ONE RULE, and the second was uglier.

   1. `margin-left: auto` with no grow: the auto margin swallowed the spare room
      and the nav was never offered any of it. At 1400px the bar had 118px going
      begging while the nav sat 52px short of its contents and clipped "Apps".
      `flex: 1 1 auto` takes the slack when there is some, and min-width:0 lets
      it shrink into a slider when there is none.

   2. ⚠️ `justify-content: flex-end` AND `overflow-x: auto` TOGETHER ARE A TRAP.
      Right-aligning the row means any overflow spills off the LEFT edge — where
      it is clipped AND unreachable, because scrolling in a left-to-right page
      only ever goes the other way. Josh saw the active "Home" pill sliced down
      the middle, a black half-button hanging off the end of the club's name.
      The row starts from the left: overflow then goes right, where it can at
      least be scrolled to, and the first item is never the one that is cut. */
.app-nav {
  display: flex; gap: 2px; align-items: center;
  flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none;
}
.app-nav::-webkit-scrollbar { display: none; }

/* The person, and the way out. Pinned beside the scrolling links rather than
   inside them, so neither can ever be clipped off the end of the row. */
.app-side { display: flex; align-items: center; gap: 8px; flex: none; margin-left: 4px; }
.app-side .btn { white-space: nowrap; }
.app-nav a {
  padding: 8px 13px; border-radius: 999px; font-weight: 600; font-size: .92rem;
  color: var(--ink2); transition: background .18s, color .18s;
  white-space: nowrap; flex: none;
}
.app-nav a:hover { background: #fff; color: var(--ink); }
.app-nav a.on { background: var(--ink); color: #fff; }

/* The signed-in person is now a LINK to their own account, so it has to opt
   out of the pill shape every other link in the bar wears — otherwise the
   avatar sits inside a second, larger, pointless pill. */
.app-nav a.who { padding: 4px 8px 4px 0; border-radius: 14px; }
.app-nav a.who:hover { background: #fff; }

/* Somebody is waiting for this club to let them in. It travels on every page,
   because a request nobody notices is a member who thinks they were ignored. */
.app-nav a.waiting, .app-nav a.waiting:hover { padding: 4px 6px; background: transparent; }

/* ⚠️ A PERSON'S NAME IS ANY LENGTH, and the bar is not. It is given a ceiling
   and truncated with an ellipsis rather than being allowed to wrap, push the
   nav off the edge, or spill below the border. */
.who { display: flex; align-items: center; gap: 9px; padding-left: 6px; max-width: 13rem; min-width: 0; }
.who > span:last-child { min-width: 0; }
.who .avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--cool); color: #fff; display: grid; place-items: center;
  font-weight: 700; font-size: .82rem; letter-spacing: .02em;
}
.who .name, .who .role {
  display: block; max-width: 8rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.who .name { font-size: .88rem; font-weight: 600; line-height: 1.2; }
.who .role { font-size: .72rem; color: var(--ink3); text-transform: uppercase; letter-spacing: .05em; font-weight: 700; line-height: 1.2; }

/* ------------------------------------------------------------------ layout */
main { padding-block: clamp(26px, 5vw, 46px) 80px; }

.page-head { display: flex; align-items: flex-end; gap: 18px; flex-wrap: wrap; margin-bottom: 26px; }
.page-head .lead { flex: 1 1 320px; }
.page-head p { margin: 6px 0 0; }
.page-head .actions { display: flex; gap: 10px; flex-wrap: wrap; }

.grid { display: grid; gap: 18px; }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

/* ------------------------------------------------------------------- cards */
.card {
  background: var(--card); border-radius: var(--radius);
  padding: clamp(20px, 3vw, 28px); box-shadow: var(--shadow);
}
.card.flush { padding: 0; overflow: hidden; }
.card h2 { margin-bottom: 4px; }
.card-head { display: flex; align-items: center; gap: 12px; padding: 20px clamp(20px, 3vw, 28px) 14px; }
.card-head h2 { flex: 1; }

/* A number that matters, shown large. */
.tile { background: var(--card); border-radius: var(--radius-sm); padding: 18px 20px; box-shadow: var(--shadow); }
.tile .k { font-size: .76rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink3); }
.tile .v { font-family: var(--display); font-size: 1.9rem; font-weight: 700; line-height: 1.15; margin-top: 4px; }
.tile .v small { font-size: .9rem; font-weight: 600; color: var(--ink3); font-family: var(--body); }

/* ----------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 22px; border: 0; border-radius: 999px; cursor: pointer;
  font: inherit; font-weight: 700; font-size: .95rem; white-space: nowrap;
  transition: transform .18s, box-shadow .18s, background .18s;
}
.btn:hover { transform: translateY(-2px); }
.btn-hot { background: var(--hot); color: #fff; box-shadow: 0 10px 28px -10px rgba(255,77,109,.7); }
.btn-hot:hover { box-shadow: 0 16px 36px -12px rgba(255,77,109,.8); }
.btn-solid { background: var(--ink); color: #fff; }
.btn-ghost { background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--line), var(--shadow); }
.btn-danger { background: var(--card); color: #d1002b; box-shadow: inset 0 0 0 1.5px #f3d7de; }
.btn-danger:hover { background: #fff1f3; }
.btn-sm { padding: 8px 16px; font-size: .86rem; }
.btn-block { width: 100%; }
.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; }

/* ------------------------------------------------------------------ fields */
.field { margin-bottom: 16px; }
.field label { display: block; font-weight: 700; font-size: .86rem; margin-bottom: 7px; }
.field .hint { font-size: .82rem; color: var(--ink3); margin-top: 6px; }
/* ⚠️ STYLED BY EXCLUSION, NOT BY LIST. This was a list of the input types we
   happened to have used, and `datetime-local` was not on it — so the one
   control on the whole platform that asks when a class starts rendered as bare
   browser furniture, in a monospace font, beside a page of rounded fields.
   A list like that is wrong again the moment anybody uses a new type; naming
   the handful that must NOT look like a text box cannot rot the same way. */
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]):not([type=submit]):not([type=button]),
select, textarea {
  width: 100%; padding: 13px 15px; font: inherit; color: inherit;
  background: #fffdfb; border: 1.5px solid var(--line); border-radius: var(--radius-sm);
  transition: border-color .18s, box-shadow .18s;
}

/* A colour well is a swatch, not a text box: it keeps the same frame and
   radius but none of the padding, so the colour fills it. */
input[type=color] {
  width: 100%; height: 48px; padding: 4px; background: #fffdfb; cursor: pointer;
  border: 1.5px solid var(--line); border-radius: var(--radius-sm);
}
input[type=color]::-webkit-color-swatch-wrapper { padding: 0; }
input[type=color]::-webkit-color-swatch { border: 0; border-radius: 9px; }

/* The little calendar and clock buttons the browser draws inside a date field.
   Left alone they are pure system grey against our own palette. */
input::-webkit-calendar-picker-indicator {
  cursor: pointer; opacity: .5; transition: opacity .15s;
}
input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: transparent;
  box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--accent) 55%, transparent);
}

/* ------------------------------------------------------------------ tables */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: .94rem; }
thead th {
  text-align: left; padding: 12px clamp(14px, 2vw, 20px);
  font-size: .74rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink3); background: var(--line-soft); white-space: nowrap;
}
tbody td { padding: 14px clamp(14px, 2vw, 20px); border-top: 1px solid var(--line-soft); vertical-align: middle; }
tbody tr:hover td { background: #fffdfb; }
td.right, th.right { text-align: right; white-space: nowrap; }
td .sub { display: block; font-size: .82rem; color: var(--ink3); }

/* ------------------------------------------------------------------ badges */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 11px; border-radius: 999px;
  font-size: .72rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
}
.badge-live { background: #e8f9f0; color: #0f7a4f; }
.badge-live .pulse {
  width: 7px; height: 7px; border-radius: 50%; background: #22b260;
  animation: breathe 1.5s ease-in-out infinite;
}
@keyframes breathe { 0%,100% { opacity: .45; } 50% { opacity: 1; } }
.badge-soon   { background: #eef4ff; color: #2b5bd7; }
.badge-draft  { background: #fff6e6; color: #9a6100; }
.badge-done   { background: var(--line-soft); color: var(--ink3); }
.badge-off    { background: #fff1f3; color: #b4123a; }

/* ------------------------------------------------------------- empty state */
.empty { text-align: center; padding: clamp(34px, 7vw, 64px) 20px; }
.empty .art { width: 74px; height: 74px; margin: 0 auto 16px; border-radius: 22px; background: var(--hot); opacity: .18; }
.empty h2 { margin-bottom: 6px; }
.empty p { max-width: 38ch; margin-inline: auto; }

/* ------------------------------------------------------------- small print */
.muted { color: var(--ink3); font-size: .88rem; }
.notice { padding: 13px 16px; border-radius: var(--radius-sm); margin-bottom: 16px; font-size: .93rem; }
.notice-error { background: #fff1f3; color: #b4123a; }
.notice-ok    { background: #e8f9f0; color: #0f7a4f; }
.notice-info  { background: #eef4ff; color: #2b5bd7; }

/* ------------------------------------------------------- the sign-in scene
   Two panels: the brand on the left, the form on the right. On a phone the
   brand panel becomes a short header so the form is reachable without
   scrolling. */
body.auth { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; }
.auth-art {
  position: relative; overflow: hidden; background: var(--hot); color: #fff;
  padding: clamp(30px, 5vw, 60px); display: flex; flex-direction: column; justify-content: space-between;
}
.auth-art::after {
  content: ""; position: absolute; inset: auto -20% -35% -20%; height: 70%;
  background: radial-gradient(closest-side, rgba(255,255,255,.3), transparent 70%);
}
.auth-art .brand { color: #fff; font-size: 1.25rem; position: relative; z-index: 1; }
.auth-art .brand .mark { background: rgba(255,255,255,.22); box-shadow: none; }
.auth-art .brand .dot { background: none; -webkit-text-fill-color: #fff; color: #fff; }
.auth-art .pitch { position: relative; z-index: 1; max-width: 22ch; }
.auth-art .pitch h1 { font-size: clamp(1.9rem, 3.6vw, 3rem); line-height: 1.08; color: #fff; }
.auth-art .pitch p { color: rgba(255,255,255,.92); font-size: 1.02rem; margin-top: 14px; }
.auth-art .foot { position: relative; z-index: 1; font-size: .84rem; color: rgba(255,255,255,.8); }
.auth-form { display: grid; place-items: center; padding: clamp(26px, 5vw, 56px) clamp(18px, 4vw, 40px); }
.auth-form .inner { width: 100%; max-width: 25rem; }
.auth-form h2 { font-size: 1.6rem; margin-bottom: 6px; }

@media (max-width: 860px) {
  body.auth { grid-template-columns: 1fr; }
  .auth-art { padding: 22px clamp(18px, 5vw, 30px) 26px; }
  .auth-art .pitch h1 { font-size: 1.6rem; }
  .auth-art .pitch p, .auth-art .foot { display: none; }
}
/* Room runs out long before a phone. A club admin has seven places to go, a
   club name beside the logo and their own name at the end — by about 1200px
   the name is the first thing that can go without costing anybody a
   destination. The avatar stays, because it is still the way to the account. */
@media (max-width: 1280px) {
  .who .name, .who .role { display: none; }
  .who { max-width: none; padding-left: 2px; }
}
/* Then the club's name, which the page itself says anyway. */
@media (max-width: 1000px) {
  .app-bar .club-chip { display: none; }
}
@media (max-width: 720px) {
  .app-bar .wrap { min-height: 0; padding-block: 12px; flex-wrap: wrap; gap: 10px; }
  .app-nav { order: 3; width: 100%; margin-left: 0; }
  .app-side { margin-left: auto; }
}

/* ------------------------------------------------------- the rest of the kit
   Small pieces the portal already uses: a tag, a yes/no, a form that sits in a
   table row, and a bare <button> that finishes a form. */
.tag {
  background: var(--accent); color: #fff; font-size: .7rem; font-weight: 800;
  letter-spacing: .05em; text-transform: uppercase; padding: 3px 9px;
  border-radius: 999px; vertical-align: middle;
}
.yes { color: #0f9d78; font-weight: 700; }
.no  { color: #c9c4d4; }
form.inline { display: inline; margin: 0 0 0 6px; }

/* A button with no class of its own finishes a form, so it looks like the
   primary action rather than unstyled browser chrome. */
button:not([class]) {
  margin-top: 18px; width: 100%; padding: 13px 22px; font: inherit; font-weight: 700;
  color: #fff; background: var(--hot); border: 0; border-radius: 999px; cursor: pointer;
  box-shadow: 0 10px 28px -10px rgba(255,77,109,.7);
}
form.inline button:not([class]) { width: auto; margin: 0; padding: 8px 16px; font-size: .86rem; }

/* Older spellings kept meaningful rather than left to fall through. */
.error { background: #fff1f3; color: #b4123a; padding: 13px 16px; border-radius: var(--radius-sm); margin-bottom: 14px; }
.btn.danger { background: var(--card); color: #d1002b; box-shadow: inset 0 0 0 1.5px #f3d7de; }
.btn.danger:hover { background: #fff1f3; }

/* ------------------------------------------------------------- the timetable
   A week: days across, times down, drawn in the club's own time zone.

   Built on CSS grid rather than absolute positioning, so a class that runs from
   nine to nine forty-five simply spans rows. The half hour is the unit because
   it is the smallest thing a club timetable ever uses. */
.grid-wrap {
  --slot: 26px;
  display: grid; grid-template-columns: 3.2rem repeat(7, minmax(7rem, 1fr));
  gap: 6px; overflow-x: auto; padding-bottom: 6px;
}
.grid-wrap .rail {
  display: grid; grid-auto-rows: var(--slot);
  padding-top: 44px;   /* clears the day headings */
}
.grid-wrap .rail span {
  font-size: 11px; color: var(--ink3); text-align: right; padding-right: 8px;
  line-height: 1; transform: translateY(-4px);
}
.grid-wrap .day { min-width: 7rem; }
.grid-wrap .dayhead {
  height: 44px; display: flex; flex-direction: column; justify-content: center;
  align-items: center; line-height: 1.15;
}
.grid-wrap .dayhead b { font-size: .84rem; }
.grid-wrap .dayhead span { font-size: .74rem; color: var(--ink3); }
.grid-wrap .day.today .dayhead b { color: var(--accent); }

/* One column of half-hour cells, with the classes laid over them. */
.grid-wrap .col {
  display: grid; position: relative;
  background: #fff; border-radius: 14px; overflow: hidden;
  box-shadow: inset 0 0 0 1.5px var(--line);
}
.grid-wrap .day.today .col { box-shadow: inset 0 0 0 1.5px var(--accent); }

/* Every empty half hour is somewhere to put a class. Clicking is the mechanism,
   not a shortcut: the front desk is often on a tablet. */
.grid-wrap .slot {
  grid-column: 1; border-top: 1px solid #f6efe9; transition: background .12s;
}
.grid-wrap .slot:first-child { border-top: 0; }
.grid-wrap .slot:hover { background: #fffaf6; }

.grid-wrap .blk {
  grid-column: 1; margin: 1px 3px; padding: 5px 7px; border-radius: 9px;
  background: color-mix(in srgb, var(--blk) 14%, #fff);
  box-shadow: inset 3px 0 0 var(--blk);
  color: var(--ink); text-decoration: none; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-start;
  font-size: .76rem; line-height: 1.25; z-index: 1;
}
.grid-wrap .blk:hover { background: color-mix(in srgb, var(--blk) 26%, #fff); }
.grid-wrap .blk b { font-weight: 700; }
.grid-wrap .blk span { color: var(--ink2); font-size: .72rem; }
.grid-wrap .blk em { font-style: normal; color: var(--ink3); font-size: .72rem; }

/* A draft is visibly not a real class — it has no public link, sends no
   reminders and cannot go live. A cancelled one is visibly still there,
   because members may have been told about it. Neither is hidden. */
.grid-wrap .blk.draft {
  background: repeating-linear-gradient(135deg, #fff, #fff 6px, #fdf4ec 6px, #fdf4ec 12px);
  box-shadow: inset 3px 0 0 #d9cfc6;
}
.grid-wrap .blk.draft em { color: #9a6100; font-weight: 600; }
.grid-wrap .blk.off { opacity: .5; }
.grid-wrap .blk.off b { text-decoration: line-through; }
.grid-wrap .blk.live { box-shadow: inset 3px 0 0 var(--blk), 0 0 0 2px var(--blk); }

/* The weekday picker, which is the whole of the repeat rule: weekly, on chosen
   days. No monthly patterns — a club timetable does not work that way. */
.days { display: flex; gap: 6px; flex-wrap: wrap; }
.daybox {
  display: inline-flex; align-items: center; gap: 5px; padding: 8px 12px;
  border-radius: 999px; background: #fff; box-shadow: inset 0 0 0 1.5px var(--line);
  font-size: .85rem; font-weight: 600; cursor: pointer;
}
.daybox:has(input:checked) { background: var(--ink); color: #fff; box-shadow: none; }

@media (max-width: 720px) {
  /* A week does not fit on a phone, and squeezing it makes it unreadable.
     It scrolls sideways instead, which is what a paper timetable does too. */
  .grid-wrap { grid-template-columns: 2.6rem repeat(7, 8rem); }
}

/* ------------------------------------------------------ a club's shop window
   The club's own address: what is on, and what can be watched again. Read by
   the whole internet, most of it on a phone, by people who have not signed in
   and may never have heard of us. */
.club-hero { text-align: center; padding-block: clamp(18px, 4vw, 40px) clamp(24px, 4vw, 44px); }
.club-hero h1 {
  font-size: clamp(1.9rem, 4.4vw, 3rem); line-height: 1.08; margin: 18px auto 0;
  max-width: 18ch;
}
.club-hero .lead { max-width: 38ch; margin: 16px auto 0; font-size: 1.05rem; }
.club-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 26px; }

.club-band { margin-bottom: clamp(28px, 5vw, 48px); }
.band-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 16px; }
.band-head h2 { flex: 1; }
.club-band > h2 { margin-bottom: 16px; }

/* What is on. A card per class — the time first, because that is what somebody
   scanning a schedule is actually looking for. */
.on-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.on-card {
  display: flex; flex-direction: column; gap: 5px;
  background: var(--card); border-radius: var(--radius-sm); padding: 16px 18px;
  box-shadow: var(--shadow); border-left: 5px solid var(--blk, var(--accent));
  transition: transform .16s, box-shadow .2s;
}
.on-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.on-card .when { font-size: .8rem; font-weight: 700; color: var(--ink3); text-transform: uppercase; letter-spacing: .04em; }
.on-card strong { font-size: 1.02rem; line-height: 1.25; }
/* One line. An instructor's name and a room name together are as long as they
   are, and wrapping them turns a tidy grid of cards into a ragged one. */
.on-card .who {
  font-size: .88rem; color: var(--ink2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.on-card .len { font-size: .8rem; color: var(--ink3); margin-top: 2px; }

/* Watch again. Pictures, because a class is judged on how it looks. */
.replay-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.replay { display: block; }
.replay .frame {
  position: relative; display: block; aspect-ratio: 16/9; overflow: hidden;
  border-radius: var(--radius-sm); background: var(--ink); box-shadow: var(--shadow);
  transition: transform .16s, box-shadow .2s;
}
.replay:hover .frame { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.replay .frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.replay .noart {
  position: absolute; inset: 0; display: grid; place-items: center;
  color: rgba(255,255,255,.55); font-size: .85rem; font-weight: 600;
}
.replay .tag { position: absolute; top: 9px; left: 9px; }
.replay .dur {
  position: absolute; right: 9px; bottom: 9px; background: rgba(0,0,0,.62); color: #fff;
  font-size: .74rem; padding: 3px 8px; border-radius: 999px;
}
.replay strong { display: block; margin-top: 10px; font-size: .97rem; line-height: 1.3; }
.replay .who { display: block; font-size: .85rem; color: var(--ink3); }
