/* ============================================================================
   The Line Staff Portal — shared theme
   ----------------------------------------------------------------------------
   ONE stylesheet for all 55 pages. Before this, every page carried its own
   copy of its styles, so a restyle meant editing 55 files; now it means
   editing this one. When converting a page: delete its <style> block, add
   <link rel="stylesheet" href="/theme.css"> and use the classes below.

   Design language: Apple dark ("Liquid Glass") — translucent layered panels,
   depth, content first. Graphite base so the only real colour on screen is
   status and the brand accent. 14px radius: sharper than stock Apple, closer
   to the sharp-cornered look Jimmy prefers.

   THEMING. Everything is driven by the variables in :root.
   - Dark is the default.
   - Light comes free via prefers-color-scheme, so it follows the device.
   - data-theme="light" / "dark" on <html> overrides the device (the manual
     toggle in theme.js writes this), so a user choice always wins.
   To try a different palette (e.g. the navy or pure-black variants), change
   only the --bg-* and --wash values in ONE of the blocks below.
   ========================================================================== */

:root {
  /* --- type -------------------------------------------------------------- */
  /* SF Pro is licensed to Apple platforms only, so it can't be shipped on the
     web. This stack gets real SF on Mac/iPhone/iPad and Segoe on Windows. */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter",
          "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* Apple's iOS type scale */
  --fs-large-title: 34px;
  --fs-title-1: 28px;
  --fs-title-2: 22px;
  --fs-title-3: 20px;
  --fs-headline: 17px;
  --fs-body: 17px;
  --fs-callout: 16px;
  --fs-subhead: 15px;
  --fs-footnote: 13px;
  --fs-caption: 12px;
  --fs-micro: 11px;

  /* --- 8pt spacing grid, 4pt subdivisions -------------------------------- */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;

  --radius: 14px;
  --radius-sm: 10px;
  --radius-pill: 999px;
  --tap: 44px;                     /* Apple's minimum touch target */
  --ease: cubic-bezier(.32,.72,0,1);
  --maxw: 1060px;

  /* --- status colours (same in both themes; these ARE the semantics) ------ */
  --green: #30D158;
  --red:   #FF453A;
  --amber: #FF9F0A;
  /* Text on a solid green/red/amber/accent fill. Near-black clears 4.5:1 on
     every one of those fills in both themes; white fails on all but light accent. */
  --on-fill: #06131A;
  --btn-ink: #06131A;   /* .btn text — dark ink on the light-cyan dark accent */

  /* --- DARK (default) ---------------------------------------------------- */
  --bg: #0E1013;
  --wash:
    radial-gradient(1100px 560px at 6% -10%, rgba(100,210,255,.13), transparent 60%),
    radial-gradient(900px 520px at 96% 2%, rgba(120,120,140,.12), transparent 60%),
    linear-gradient(180deg, #14171C 0%, #0E1013 60%, #0A0C0F 100%);
  --label:   #F5F5F7;
  --label-2: rgba(235,235,245,.62);
  --label-3: rgba(235,235,245,.34);
  --accent:  #64D2FF;
  --accent-bg: rgba(100,210,255,.10);
  --accent-line: rgba(100,210,255,.18);
  --sep:      rgba(255,255,255,.09);
  --panel:    rgba(255,255,255,.05);
  --panel-hi: rgba(255,255,255,.09);
  --panel-solid: #171A1F;          /* used when transparency is reduced */
  --chrome:   rgba(18,20,24,.66);
  --specular: rgba(255,255,255,.07);
  /* 30px read the same as 20px at this panel size and cost noticeably more:
     blur cost scales with radius, and every panel pays it. */
  --blur: blur(20px) saturate(180%);
  --alert-text: #FF9A92;
  --shadow: 0 10px 34px rgba(0,0,0,.34);
}

/* Dark is the house style, so it is the default even on a machine set to light
   — otherwise half the staff would see a different-looking portal. Light is a
   deliberate choice via the toggle (or data-theme="system" to follow the
   device). It is not an afterthought: no washes to blur means it is genuinely
   cheaper to draw, and it is easier to read in a bright room. */
@media (prefers-color-scheme: light) {
  :root[data-theme="system"] {
    --bg: #EAEAEE;      /* was #F5F5F7 — a notch darker so switching from dark is less of a flashbang, and white panels actually stand out (Jimmy, Aug 11) */
    --wash: none;
    --label:   #1D1D1F;
    --label-2: #6E6E73;
    --label-3: #8E8E93;
    --accent:  #007AFF;
    --accent-bg: rgba(0,122,255,.10);
    --accent-line: rgba(0,122,255,.20);
    --sep:      rgba(60,60,67,.13);
    --panel:    #FFFFFF;
    --panel-hi: #FFFFFF;
    --panel-solid: #FFFFFF;
    --chrome:   rgba(234,234,238,.80);
    --specular: transparent;
    --blur: saturate(180%) blur(20px);
    --alert-text: #B3261E;
    --btn-ink: #FFFFFF;   /* white on the solid-blue light accent */
    --shadow: 0 1px 2px rgba(0,0,0,.05), 0 8px 24px rgba(0,0,0,.06);
  }
}

/* Manual override — a user's explicit choice beats the device setting. */
:root[data-theme="light"] {
  --bg: #EAEAEE;      /* was #F5F5F7 — a notch darker so switching from dark is less of a flashbang, and white panels actually stand out (Jimmy, Aug 11) */
  --wash: none;
  --label:   #1D1D1F;
  --label-2: #6E6E73;
  --label-3: #8E8E93;
  --accent:  #007AFF;
  --accent-bg: rgba(0,122,255,.10);
  --accent-line: rgba(0,122,255,.20);
  --sep:      rgba(60,60,67,.13);
  --panel:    #FFFFFF;
  --panel-hi: #FFFFFF;
  --panel-solid: #FFFFFF;
  --chrome:   rgba(234,234,238,.80);
  --specular: transparent;
  --blur: saturate(180%) blur(20px);
  --alert-text: #B3261E;
  --btn-ink: #FFFFFF;   /* white on the solid-blue light accent */
  --shadow: 0 1px 2px rgba(0,0,0,.05), 0 8px 24px rgba(0,0,0,.06);
}

/* ---------------------------------------------------------------------------
   PERFORMANCE / ACCESSIBILITY ESCAPE HATCHES
   Frosted glass is the one genuinely expensive thing here: the browser has to
   re-blur what is behind every panel. Three ways out, all automatic:
     1. The OS "reduce transparency" setting (Apple has this; Windows too).
     2. Small screens — phones gain nothing from blur behind a full-width card
        and pay for it in scroll smoothness, so panels go solid under 700px.
     3. data-perf="solid" on <html>, which theme.js can set if a machine is
        struggling or a user picks it.
   In every case the layout is identical; only the material changes.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-transparency: reduce) {
  :root { --panel: var(--panel-solid); --panel-hi: var(--panel-solid);
          --blur: none; --specular: transparent; }
}
@media (max-width: 700px) {
  :root { --blur: none; --panel: var(--panel-solid); --panel-hi: var(--panel-solid); }
}
:root[data-perf="solid"] {
  --panel: var(--panel-solid); --panel-hi: var(--panel-solid);
  --blur: none; --specular: transparent; --wash: none;
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* --- base ----------------------------------------------------------------- */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="system"] { color-scheme: dark light; }
body {
  font-family: var(--font);
  font-size: var(--fs-body);
  color: var(--label);
  background: var(--bg);
  letter-spacing: -.01em;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; background: var(--wash);
  /* Own compositing layer. A fixed element that isn't composited gets REPAINTED
     on every scroll frame; a composited one is just re-composited by the GPU.
     Without this the gradient wash costs a full-viewport repaint per frame. */
  transform: translateZ(0);
  will-change: transform;
}

/* ---------------------------------------------------------------------------
   DENSE PAGES — <body class="dense">
   A month grid is several screens tall (the schedule page is ~5800px), and two
   things that are free on a short page are expensive on a long one: a blurred
   sticky bar has to re-blur what's behind it every scroll frame, and a gradient
   wash has to repaint. Calendars therefore trade the glass for a flat bar. The
   layout, spacing and colours are identical — only the material changes, the
   same deal as the reduced-transparency and phone rules above.
   ------------------------------------------------------------------------- */
body.dense::before { background: none; }
body.dense .chrome { background: var(--panel-solid); backdrop-filter: none; }
body.dense .toolbar, body.dense .group, body.dense .card, body.dense .panel,
body.dense .list-item, body.dense .strip { backdrop-filter: none; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
a { color: var(--accent); }

/* --- icons (sprite injected by icons.js) --------------------------------- */
svg.i {
  width: 20px; height: 20px; display: block; flex: none;
  stroke: currentColor; fill: none;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}
svg.i.sm { width: 16px; height: 16px; }
svg.i.lg { width: 24px; height: 24px; }

/* --- top bar -------------------------------------------------------------- */
.chrome {
  position: sticky; top: 0; z-index: 20;
  background: var(--chrome);
  backdrop-filter: var(--blur);
  border-bottom: 1px solid var(--sep);
}
.chrome-in {
  max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s5);
  min-height: 52px; display: flex; align-items: center; gap: var(--s4);
}
.brand {
  font-size: var(--fs-footnote); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--label);
  text-decoration: none;
}
.chrome-in .spacer { flex: 1; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-micro); font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); padding: 5px 10px;
  border-radius: var(--radius-sm);
}
.chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--label-3); display: block; }
.chip.live { color: var(--red); border-color: rgba(255,69,58,.45); }
.chip.live i { background: var(--red); }
.chip.ok { color: var(--green); } .chip.ok i { background: var(--green); }

/* theme toggle sits in the bar on every page */
.theme-toggle {
  width: 34px; height: 34px; display: grid; place-items: center;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius-sm);
  cursor: pointer; transition: color .18s, background .18s;
}
.theme-toggle:hover { color: var(--label); background: var(--panel-hi); }

/* --- page scaffolding ----------------------------------------------------- */
.wrap { max-width: var(--maxw); margin: 0 auto; padding: var(--s7) var(--s5) var(--s8); }
.wrap.narrow { max-width: 640px; }
h1 { font-size: 38px; line-height: 1.1; font-weight: 600; letter-spacing: -.03em; }
h2 { font-size: var(--fs-title-2); font-weight: 600; letter-spacing: -.02em; }
.lede { font-size: 18px; color: var(--label-2); margin-top: 9px; }
.back-link {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--accent); text-decoration: none;
  font-size: var(--fs-subhead); margin-bottom: var(--s4);
}
.back-link:hover { text-decoration: underline; }
.section { margin-top: var(--s7); }
.section-title, .group-title {
  font-size: var(--fs-micro); font-weight: 700; color: var(--label-3);
  text-transform: uppercase; letter-spacing: .13em;
  margin: var(--s5) 0 var(--s3);
}
/* First label on a page shouldn't be pushed down by that top margin. */
.wrap > .section-title:first-of-type { margin-top: 0; }

/* --- next-show strip ------------------------------------------------------ */
.strip {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 30px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s4) var(--s5);
  backdrop-filter: var(--blur); margin-top: var(--s5);
}
.strip::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--accent); }
.strip .spacer { flex: 1; }
.k { font-size: 10px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--label-3); }
.v { font-size: var(--fs-subhead); font-weight: 600; margin-top: 3px; }
.v.warn { color: var(--alert-text); }

/* --- tiles ---------------------------------------------------------------- */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--s3); }
.card {
  position: relative; display: block; overflow: hidden;
  text-decoration: none; color: inherit;
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s5) var(--s5) var(--s5);
  backdrop-filter: var(--blur); box-shadow: var(--shadow);
  transition: background .22s, transform .22s var(--ease), border-color .22s;
}
.card::after {
  content: ""; position: absolute; inset: 0; border-radius: var(--radius);
  pointer-events: none;
  background: linear-gradient(180deg, var(--specular), transparent 40%);
}
.card:hover { background: var(--panel-hi); transform: translateY(-2px); border-color: var(--accent-line); }
.card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s4); }
.card-icon {
  width: 38px; height: 38px; border-radius: var(--radius-sm);
  display: grid; place-items: center; color: var(--accent);
  background: var(--accent-bg); border: 1px solid var(--accent-line);
}
.card-icon img { width: 26px; height: 26px; border-radius: 6px; display: block; }
.card-title { font-size: var(--fs-callout); font-weight: 600; letter-spacing: -.015em; }
.card-desc { font-size: 14px; color: var(--label-2); line-height: 1.5; margin-top: 5px; }
.card-meta { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-caption); color: var(--label-3); margin-top: var(--s3); }
.tag { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--label-3); padding-top: 5px; }
.tag.ok { color: var(--green); }
.tag.warn { color: var(--amber); }
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-footnote); font-weight: 600; color: var(--green);
  background: rgba(48,209,88,.14); border: 1px solid rgba(48,209,88,.26);
  padding: 3px 10px; border-radius: var(--radius-pill); margin-top: var(--s3);
}
.pill i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
/* Status variants — used by the to-do banner, which previously set light-mode
   hex directly from JS and so broke the moment the page went dark. */
.pill.alert { color: var(--alert-text); background: rgba(255,69,58,.12); border-color: rgba(255,69,58,.28); }
.pill.warn  { color: var(--amber); background: rgba(255,159,10,.12); border-color: rgba(255,159,10,.28); }
.pill.quiet { color: var(--label-2); background: var(--panel-hi); border-color: var(--sep); }

/* --- needs-attention (bio not filled in, availability not submitted) ------
   A lit red edge rather than a solid red fill: over frosted glass a fill goes
   muddy and the text stops being readable. */
.card.needs-attention {
  border-color: rgba(255,69,58,.60);
  background: rgba(255,69,58,.09);
  box-shadow: 0 0 0 1px rgba(255,69,58,.24), 0 10px 34px rgba(255,69,58,.16);
}
.card.needs-attention:hover { border-color: rgba(255,95,85,.82); background: rgba(255,69,58,.14); }
.card.needs-attention .card-icon { color: #FF7A70; background: rgba(255,69,58,.14); border-color: rgba(255,69,58,.30); }

/* The tile people are usually looking for (Stream Collab) — green OUTLINE
   only, deliberately no fill, so it reads as "start here" not "problem".
   Applied by the dashboard's JS only when this person is on today's
   committed schedule (Portal.myShowsToday), never statically. */
.card.featured { border-color: rgba(48,209,88,.60); box-shadow: 0 0 0 1px rgba(48,209,88,.22), var(--shadow); }
.card.featured:hover { border-color: rgba(48,209,88,.85); background: var(--panel-hi); }

/* Stream Collab landing: the session row that matches a show YOU are
   scheduled on today gets the same green ring. */
.list-item.mine-today { border-color: rgba(48,209,88,.60); box-shadow: 0 0 0 1px rgba(48,209,88,.22); }
.needs-badge {
  position: absolute; top: var(--s4); right: var(--s4);
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--red); color: #fff;
  font-size: 17px; font-weight: 800; line-height: 26px; text-align: center;
  box-shadow: 0 2px 12px rgba(255,69,58,.55);
}
.needs-note { color: var(--alert-text); font-size: var(--fs-footnote); font-weight: 600; margin-top: 9px; }

/* --- grouped rows (settings-style lists, admin sections) ------------------ */
.group {
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); overflow: hidden; backdrop-filter: var(--blur);
}
.row {
  display: flex; align-items: center; gap: var(--s3);
  min-height: var(--tap); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--sep);
  text-decoration: none; color: inherit; transition: background .18s;
}
.row:last-child { border-bottom: none; }
.row:hover { background: var(--panel-hi); }
.row-icon {
  width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;
  color: var(--label-2); background: var(--panel-hi); flex: none;
}
.row-title { font-size: var(--fs-callout); font-weight: 500; flex: 1; }
.row-meta { font-size: 14px; color: var(--label-3); }
.chev { color: var(--label-3); font-size: var(--fs-callout); }
/* A row that isn't a link — a setting with a switch — shouldn't light up on
   hover, because nothing happens if you click the row itself. */
.row.plain { cursor: default; }
.row.plain:hover { background: none; }
.row-body { flex: 1; min-width: 0; padding-right: var(--s3); }
.row-sub { font-size: var(--fs-footnote); color: var(--label-3); margin-top: 2px; line-height: 1.45; }

/* --- switch ---------------------------------------------------------------
   The knob is white and the off-track is a neutral grey in BOTH themes: on
   light, tying either one to --panel-hi (which is white there) made the switch
   invisible when off. */
.toggle { position: relative; display: inline-block; width: 46px; height: 28px; flex: none; }
.toggle input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.toggle-slider {
  position: absolute; inset: 0; pointer-events: none;
  border-radius: var(--radius-pill); background: rgba(120,120,128,.36);
  border: 1px solid transparent; transition: background .2s;
}
.toggle-slider::before {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
  transition: transform .2s var(--ease);
}
.toggle input:checked + .toggle-slider { background: var(--accent); }
.toggle input:checked + .toggle-slider::before { transform: translateX(18px); }
.toggle input:focus-visible + .toggle-slider { border-color: var(--label); }

/* --- avatar --------------------------------------------------------------- */
.avatar {
  position: relative; width: 112px; height: 112px; border-radius: 50%;
  overflow: hidden; cursor: pointer; margin: 0 auto;
  border: 1px solid var(--sep); background: var(--panel-hi);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-overlay {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(0,0,0,.55); color: #fff;
  font-size: var(--fs-caption); font-weight: 600;
  opacity: 0; transition: opacity .2s;
}
.avatar:hover .avatar-overlay { opacity: 1; }
/* Quiet destructive action — underlined text, never a big red button. */
.link-danger {
  background: none; border: none; padding: 0; cursor: pointer;
  font-family: inherit; font-size: var(--fs-footnote);
  color: var(--alert-text); text-decoration: underline;
}
.link-danger:hover { opacity: .8; }

/* --- status badges --------------------------------------------------------
   Sharp-cornered, uppercase, and colour-coded by meaning. LIVE is the one that
   matters at a glance during a show, so it is the only one that gets a glow. */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; margin-left: 6px; vertical-align: middle;
  font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  border-radius: 6px; border: 1px solid transparent; white-space: nowrap;
}
.badge.live  { color: var(--red); background: rgba(255,69,58,.14); border-color: rgba(255,69,58,.42);
               box-shadow: 0 0 12px rgba(255,69,58,.25); }
.badge.ended { color: var(--label-3); background: var(--panel-hi); border-color: var(--sep); }
.badge.ext   { color: var(--green); background: rgba(48,209,88,.14); border-color: rgba(48,209,88,.32); }
.badge.info  { color: var(--accent); background: var(--accent-bg); border-color: var(--accent-line); }
.badge i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* --- list rows with actions (sessions, queues) ---------------------------- */
.list { display: flex; flex-direction: column; gap: var(--s2); }
.list-item {
  display: grid; grid-template-columns: 1fr auto auto; gap: var(--s3); align-items: center;
  padding: var(--s4); background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); backdrop-filter: var(--blur);
  transition: border-color .18s, transform .18s var(--ease);
}
.list-item:hover { border-color: var(--accent-line); transform: translateY(-1px); }
.list-item.is-ended { opacity: .55; }
.list-item .info { min-width: 0; }
.list-item .name { font-size: var(--fs-callout); font-weight: 600; margin-bottom: 4px;
                   white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list-item .meta { font-size: var(--fs-footnote); color: var(--label-2); }
.empty { text-align: center; padding: var(--s6) var(--s3); color: var(--label-3); font-size: var(--fs-subhead); }

/* --- page-level status banner --------------------------------------------
   One line at the top of a page telling you whether you need to do anything.
   Colour carries the meaning, so it must survive a theme switch — the old
   version set light-mode hex from JS and turned unreadable on dark. */
.banner {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5); border-radius: var(--radius);
  font-size: var(--fs-callout); font-weight: 600;
  color: var(--label); background: var(--panel);
  border: 1px solid var(--sep); backdrop-filter: var(--blur);
}
.banner.ok    { color: var(--green);      background: rgba(48,209,88,.10);  border-color: rgba(48,209,88,.28); }
.banner.alert { color: var(--alert-text); background: rgba(255,69,58,.10);  border-color: rgba(255,69,58,.30); }
.banner.warn  { color: var(--amber);      background: rgba(255,159,10,.10); border-color: rgba(255,159,10,.28); }

/* --- task cards (to-do) --------------------------------------------------
   Stacked: what to do, when it's due, then what you can do about it. Overdue
   gets a red edge; done fades back instead of vanishing, so you can still see
   that you did it. */
.task {
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s4) var(--s5);
  backdrop-filter: var(--blur); transition: border-color .18s, opacity .18s;
}
.task + .task { margin-top: var(--s2); }
.task.is-overdue { border-color: rgba(255,69,58,.42); background: rgba(255,69,58,.05); }
.task.is-done { opacity: .5; }
.task-text { font-size: var(--fs-callout); font-weight: 600; letter-spacing: -.01em; }
.task.is-done .task-text { text-decoration: line-through; color: var(--label-3); }
.task-meta { font-size: var(--fs-footnote); color: var(--label-2); margin-top: 5px; line-height: 1.5; }
.task-meta .overdue-label   { color: var(--alert-text); font-weight: 600; }
.task-meta .completed-label { color: var(--green); font-weight: 600; }
.task-actions { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s3); }
/* Row actions are secondary to the page's main action, so they sit smaller
   than a full .btn while staying above the 44px tap target on touch. */
.task-actions .btn { min-height: 38px; padding: 9px 18px; font-size: var(--fs-footnote); }

/* --- picker buttons (today's shows) -------------------------------------- */
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s2); }
.pick {
  display: block; width: 100%; text-align: left; padding: var(--s3) var(--s4);
  font-family: inherit; color: var(--label);
  background: var(--panel); border: 1px solid var(--sep); border-radius: var(--radius-sm);
  cursor: pointer; transition: border-color .18s, transform .18s var(--ease), background .18s;
}
.pick:hover { border-color: var(--accent-line); background: var(--panel-hi); transform: translateY(-2px); }
.pick .pick-name { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: var(--fs-subhead); }
.pick .dot { width: 10px; height: 10px; border-radius: 3px; background: var(--label-3); flex: none; }
.pick .pick-meta { font-size: var(--fs-caption); color: var(--label-2); margin-top: 3px; }

/* --- forms ---------------------------------------------------------------- */
.field { margin-bottom: var(--s5); }
.field label {
  display: block; font-size: var(--fs-caption); font-weight: 600;
  color: var(--label-2); margin-bottom: 6px;
  text-transform: uppercase; letter-spacing: .06em;
}
.field .optional { font-weight: 400; color: var(--label-3); text-transform: none; letter-spacing: 0; }
input[type="text"], input[type="email"], input[type="url"], textarea, select {
  width: 100%; min-height: var(--tap); padding: 12px 14px;
  font-family: inherit; font-size: var(--fs-callout);
  color: var(--label); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius-sm);
  transition: border-color .18s;
}
textarea { min-height: 96px; resize: vertical; line-height: 1.45; }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); }
/* Native select POPUPS: on Windows, Chromium can render the dropdown list with
   UA light-mode colours regardless of the page theme — unstyled options then
   inherit the select's near-white text onto a white popup and vanish. Painting
   each option explicitly keeps the list readable in either popup chrome. */
select option, select optgroup {
  background-color: var(--panel-solid);
  color: var(--label);
}
::placeholder { color: var(--label-3); }
/* A read-only field still has to look like it can't be typed in, or people
   try and think the page is broken. */
input[readonly], textarea[readonly] { color: var(--label-2); background: var(--panel-hi); cursor: default; }
input[readonly]:focus, textarea[readonly]:focus { border-color: var(--sep); }
input[type="checkbox"], input[type="radio"] {
  width: 18px; height: 18px; min-height: 0; padding: 0;
  accent-color: var(--accent); cursor: pointer; flex: none;
}
.check-row { display: flex; align-items: center; gap: var(--s2); min-height: var(--tap); }
/* Overrides the uppercase treatment of .field label — this one is a sentence
   sitting next to a checkbox, not a field name above an input. */
.check-row label {
  margin: 0; font-size: var(--fs-subhead); font-weight: 400; color: var(--label-2);
  text-transform: none; letter-spacing: 0; cursor: pointer;
}
.hint { font-size: var(--fs-caption); color: var(--label-3); margin-top: 5px; }
.label-row { display: flex; align-items: baseline; justify-content: space-between; }
.counter { font-size: var(--fs-caption); font-weight: 600; color: var(--label-3); }
.counter.warn { color: var(--amber); } .counter.over { color: var(--red); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--tap); padding: 12px 24px;
  font-family: inherit; font-size: var(--fs-callout); font-weight: 600;
  color: var(--btn-ink); background: var(--accent); border: none;
  border-radius: var(--radius-sm); cursor: pointer;
  text-decoration: none;          /* buttons are often <a> — never underline them */
  transition: opacity .18s, transform .18s var(--ease);
}
/* .btn text colour comes from --btn-ink (dark ink on the light-cyan dark-mode
   accent, white on the solid-blue light-mode accent). It is a VARIABLE, not a
   themed override rule, so tinted variants (.btn-remove, .btn-shows, …) can
   re-colour text at normal single-class specificity — a
   :root[data-theme="light"] .btn override out-specifies them and forces white
   text onto pale tinted fills. That bug shipped once; do not reintroduce it. */
.btn:hover { opacity: .9; transform: translateY(-1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.btn.block { width: 100%; }
.btn.secondary { color: var(--label); background: var(--panel); border: 1px solid var(--sep); }

.message { margin-top: var(--s3); padding: 10px 14px; border-radius: var(--radius-sm); font-size: var(--fs-subhead); display: none; }
.message.success { display: block; color: var(--green); background: rgba(48,209,88,.12); border: 1px solid rgba(48,209,88,.26); }
.message.error   { display: block; color: var(--alert-text); background: rgba(255,69,58,.12); border: 1px solid rgba(255,69,58,.28); }
.notice { padding: var(--s3) var(--s4); border-radius: var(--radius-sm); font-size: var(--fs-subhead); line-height: 1.5;
          color: var(--amber); background: rgba(255,159,10,.10); border: 1px solid rgba(255,159,10,.28); }
.panel { background: var(--panel); border: 1px solid var(--sep); border-radius: var(--radius);
         padding: var(--s5); backdrop-filter: var(--blur); }
/* Explanatory lead-in at the top of a form — accent-tinted so it reads as help,
   not as a warning. */
.intro {
  background: var(--accent-bg); border: 1px solid var(--accent-line);
  border-radius: var(--radius-sm); padding: var(--s3) var(--s4);
  font-size: var(--fs-subhead); line-height: 1.55; color: var(--label-2);
  margin-bottom: var(--s5);
}
/* Elevated-scope block (an admin acting on someone else's behalf). Amber, not
   red — in this theme red means something is wrong, and this isn't. */
.panel.admin-only-panel {
  padding: var(--s4); position: relative; overflow: hidden;
  border-color: rgba(255,159,10,.28); background: rgba(255,159,10,.06);
}
.panel.admin-only-panel::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--amber); }
.panel.admin-only-panel label { color: var(--amber); }
.stack > * + * { margin-top: var(--s2); }
.divider { border: none; border-top: 1px solid var(--sep); margin: var(--s5) 0; }
.preview-block {
  background: var(--panel); border: 1px solid var(--sep); border-radius: var(--radius-sm);
  padding: var(--s4); font-size: var(--fs-subhead); color: var(--label-2);
  white-space: pre-wrap; word-break: break-word; line-height: 1.5; min-height: 40px;
}

/* --- photo grid (My Photos, photo admin) ---------------------------------
   The caption bar stays dark in both themes on purpose — it sits on top of a
   photograph, not on the page. */
.thumb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s3); }
.thumb {
  position: relative; aspect-ratio: 1; overflow: hidden;
  border-radius: var(--radius-sm); border: 1px solid var(--sep);
  background: var(--panel); transition: border-color .18s;
}
.thumb:hover { border-color: var(--accent-line); }
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb-bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: var(--s2);
  padding: 6px 8px; background: rgba(0,0,0,.62); backdrop-filter: blur(8px);
}
.thumb-name {
  flex: 1; min-width: 0; color: #fff; font-size: var(--fs-caption);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.thumb-del {
  background: none; border: none; padding: 2px; cursor: pointer;
  color: #FF9A92; display: grid; place-items: center;
}
.thumb-del:hover { color: var(--red); }

/* --- special events (one-tap RSVPs + the admin response grid) ------------- */
.who { font-size: 14px; color: var(--label-2); margin-bottom: var(--s4); }
.who b { color: var(--label); }
.who select { width: auto; min-height: 34px; padding: 6px 10px; font-size: 14px; }
.role-btn {
  margin-left: 6px; padding: 4px 12px; cursor: pointer;
  font-family: inherit; font-size: var(--fs-caption); font-weight: 600;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius-pill);
}
.role-btn.active { color: var(--accent); background: var(--accent-bg); border-color: var(--accent-line); }

.view-tabs { display: flex; gap: var(--s2); margin: var(--s1) 0 var(--s4); flex-wrap: wrap; }
.view-tab {
  flex: 1 1 180px; padding: 13px var(--s4); text-align: center; cursor: pointer;
  font-family: inherit; font-size: var(--fs-subhead); font-weight: 600;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius);
  transition: border-color .15s, color .15s;
}
.view-tab:hover { border-color: var(--accent-line); color: var(--label); }
.view-tab.active { color: var(--accent); background: var(--accent-bg); border-color: var(--accent-line); }
.view-tab .vt-count { display: block; margin-top: 3px; font-size: var(--fs-caption); font-weight: 600; color: var(--amber); }
.view-tab .vt-count.done { color: var(--green); }

/* These two are the page's "you still owe us answers" / "you're done" states. */
.awaiting-banner {
  padding: var(--s3) var(--s4); border-radius: var(--radius); margin-bottom: 6px;
  font-size: var(--fs-subhead); font-weight: 600;
  color: var(--amber); background: rgba(255,159,10,.10); border: 1px solid rgba(255,159,10,.28);
}
.all-done {
  padding: var(--s3) var(--s4); border-radius: var(--radius); margin-bottom: 6px;
  font-size: var(--fs-subhead); font-weight: 600;
  color: var(--green); background: rgba(48,209,88,.10); border: 1px solid rgba(48,209,88,.28);
}

.evt-row {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s4); margin-bottom: var(--s2);
  background: var(--panel); border: 1px solid var(--sep); border-radius: var(--radius);
}
.evt-row.pending { border-style: dashed; border-color: rgba(255,159,10,.5); }
.evt-info { flex: 1 1 200px; min-width: 180px; padding-left: var(--s3); border-left: 3px solid var(--evc, var(--accent)); }
.evt-date { font-size: var(--fs-caption); font-weight: 700; color: var(--label-3); text-transform: uppercase; letter-spacing: .08em; }
.evt-name { font-size: var(--fs-callout); font-weight: 600; color: var(--label); }
.evt-time { font-size: var(--fs-footnote); color: var(--label-2); }
.evt-note { font-size: var(--fs-caption); color: var(--label-3); font-style: italic; margin-top: 3px; }

/* Yes / Maybe / No. Unselected they're quiet; the chosen one fills in, because
   the answer has to be readable at a glance down a list of events. */
.answer-btns { display: flex; gap: var(--s2); }
.abtn {
  padding: 10px 20px; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 700;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius-sm);
  transition: color .12s, background .12s, border-color .12s;
}
.abtn:hover { color: var(--label); border-color: var(--accent-line); }
.abtn.yes.sel,   .abtn.yes:hover   { background: var(--green); border-color: var(--green); color: #08240F; }
.abtn.maybe.sel, .abtn.maybe:hover { background: var(--amber); border-color: var(--amber); color: #2B1A00; }
.abtn.no.sel,    .abtn.no:hover    { background: var(--red);   border-color: var(--red);   color: #FFF; }
.save-status { text-align: center; font-size: var(--fs-footnote); color: var(--label-3); min-height: 20px; margin-top: var(--s2); }
.save-status.ok  { color: var(--green); }
.save-status.err { color: var(--alert-text); }

.admin-box { margin-top: var(--s6); padding-top: var(--s4); border-top: 1px solid var(--sep); }
.tbl-wrap { overflow-x: auto; border: 1px solid var(--sep); border-radius: var(--radius-sm); }
table.responses { width: 100%; border-collapse: collapse; font-size: var(--fs-footnote); background: var(--panel-solid); }
.responses th, .responses td { padding: 8px 10px; text-align: center; border: 1px solid var(--sep); }
.responses th {
  position: sticky; top: 0; white-space: nowrap; background: var(--panel-hi);
  font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--label-3);
}
.responses tr:nth-child(even) td { background: rgba(255,255,255,.02); }
.responses td.pname {
  position: sticky; left: 0; text-align: left; white-space: nowrap;
  font-weight: 600; color: var(--label); background: var(--panel-hi);
}
/* Click-to-highlight: a scratchpad while placing people on events. */
.responses td.cellc { cursor: pointer; }
.responses td.cellc:hover { box-shadow: inset 0 0 0 2px var(--accent-line); }
.responses td.cellc.hl, .responses tr:nth-child(even) td.cellc.hl {
  background: var(--accent-bg); box-shadow: inset 0 0 0 2px var(--accent);
}
.hl-hint { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
           font-size: var(--fs-caption); color: var(--label-3); margin: var(--s2) 2px var(--s3); }
.hl-clear {
  padding: 3px 12px; cursor: pointer; font-family: inherit;
  font-size: var(--fs-caption); font-weight: 600;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius-pill);
}
.hl-clear:hover { color: var(--label); border-color: var(--accent-line); }
.th-del { padding: 0 3px; border-radius: 4px; font-weight: 700; color: var(--label-3); }
.th-del:hover { color: #fff; background: var(--red); }
.cellv { display: inline-block; min-width: 70px; padding: 4px 10px; border-radius: 6px;
         font-size: var(--fs-caption); font-weight: 700; }
.cv-yes   { color: var(--green);      background: rgba(48,209,88,.14); }
.cv-no    { color: var(--alert-text); background: rgba(255,69,58,.14); }
.cv-maybe { color: var(--amber);      background: rgba(255,159,10,.14); }
.cv-await { color: var(--label-3); background: var(--panel-hi); font-weight: 600; font-style: italic; }
.cv-na    { color: var(--label-3); opacity: .5; }
.chiprow { margin: var(--s2) 0 var(--s3); }
/* This page's .chip is a name pill, not the top-bar status chip, so undo the
   uppercase treatment when it appears in a chiprow. */
.chiprow .chip { margin: 2px 6px 2px 0; text-transform: none; letter-spacing: 0;
                 font-size: var(--fs-caption); font-weight: 600; }
.no-reply-line { font-size: var(--fs-caption); color: var(--label-3); margin: 2px 0 var(--s2); }
.no-reply-line b { color: var(--label-2); }

/* --- tables (admin, schedules) ------------------------------------------- */
table.data { width: 100%; border-collapse: collapse; background: var(--panel);
             border: 1px solid var(--sep); border-radius: var(--radius); overflow: hidden; }
table.data th {
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--label-3); text-align: left; padding: 10px var(--s4);
  border-bottom: 1px solid var(--sep); background: var(--panel-hi);
}
table.data td { font-size: 14px; padding: 12px var(--s4); border-bottom: 1px solid var(--sep); }
table.data tr:last-child td { border-bottom: none; }
table.data tr:hover td { background: var(--panel-hi); }
table.data td.right { text-align: right; color: var(--label-2); font-size: var(--fs-footnote); }

/* --- calendars (schedule, schedule admin, availability) -------------------
   A dense grid is the one place frosted glass is the wrong material: 200-odd
   cells each re-blurring the page behind them is the most expensive thing this
   stylesheet could ask for, and it buys nothing when the cells tile edge to
   edge. So calendars use SOLID panels and 1px hairlines throughout.

   Show blocks keep their per-show colour, which arrives inline from JS as an
   8%-alpha tint plus a full-strength left rule. That works on either theme
   because the tint is faint enough to sit over any background and the rule,
   not the fill, is what identifies the show. */
.cal-wrapper { overflow-x: auto; }
.cal-grid, .compact-grid {
  display: grid; grid-template-columns: repeat(7, minmax(140px, 1fr));
  gap: 1px; background: var(--sep);
  border: 1px solid var(--sep); border-radius: var(--radius-sm); overflow: hidden;
}
.cal-header, .compact-header {
  background: var(--panel-hi); color: var(--label-3);
  padding: 8px 4px; text-align: center;
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}
.cal-cell, .compact-cell { background: var(--panel-solid); padding: 5px; position: relative; }
.cal-cell { min-height: 140px; }
/* No transition here on purpose: this rule is armed on ~170 cells at once and
   moving the mouse across a calendar would animate a repaint per cell. */
.cal-cell:hover { background: var(--panel-hi); }
.compact-cell { min-height: 120px; padding: 4px; display: flex; flex-direction: column; gap: 2px; }
/* Days outside the month: recede, don't disappear. */
.cal-cell.empty, .compact-cell.empty { background: var(--bg); }
.day-num, .compact-day-num {
  font-size: 15px; font-weight: 700; color: var(--label-2);
  font-variant-numeric: tabular-nums; margin-bottom: 4px;
}
.compact-day-num { font-size: 13px; padding: 0 2px; margin-bottom: 1px; }
.day-num.muted, .compact-day-num.muted { color: var(--label-3); font-weight: 500; }

/* A show is a SOLID colour block. On dark, a faint tint of a hue just reads as
   grey mush — the colour has to carry. `background` and `color` arrive inline
   from Portal.showColor(), which desaturates the show's hue for the current
   theme and picks the text colour by measured contrast. Everything inside the
   block therefore inherits, and steps back using opacity rather than its own
   grey, which would fight the fill. */
.show-block {
  border-radius: 6px; padding: 5px 7px; margin-bottom: 4px;
  font-size: 12px; line-height: 1.4;
  background: var(--panel-hi); color: var(--label);
}
.show-name {
  font-weight: 700; font-size: 11px; letter-spacing: .04em;
  text-transform: uppercase; color: inherit;
}
.show-time { font-weight: 600; font-size: 11px; color: inherit; opacity: .80; }
.show-slot { font-size: 11px; color: inherit; }
.show-slot .label { color: inherit; opacity: .62; font-size: 10px; }
.show-slot .name { font-weight: 600; color: inherit; }
.show-slot .name.tbd { color: inherit; opacity: .55; font-style: italic; }
/* "This one is you" — the whole point of opening the schedule. Inverts against
   whatever colour the block happens to be: the chip takes the text colour and
   the text takes the block's own background (passed in as --blk), so it pops on
   every show colour instead of relying on one fixed highlighter that only
   worked on white. */
/* Both colours must be named explicitly. `background: currentColor` cannot work
   here: currentColor resolves to the element's OWN color, which this same rule
   overrides, so the chip came out invisible — text and fill identical. --ink and
   --blk are the block's text and background, passed in inline. */
.show-slot .name.highlighted, .ct-highlighted {
  background: var(--ink, var(--label)); color: var(--blk, var(--bg));
  font-weight: 800; padding: 0 4px; border-radius: 3px;
}

.compact-cal { margin-bottom: var(--s5); }
/* Title and time stack on separate lines. Side by side they did not fit a
   ~130px column and hard-clipped mid-word ("The Sunday Show 1:00 PN"); stacked,
   the title gets the full width and only ever ellipsises at the end. */
.compact-show {
  position: relative; flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
  padding: 4px 6px; border-radius: 5px;
  background: var(--panel-hi); color: var(--label);
  line-height: 1.25; cursor: pointer; overflow: hidden;
}
.compact-show .cs-name {
  font-weight: 700; font-size: 11px; color: inherit;
  max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.compact-show .cs-time { font-weight: 600; font-size: 10px; color: inherit; opacity: .82; }
.compact-show .cs-details { display: none; }
/* You're on this one. A ring rather than a colour change, so the show's own
   colour still reads. */
.compact-show.person-on {
  outline: 2px solid var(--label); outline-offset: -2px; z-index: 1;
  box-shadow: 0 0 0 1px var(--bg);
}
.compact-show.expanded {
  white-space: normal; overflow: visible; z-index: 2;
  flex-direction: column; align-items: flex-start; padding: 6px 8px;
}
.compact-show.expanded .cs-details { display: block; margin-top: 3px; font-size: 10px; line-height: 1.5; }
.compact-show.expanded .cs-details .ct-slot { color: inherit; opacity: .62; }
.compact-show.expanded .cs-details .ct-val { color: inherit; font-weight: 600; }

/* Channel / section heading inside a calendar page */
.channel-title, .compact-cal-title {
  position: relative; text-align: center;
  font-size: var(--fs-callout); font-weight: 600; letter-spacing: -.01em;
  color: var(--label); background: var(--panel);
  border: 1px solid var(--sep); border-left: 2px solid var(--accent);
  border-radius: var(--radius-sm); padding: 9px var(--s4); margin-bottom: var(--s3);
}
/* The schedule stacks one full month grid per channel, so three of the four are
   off screen at any time. content-visibility lets the browser skip laying out
   and painting them until they scroll close, which is the single biggest win on
   this page. contain-intrinsic-size keeps the scrollbar from jumping: `auto`
   means "remember the real height once you've measured it", with ~900px as the
   first guess (six rows at 140px plus the heading). */
.channel-section {
  margin-bottom: var(--s6);
  content-visibility: auto;
  contain-intrinsic-size: auto 900px;
}

/* --- availability calendar (the click-a-day form) -------------------------
   Unlike the schedule, the answers here are SOLID fills. That is deliberate:
   the whole job of this page is to glance at a month and see your yeses,
   noes and maybes, so the colour has to carry across the grid, not whisper.
   Bright fills (green, amber) take dark text; red takes white. */
.calendar {
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s3);
  margin-bottom: var(--s6); overflow-x: auto;
}
.calendar-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px;
  background: var(--sep); border: 1px solid var(--sep);
  border-radius: var(--radius-sm); overflow: hidden; min-width: 980px;
}
.day-header {
  display: flex; align-items: center; justify-content: center;
  min-height: 38px; padding: 8px 4px; text-align: center;
  background: var(--panel-hi); color: var(--label-3);
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}
.day {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  min-height: 130px; height: auto; position: relative; cursor: pointer;
  background: var(--panel-solid); color: var(--label);
  transition: background .15s;
}
/* Hover must never hide the answer. This is scoped with :not() rather than
   left to source order — .day:hover sits ABOVE the colour rules while
   .sunday-section:hover sat BELOW them, which is exactly why clicking a
   Sunday/split cell showed no colour until you moved the mouse away while
   plain days were fine. Equal specificity, so whichever came last won. */
.day:not(.green):not(.red):not(.yellow):hover { background: var(--panel-hi); }
.day:hover { z-index: 2; }
.day.other-month { background: var(--bg); color: var(--label-3); cursor: not-allowed; }
.day.other-month:hover { background: var(--bg); }
/* The three answers. */
.day.green,  .sunday-section.green  { background: var(--green); color: #08240F; }
.day.red,    .sunday-section.red    { background: var(--red);   color: #FFF; }
.day.yellow, .sunday-section.yellow { background: var(--amber); color: #2B1A00; }
.day-number, .split-date-header, .sunday-date {
  width: 100%; height: 28px; line-height: 28px;
  font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--sep);
}
.show-info, .sunday-show-info { padding: 4px 5px; width: 100%; }
/* Scoped to the availability calendar's .day cells. These class names are ALSO
   used by the schedule's colour cards (.show-block) — unscoped, these muted
   greys silently overrode the cards' WCAG-picked ink (same specificity, later
   in the file) and made every show time unreadable on colour. Keep the scope. */
.day .show-name, .sunday-show-name {
  font-size: 11px; font-weight: 700; line-height: 1.3;
  text-transform: uppercase; letter-spacing: .03em; color: var(--label-2);
}
.day .show-time, .sunday-show-time { font-size: 11px; font-weight: 600; color: var(--label-3); }
/* Once a day is answered, its fill carries the meaning, so the show text has to
   sit on that fill rather than keep its own muted grey. */
.day.green .show-name, .day.red .show-name, .day.yellow .show-name,
.day.green .show-time, .day.red .show-time, .day.yellow .show-time,
.sunday-section.green .sunday-show-name, .sunday-section.red .sunday-show-name,
.sunday-section.yellow .sunday-show-name,
.sunday-section.green .sunday-show-time, .sunday-section.red .sunday-show-time,
.sunday-section.yellow .sunday-show-time { color: inherit; opacity: .92; }
/* Days with two shows split into stacked halves, each answered separately. */
.split-sections-area { display: flex; flex-direction: column; width: 100%; flex: 1; }
.sunday-section {
  flex: 1; display: flex; flex-direction: column; justify-content: center;
  padding: 4px 5px; cursor: pointer; background: var(--panel-solid);
  transition: background .15s;
}
.sunday-section + .sunday-section { border-top: 1px solid var(--sep); }
.sunday-section:not(.green):not(.red):not(.yellow):hover { background: var(--panel-hi); }
/* An answered cell still reacts to the pointer, but by brightening its own
   colour instead of being painted over, so the answer is never obscured. */
.day.green:hover, .day.red:hover, .day.yellow:hover,
.sunday-section.green:hover, .sunday-section.red:hover, .sunday-section.yellow:hover {
  filter: brightness(1.14);
}
.clear-btn {
  position: absolute; top: 2px; right: 2px; z-index: 3;
  width: 20px; height: 20px; padding: 0; line-height: 1;
  display: grid; place-items: center;
  font-family: inherit; font-size: 13px; font-weight: 700;
  color: var(--label-2); background: var(--panel-hi);
  border: 1px solid var(--sep); border-radius: 5px; cursor: pointer;
}
.clear-btn:hover { color: var(--label); border-color: var(--accent-line); }
/* Legend chips in the instructions panel. */
.key { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px;
       border-radius: var(--radius-sm); font-size: var(--fs-footnote); font-weight: 600; }
.key.yes   { background: var(--green); color: #08240F; }
.key.no    { background: var(--red);   color: #FFF; }
.key.maybe { background: var(--amber); color: #2B1A00; }
.key.unset { background: var(--panel-solid); color: var(--label-2); border: 1px solid var(--sep); }

/* --- toolbar (month pickers, exports) ------------------------------------ */
.toolbar {
  display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center;
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s3) var(--s4);
  backdrop-filter: var(--blur);
}
.toolbar .spacer { flex: 1; }
.toolbar select, .toolbar input[type="text"] { width: auto; min-height: 38px; padding: 8px 12px; font-size: 14px; }
.tbtn, .ics-btn {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 38px; padding: 8px 14px;
  font-family: inherit; font-size: 14px; font-weight: 500;
  color: var(--label); background: var(--panel-hi);
  border: 1px solid var(--sep); border-radius: var(--radius-sm);
  cursor: pointer; text-decoration: none;
  transition: border-color .18s, background .18s;
}
.tbtn:hover, .ics-btn:hover { border-color: var(--accent-line); background: var(--panel); }
.tbtn.accent { color: var(--accent); border-color: var(--accent-line); background: var(--accent-bg); }
.tbtn.sm, .ics-btn { min-height: 30px; padding: 4px 11px; font-size: var(--fs-caption); }

/* The person-by-person drawer on the schedule page. JS toggles .visible, so the
   hidden state has to live here rather than in an inline style. */
.host-list-panel { display: none; max-height: 340px; overflow-y: auto; }
.host-list-panel.visible { display: block; }
.host-list-item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: 9px var(--s4); border-bottom: 1px solid var(--sep); font-size: 14px;
}
.host-list-item:last-child { border-bottom: none; }
/* JS writes <div class="loading"> in a few places while fetching. */
.loading { text-align: center; padding: var(--s6) var(--s3); color: var(--label-3); font-size: var(--fs-subhead); }
/* Pill row for "jump to my next show" style shortcuts */
.pill-row { display: flex; gap: 6px; flex-wrap: wrap; }
.pill-btn {
  font-family: inherit; font-size: var(--fs-caption); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--label-2); background: var(--panel);
  border: 1px solid var(--sep); border-radius: var(--radius-pill);
  padding: 5px 13px; cursor: pointer; transition: color .18s, border-color .18s;
}
.pill-btn:hover { color: var(--label); border-color: var(--accent-line); }
.pill-btn.active {
  color: var(--on-fill); background: var(--accent); border-color: var(--accent);
}
/* Count badge inside a pill — "how many of these are mine". Inherits the pill's
   ink so it stays readable on both the plain and the active (accent) fill. */
.pill-btn .cnt {
  display: inline-block; min-width: 17px; margin-left: 7px; padding: 0 4px;
  font-size: 11px; font-weight: 700; line-height: 16px; text-align: center;
  letter-spacing: 0; border-radius: var(--radius-pill);
  color: inherit; background: rgba(120,120,128,.28);
}
.pill-btn.active .cnt { background: rgba(0,0,0,.20); }
.pill-btn .cnt.zero { opacity: .45; font-weight: 600; }

/* Tabbed calendar views: every calendar occupies the SAME space, one at a time,
   instead of a long scroll. All views stay in the DOM so printing can still
   emit the whole month (see the print block). */
.cal-view { display: none; }
.cal-view.active { display: block; }
.cal-empty {
  padding: var(--s7) var(--s5); text-align: center; color: var(--label-2);
  background: var(--panel); border: 1px solid var(--sep); border-radius: var(--radius);
}
.cal-empty strong { display: block; margin-bottom: 6px; color: var(--label); font-size: var(--fs-callout); }

/* --- print ----------------------------------------------------------------
   Staff print the month and pin it up. Force a white page regardless of theme
   and drop the on-screen chrome. */
@media print {
  :root { --bg: #fff; --panel: #fff; --panel-solid: #fff; --panel-hi: #fff;
          --wash: none; --blur: none; --label: #111; --label-2: #444; --label-3: #777;
          --sep: #ccc; --shadow: none; }
  body::before { display: none; }
  .chrome, .toolbar, .back-link, .pill-row, .theme-toggle, .no-print { display: none !important; }
  .wrap { padding: 0; max-width: none; }
  .cal-grid, .compact-grid { grid-template-columns: repeat(7, 1fr); }
  .show-block { page-break-inside: avoid; }
  .compact-cal { display: none; }
  /* On screen the calendars are tabs (one visible). On paper you want the whole
     month, so every view comes back — including the ones the tabs have hidden. */
  .cal-view { display: block !important; }
  .cal-view[data-view="mine"] .compact-cal { display: block; }   /* keep YOUR month on the printout */
  /* Off-screen sections are skipped for speed while scrolling. Printing must
     force every one of them back, or the months below the fold come out blank. */
  .channel-section { content-visibility: visible; contain-intrinsic-size: auto; page-break-inside: avoid; }
}

/* ===========================================================================
   COMPATIBILITY LAYER
   ---------------------------------------------------------------------------
   These class names were the portal's de facto shared vocabulary — the same
   .form-section, .btn-primary, .modal, .msg appeared in page after page, each
   with its own private copy of the rules. Now that the per-page stylesheets are
   gone they need one home, so the pages that use them keep their layout instead
   of collapsing into unstyled markup.

   New work should prefer the named components above (.panel, .btn, .banner,
   .group/.row). This block exists so 20-odd existing tool pages keep working;
   it is not a pattern to copy.
   ========================================================================= */

/* Safety net. A button whose class has no rule would otherwise render as a
   light OS-default button on a dark page. Bare element selector, so any themed
   class still wins. */
button, input[type="button"], input[type="submit"] {
  font-family: inherit; font-size: 14px; font-weight: 600;
  min-height: 36px; padding: 8px 14px; cursor: pointer;
  color: var(--label); background: var(--panel-hi);
  border: 1px solid var(--sep); border-radius: var(--radius-sm);
}
button:hover { border-color: var(--accent-line); }

/* --- containers ---------------------------------------------------------- */
.form-section, .admin-content, .add-form, .create-panel, .photo-section, .create-card {
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s5); margin-bottom: var(--s5);
}
.form-group { margin-bottom: var(--s4); }
.form-group label, .form-row label {
  display: block; margin-bottom: 6px;
  font-size: var(--fs-caption); font-weight: 600; color: var(--label-2);
  text-transform: uppercase; letter-spacing: .06em;
}
.form-row { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: flex-end; margin-bottom: var(--s4); }
.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--s3); }
.tablewrap, .tbl-wrap { overflow-x: auto; border: 1px solid var(--sep); border-radius: var(--radius-sm); }
.actions, .edit-row { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }
.footer { margin-top: var(--s7); padding-top: var(--s4); border-top: 1px solid var(--sep);
          font-size: var(--fs-caption); color: var(--label-3); text-align: center; }
.footer a { color: var(--label-2); text-decoration: none; }

/* --- buttons -------------------------------------------------------------
   All the ad-hoc button names land on the same shape; only the colour differs,
   and only where the colour carries meaning (destructive, confirm). */
.btn-primary, .btn-save, .btn-publish, .open-btn, .edit-btn, .person-btn,
.quick-btn, .action-btn, .filter-btn, .today-btn, .jump-btn, .btn-sm,
.btn-success, .btn-danger, .btn-remove, .btn-cancel, .delete-btn, .sign-out-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 38px; padding: 9px 16px;
  font-family: inherit; font-size: 14px; font-weight: 600;
  color: var(--label); background: var(--panel-hi);
  border: 1px solid var(--sep); border-radius: var(--radius-sm);
  cursor: pointer; text-decoration: none;
  transition: border-color .18s, background .18s, opacity .18s;
}
.btn-primary:hover, .btn-save:hover, .btn-publish:hover, .open-btn:hover,
.edit-btn:hover, .person-btn:hover, .quick-btn:hover, .action-btn:hover,
.filter-btn:hover, .today-btn:hover, .jump-btn:hover, .btn-sm:hover,
.btn-success:hover, .btn-danger:hover, .btn-remove:hover, .btn-cancel:hover,
.delete-btn:hover, .sign-out-btn:hover { border-color: var(--accent-line); background: var(--panel); }
.btn-primary, .btn-publish, .btn-save { color: var(--btn-ink); background: var(--accent); border-color: transparent; }
.btn-success { color: #08240F; background: var(--green); border-color: transparent; }
.btn-danger, .btn-remove, .delete-btn { color: var(--alert-text); background: rgba(255,69,58,.10); border-color: rgba(255,69,58,.28); }
.btn-danger:hover, .btn-remove:hover, .delete-btn:hover { color: var(--on-fill); background: var(--red); border-color: var(--red); }
.btn-sm, .filter-btn, .quick-btn { min-height: 30px; padding: 5px 12px; font-size: var(--fs-caption); }
.filter-btn.active, .today-btn.active, .quick-btn.active {
  color: var(--accent); background: var(--accent-bg); border-color: var(--accent-line);
}
button:disabled, .btn-primary:disabled { opacity: .5; cursor: not-allowed; }

/* --- messages and status ------------------------------------------------- */
.msg, .success-message, .status-msg, .status-line, .error-message {
  padding: 10px 14px; border-radius: var(--radius-sm);
  font-size: var(--fs-subhead); line-height: 1.5;
}
.success-message, .msg.success, .status-msg.success, .status-line.ok, .saved {
  color: var(--green); background: rgba(48,209,88,.12); border: 1px solid rgba(48,209,88,.26);
}
.error-message, .msg.error, .status-msg.error, .status-line.err {
  color: var(--alert-text); background: rgba(255,69,58,.12); border: 1px solid rgba(255,69,58,.28);
}
.stale, .status-line.stale { color: var(--amber); background: rgba(255,159,10,.10); border: 1px solid rgba(255,159,10,.28); }
.saving { color: var(--label-3); }
.empty-msg, .today-empty, .placeholder {
  text-align: center; padding: var(--s5) var(--s3);
  color: var(--label-3); font-size: var(--fs-subhead);
}
.note, .hint-text, .proj-desc { font-size: var(--fs-footnote); color: var(--label-2); line-height: 1.5; }
.count, .count-badge, .tally {
  display: inline-block; padding: 2px 8px; border-radius: var(--radius-pill);
  font-size: var(--fs-caption); font-weight: 700;
  color: var(--label-2); background: var(--panel-hi); border: 1px solid var(--sep);
}
.role-badge, .exp-tag, .special-chip {
  display: inline-block; padding: 2px 8px; border-radius: 6px;
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent); background: var(--accent-bg); border: 1px solid var(--accent-line);
}
.section-label, .today-label, .label-strip, .todo-sec-title, .proj-title, .photo-header {
  font-size: var(--fs-micro); font-weight: 700; color: var(--label-3);
  text-transform: uppercase; letter-spacing: .13em; margin: var(--s5) 0 var(--s3);
}
.legend { display: flex; gap: var(--s3); flex-wrap: wrap; font-size: var(--fs-caption); color: var(--label-2); }
.time, .se-time { font-size: var(--fs-footnote); color: var(--label-2); font-variant-numeric: tabular-nums; }

/* --- modals ---------------------------------------------------------------
   .open is the state class every page used to toggle these. It has to live here
   or the dialogs would never appear. */
.modal-overlay {
  position: fixed; inset: 0; z-index: 60; display: none;
  align-items: center; justify-content: center; padding: var(--s4);
  background: rgba(0,0,0,.62); backdrop-filter: blur(6px);
}
.modal-overlay.open, .modal-overlay.visible { display: flex; }
.modal {
  width: 100%; max-width: 520px; max-height: 86vh; overflow-y: auto;
  background: var(--panel-solid); border: 1px solid var(--sep);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.modal-header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) var(--s5); border-bottom: 1px solid var(--sep);
  font-size: var(--fs-title-3); font-weight: 600;
}
.modal-close {
  background: none; border: none; cursor: pointer; padding: 4px;
  font-family: inherit; font-size: 20px; line-height: 1; color: var(--label-3);
}
.modal-close:hover { color: var(--label); }
.modal-body { padding: var(--s5); }
.modal-footer { display: flex; gap: var(--s2); justify-content: flex-end;
                padding: var(--s4) var(--s5); border-top: 1px solid var(--sep); }

/* --- session / "today" lists (screener, duelogues, chat queue) ------------ */
.sessions, .session-list, .today-grid, .today-shows, .person-grid, .areagrid, .date-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--s2);
}
.session, .item, .area, .proj, .channel-row, .crew-row, .photo-card, .show-card {
  background: var(--panel); border: 1px solid var(--sep);
  border-radius: var(--radius); padding: var(--s3) var(--s4);
  transition: border-color .18s;
}
.session:hover, .item:hover, .area:hover, .proj:hover, .show-card:hover { border-color: var(--accent-line); }
.session-info, .crew-info, .proj-head { min-width: 0; }
.session-name, .today-btn-name, .crew-name, .sc-name {
  font-size: var(--fs-callout); font-weight: 600; color: var(--label);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.session-meta, .today-btn-meta, .sc-header, .sc-anon, .phase, .a-em {
  font-size: var(--fs-footnote); color: var(--label-2);
}
.today-btn-color, .show-color-bar, .crew-avatar {
  width: 10px; height: 10px; border-radius: 3px; background: var(--label-3); flex: none;
}
.crew-avatar { width: 34px; height: 34px; border-radius: 50%; overflow: hidden; }
.crew-avatar img { width: 100%; height: 100%; object-fit: cover; }
.today-section, .todo-section, .show-grid, .photo-grid, .filters, .chiprow, .pill-group {
  display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center;
}
.today-section, .todo-section { display: block; margin-top: var(--s5); }
.show-grid, .photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s3); }

/* --- survey / questionnaire (special.html) -------------------------------- */
.survey-q { margin-bottom: var(--s6); padding-bottom: var(--s6); border-bottom: 1px solid var(--sep); }
.survey-q:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; }
.question, .se-title, .panel-title, .date-card-title {
  font-size: var(--fs-title-3); font-weight: 600; color: var(--label);
  line-height: 1.45; margin-bottom: var(--s4);
}
.survey-textarea, .survey-notes { width: 100%; min-height: 92px; }
.survey-notes { margin-top: var(--s3); }
.section-divider { border: none; border-top: 1px solid var(--sep); margin: var(--s6) 0; }
/* .pill is already a status chip above; inside a pill-group it is a choice. */
.pill-group { display: flex; gap: var(--s3); flex-wrap: wrap; }
.pill-group .pill {
  margin-top: 0; cursor: pointer;
  color: var(--label-2); background: var(--panel); border: 1px solid var(--sep);
}
.pill-group .pill:hover { color: var(--label); border-color: var(--accent-line); }
.pill-group .pill.selected, .pill-group .pill.active {
  color: var(--accent); background: var(--accent-bg); border-color: var(--accent-line);
}

/* --- labelled field cluster (shows.html, linecon-admin) ------------------- */
.show-field { display: flex; flex-direction: column; gap: 3px; }
.show-field label, .role-label, .when {
  font-size: var(--fs-micro); font-weight: 600; color: var(--label-3);
  text-transform: uppercase; letter-spacing: .08em;
}
.show-field input, .show-field select { min-height: 36px; padding: 7px 10px; font-size: 14px; }
.show-field input[type="color"] { width: 46px; padding: 2px; cursor: pointer; }
.show-field input[type="number"] { width: 62px; text-align: center; }
.show-actions, .show-list, .role-section, .assignment-panel, .people-groups,
.link-options, .quick-select, .phases, .chips {
  display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center;
}
.show-list, .people-groups, .link-options { display: block; }
.link-row { display: flex; gap: var(--s2); align-items: center; margin-bottom: var(--s2); }
.time-picker, .ampm-toggle {
  min-height: 36px; padding: 7px 10px; cursor: pointer;
  font-family: inherit; font-size: 14px; color: var(--label);
  background: var(--panel); border: 1px solid var(--sep); border-radius: var(--radius-sm);
}
.ampm-toggle:hover, .time-picker:hover { border-color: var(--accent-line); }
.event-detail, .selected-name, .bind-badge, .user-info, .txt, .gcount, .blank {
  font-size: var(--fs-footnote); color: var(--label-2);
}
.bind-badge, .bound, .copied {
  display: inline-block; padding: 2px 8px; border-radius: 6px;
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--green); background: rgba(48,209,88,.14); border: 1px solid rgba(48,209,88,.28);
}
.role-checkboxes, .role-toggle, .msg-area, .tzbar, .tzbase, .toggleBar {
  display: flex; gap: var(--s3); flex-wrap: wrap; align-items: center;
}
.msg-area { display: block; }
.user-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.user-table th, .user-table td { padding: 10px var(--s3); text-align: left; border-bottom: 1px solid var(--sep); }
.user-table th { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
                 letter-spacing: .1em; color: var(--label-3); }
.user-avatar { width: 32px; height: 32px; border-radius: 50%; overflow: hidden; background: var(--panel-hi); }
.user-avatar img { width: 100%; height: 100%; object-fit: cover; }
.role-select { width: auto; min-height: 34px; padding: 6px 10px; font-size: 14px; }
.progressbar { height: 6px; border-radius: 999px; background: var(--panel-hi); overflow: hidden; }
.progressbar > * { height: 100%; background: var(--accent); display: block; }
/* Generic state modifiers a few pages toggle. `show` reveals, `unlocked` is an
   admin section that has been unlocked. */
.show { display: block !important; }
.unlocked { border-color: var(--accent-line); }
/* Aliases for the same components under a different name on another page. */
.task-card { background: var(--panel); border: 1px solid var(--sep);
             border-radius: var(--radius); padding: var(--s4) var(--s5); margin-bottom: var(--s2); }
.task-card.overdue, .overdue { border-color: rgba(255,69,58,.42); }
.session-card { background: var(--panel); border: 1px solid var(--sep);
                border-radius: var(--radius); padding: var(--s3) var(--s4); }
.session-badge {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 6px;
  font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent); background: var(--accent-bg); border: 1px solid var(--accent-line);
}
.person-row, .sc-meta, .day-group-label, .show-card-body, .sc-body, .quota-info,
.instruction-text, .eligible-count, .photo-info, .legend-item, .save-row, .slot-buttons {
  font-size: var(--fs-footnote); color: var(--label-2);
}
.person-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
              border-bottom: 1px solid var(--sep); font-size: 14px; }
.person-name, .photo-name, .user-name { font-weight: 600; color: var(--label); }
.person-role, .user-email, .crew-role { font-size: var(--fs-caption); color: var(--label-3); }
.show-fields { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: flex-end; }
.day-group-label, .se-month-label {
  font-size: var(--fs-micro); font-weight: 700; color: var(--label-3);
  text-transform: uppercase; letter-spacing: .13em; margin: var(--s5) 0 var(--s3);
}
.se-awaiting-banner { padding: var(--s3) var(--s4); border-radius: var(--radius);
  font-size: var(--fs-subhead); font-weight: 600; color: var(--amber);
  background: rgba(255,159,10,.10); border: 1px solid rgba(255,159,10,.28); }
.collapsible-toggle { display: flex; align-items: center; gap: var(--s2); width: 100%;
                      text-align: left; background: none; border: none; padding: var(--s3) 0; }
.collapsible-body { display: none; padding-bottom: var(--s3); }
.collapsible.open .collapsible-body { display: block; }
.collapsible-arrow { color: var(--label-3); transition: transform .18s; }
.collapsible.open .collapsible-arrow { transform: rotate(90deg); }
.avail-table, .table-view { width: 100%; border-collapse: collapse; font-size: var(--fs-footnote); }
.avail-table th, .avail-table td { padding: 7px 9px; text-align: center; border: 1px solid var(--sep); }
.avail-table th, .name-col { background: var(--panel-hi); color: var(--label-3);
  font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }
.name-col { text-align: left; color: var(--label); text-transform: none; letter-spacing: 0; font-size: 14px; }
.save-msg { font-size: var(--fs-footnote); color: var(--label-2); }

/* --- responsive ---------------------------------------------------------- */
@media (max-width: 700px) {
  .wrap { padding: var(--s5) var(--s4) var(--s7); }
  h1 { font-size: 30px; }
  .card-grid { grid-template-columns: 1fr; }
  .strip { gap: var(--s4); }
  .chrome-in { padding: 0 var(--s4); }
  .thumb-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: var(--s2); }
  .cal-grid, .compact-grid { grid-template-columns: repeat(7, minmax(100px, 1fr)); }
  .toolbar { padding: var(--s2) var(--s3); }
}

/* schedule-visual: photo legend under the calendar (restored — the bulk
   conversion dropped the page's own copy of these) */
.photo-legend { display: flex; flex-wrap: wrap; gap: 12px; padding: 16px 0; margin-top: var(--s5); border-top: 1px solid var(--sep); justify-content: center; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--label-2); }
.legend-avatar { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; border: 2px solid var(--sep); }
