/* =============================================================================
   I4PL Conference 2026 - Programme (time-slot grid)
   -----------------------------------------------------------------------------
   Four sessions run concurrently in most blocks. Grouping by start time shows
   that for what it is, a choice of four in four rooms, instead of a flat list
   that reads like sixteen sequential items.

   Portraits are large on purpose. At thumbnail scale the faces carried no
   weight, and the speakers are the reason people register: 144px in slot cards,
   176px on feature sessions, against 48px before.
   ============================================================================= */

.schedule { padding: 3rem 0 4rem; background: var(--paper-2); }

.schedule-bar {
  position: sticky; top: 4.5rem; z-index: 60;
  display: grid; gap: 1rem;
  margin: 0 0 1.5rem;
  padding: 1rem 0;
  background: linear-gradient(180deg, var(--paper-2) 78%, rgba(233, 240, 246, 0));
}
.day-tabs { display: flex; flex-wrap: wrap; gap: .6rem; }
.day-tab {
  display: inline-flex; align-items: center; min-height: 3rem;
  padding: .7rem 1.4rem; border-radius: 999px;
  background: var(--white); border: 1px solid var(--line);
  font-size: var(--t-small); font-weight: 800; color: var(--ink);
  text-decoration: none; box-shadow: var(--sh-1);
  transition: background-color .2s var(--ease), color .2s var(--ease),
              transform .2s var(--ease);
}
.day-tab:hover { background: var(--ink); color: var(--white); transform: translateY(-2px); }

.stream-key { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; }
.stream-key li {
  display: inline-flex; align-items: center; gap: .5rem;
  font-size: var(--t-small); font-weight: 700; color: var(--muted);
}
.key-dot { width: .8rem; height: .8rem; border-radius: 50%; flex-shrink: 0; }
.key-dot-navy   { background: var(--navy); }
.key-dot-blue   { background: var(--blue); }
.key-dot-maroon { background: var(--maroon); }
.key-dot-cyan   { background: var(--cyan); }

.day { margin-top: 3rem; scroll-margin-top: 9rem; }
.day-title {
  font-size: var(--t-h2); letter-spacing: -.03em; color: var(--navy);
  padding-bottom: .9rem; margin-bottom: 1.5rem;
  border-bottom: 3px solid var(--line);
}

/* --- Slots --------------------------------------------------------------- */
.slot-stack { display: grid; gap: 2.25rem; }
.slot { display: grid; gap: .85rem; }
.slot-time {
  font-size: var(--t-small); font-weight: 800; letter-spacing: .04em;
  color: var(--ink); font-variant-numeric: tabular-nums;
  padding-bottom: .5rem; border-bottom: 2px solid var(--ink);
}
.slot.is-quiet .slot-time {
  color: var(--muted); border-bottom-color: var(--line); font-weight: 700;
}
.slot-body { display: grid; gap: 1rem; }
.slot-choose {
  margin: .25rem 0 0; font-size: var(--t-small); font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}

/* --- Quiet rows: breaks, registration, logistics ------------------------- */
.quiet-list { display: grid; gap: .4rem; }
.quiet {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem 1rem;
  padding: .7rem 1rem;
  border: 1px dashed var(--line); border-radius: var(--r-sm);
}
.quiet-title { font-size: var(--t-small); font-weight: 700; color: var(--muted); }

/* --- Feature sessions: keynote, plenary, VIP ----------------------------- */
.feature {
  display: grid; gap: 1.5rem;
  padding: 1.75rem 1.5rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 6px solid var(--maroon);
  border-radius: var(--r);
  box-shadow: var(--sh-2);
}
.feature-plenary { border-top-color: var(--navy); }
.feature-vip     { border-top-color: var(--cyan); }
.feature-top {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: .6rem 1rem; margin-bottom: .85rem;
}
.feature-title {
  font-size: clamp(1.5rem, 1.1rem + 1.1vw, 2rem);
  letter-spacing: -.02em; line-height: 1.18; text-wrap: balance;
  max-width: 24ch;
}
/* Session copy is now the speakers' own full abstracts, several hundred words
   in places. Give it a reading measure and real leading. */
.feature-body .ses-blurb,
.feature-body .ses-note,
.feature-body .ses-bio { max-width: 66ch; line-height: 1.65; }

/* --- Concurrent session cards -------------------------------------------- */
/* Equal columns, and each card shares the row track set so the chip, title,
   speaker block and abstract all sit on the same baseline across the row.
   Without this every card sized itself independently and nothing lined up. */
.pick-grid { display: grid; gap: 1rem; }
.pickc {
  display: flex; flex-direction: column; gap: .9rem;
  padding: 1.5rem 1.35rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 5px solid var(--muted);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.pickc:hover { transform: translateY(-4px); box-shadow: var(--sh-2); }
.pickc-navy   { border-top-color: var(--navy); }
.pickc-blue   { border-top-color: var(--blue); }
.pickc-maroon { border-top-color: var(--maroon); }
.pickc-cyan   { border-top-color: var(--cyan); }
.pickc-top { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .85rem; }
.pickc-title {
  font-size: var(--t-h3); letter-spacing: -.02em;
  line-height: 1.2; text-wrap: balance;
}

.ses-chip {
  display: inline-block;
  padding: .32rem .7rem; border-radius: .45rem;
  font-size: var(--t-small); font-weight: 800; letter-spacing: .03em;
  text-transform: uppercase; line-height: 1.3;
  background: var(--paper-2); color: var(--muted);
  text-wrap: balance;
}
/* The stream row is its own track so chips of different heights do not shove
   the titles beneath them out of alignment. */
.pickc-top { align-items: start; min-height: 3.1rem; }
.ses-chip-navy   { background: rgba(39, 58, 148, .13); color: #1d2c73; }
.ses-chip-blue   { background: rgba(0, 119, 193, .13); color: #005688; }
.ses-chip-maroon { background: rgba(138, 35, 79, .13); color: #6f1c40; }
.ses-chip-cyan   { background: rgba(3, 186, 178, .18); color: #015b57; }
.ses-chip-keynote, .ses-chip-plenary, .ses-chip-vip { background: var(--ink); color: var(--cyan); }

.ses-room { font-size: var(--t-small); font-weight: 700; color: var(--muted); }
.ses-blurb { font-size: var(--t-small); color: var(--body); max-width: 66ch; }

/* A session the attendee must register for separately is a condition, not a
   footnote: it gets its own line above the description, where it is read
   before the copy that makes someone want to attend. */
.ses-note {
  display: flex; align-items: baseline; gap: .5rem;
  margin: 0; padding: .6rem .85rem;
  background: var(--paper-2);
  border-left: 3px solid var(--cyan-deep);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: var(--t-small); font-weight: 700; color: var(--cyan-deep);
  max-width: 66ch;
}

.ses-bio {
  font-size: var(--t-small); color: var(--body); max-width: 66ch;
  padding-top: .9rem; border-top: 1px solid var(--line);
}
.ses-bio-head {
  display: block; margin-bottom: .3rem;
  font-size: var(--t-small); font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.ses-bio-link { font-weight: 700; color: var(--cyan-deep); }

/* --- Speakers ------------------------------------------------------------ */
.spk-list { display: grid; gap: .85rem; }
/* Each speaker gets their own card. Presented as a plain inline row they read
   as metadata; as a card they read as a person worth turning up for. */
.spk {
  display: flex; align-items: center; gap: 1.15rem;
  padding: 1rem 1.15rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease);
}
.spk:hover { border-color: rgba(3,186,178,.55); box-shadow: var(--sh-1); }
.spk-shot { flex-shrink: 0; display: block; }
.spk-badge {
  display: inline-block; width: fit-content; max-width: 100%; margin-bottom: .35rem;
  /* No nowrap: "CONFÉRENCIER OU CONFÉRENCIÈRE" is 371px on one line, wider than a
     desktop card column, and pushed French pages sideways at 1312-1366px too. */
  padding: .18rem .55rem; border-radius: .35rem;
  background: var(--white); border: 1px solid var(--line);
  font-size: var(--t-small); font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); line-height: 1.4;
}
.spk-face {
  display: block; width: 9rem; height: 9rem;      /* 144px, 3x the previous 48px */
  border-radius: 50%; object-fit: cover;
  background: var(--paper-2);
  box-shadow: 0 0 0 4px var(--white), 0 0 0 6px var(--cyan), var(--sh-1);
}
/* On feature sessions the speaker block sits in a narrow side column, so the
   portrait goes on top and the name, role and organisation run underneath at
   full column width. Beside the portrait they were wrapping one or two words
   to a line: "Precision Marketing Group Inc." over four lines. */
.spk-xl .spk { flex-direction: column; align-items: flex-start; gap: .85rem; }
.spk-xl .spk-face { width: 11rem; height: 11rem; }  /* 176px on feature sessions */
.spk-xl .spk-txt { width: 100%; }
/* No portrait supplied: a branded monogram. Never a stock face, never a
   generated one. */
.spk-initials {
  display: flex; align-items: center; justify-content: center;
  background: var(--navy); color: var(--white);
  font-size: 2.5rem; font-weight: 900; letter-spacing: .02em;
}
.spk-xl .spk-initials { font-size: 3rem; }
.spk-txt { display: grid; gap: .15rem; min-width: 0; }
.spk-name { font-size: var(--t-body); font-weight: 900; color: var(--ink); line-height: 1.2; }
.spk-role { font-size: var(--t-small); font-weight: 700; color: var(--body); line-height: 1.35; }
.spk-org  { font-size: var(--t-small); font-weight: 600; color: var(--muted); line-height: 1.35; }

/* =============================================================================
   BREAKPOINTS
   ============================================================================= */

@media (min-width: 40rem) {
  .pick-grid { grid-template-columns: repeat(2, 1fr); }
  .slot { grid-template-columns: 9.5rem 1fr; gap: 1.5rem; align-items: start; }
  .slot-time {
    border-bottom: 0; padding-top: .2rem; padding-right: 1rem;
    border-right: 2px solid var(--ink); text-align: right;
  }
  .slot.is-quiet .slot-time { border-right-color: var(--line); }
  /* The speaker column used to be `auto`, so it took whatever width the name
     and organisation needed and squeezed a 36px headline into what was left.
     Cap it, start both columns at the top, and let the text column dominate. */
  /* Nothing to read means nothing to reserve: the opening events carry only
     emcees, so they run full width with the people side by side instead of
     stacked against an empty half of the card. */
  /* Two class names, so this beats the single-class .feature rule below it
     regardless of source order. Written flat first, it lost the cascade and
     the card kept its two columns. */
  .feature.feature-plain { grid-template-columns: minmax(0, 1fr); }
  .feature-plain .spk-list { grid-template-columns: repeat(auto-fit, minmax(15rem, 18rem)); }
  /* Full width means the headline gets the full width. The 24ch measure is for
     the narrow text column beside a portrait. */
  .feature-plain .feature-title { max-width: 46ch; }
  .feature {
    grid-template-columns: minmax(15rem, 19rem) minmax(0, 1fr);
    align-items: start;
    gap: 2rem;
    padding: 2rem 2.25rem;
  }
  .pickc { padding: 1.75rem 1.6rem; }
}

@media (min-width: 62rem) {
  .schedule { padding: 4.5rem 0 5.5rem; }
  .schedule-bar {
    grid-template-columns: auto 1fr; align-items: center;
    justify-content: space-between; gap: 2rem; top: 5.25rem;
  }
  .stream-key { justify-content: flex-end; }
  .slot { grid-template-columns: 11rem 1fr; gap: 2rem; }
  .pick-grid { grid-template-columns: repeat(2, 1fr); gap: 1.25rem; }
  .day { margin-top: 4rem; }
}

@media (min-width: 82rem) {
  /* Four across so the concurrent choice is visible at a glance.
     minmax(0,1fr) forces genuinely equal columns; long titles were otherwise
     stretching their own column and squashing the others. */
  /* Two across, not four. Four columns worked while these cards held a single
     placeholder line; with the speakers' full abstracts in place each column
     was about twenty characters wide and unreadable. */
  .pick-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto auto auto auto;
    gap: 1.5rem;
    /* Cards keep their chips, titles and portraits aligned across the row, but
       a session whose description has not arrived yet should not be stretched
       to the height of a neighbour carrying eight hundred words. */
    align-items: start;
  }
  /* Subgrid was here to align four narrow columns. With two wide columns the
     alignment buys little and the row span forces a short card to the height of
     a long one, leaving half a screen of white space under a panel whose
     description has not arrived. Cards size to their own content instead. */
  .pickc {
    display: flex;
    flex-direction: column;
    gap: .85rem;
    padding: 1.6rem 1.35rem;
    align-self: start;
  }
  /* Exactly four children: chip row, title, speakers, body. A fifth child
     falls outside the four-row span and collides with the card below, which
     is what was overlapping the session text. */
  .pickc > * { min-width: 0; }
  .pickc-title { font-size: 1.2rem; line-height: 1.25; }
  .spk-md .spk-face { width: 8.5rem; height: 8.5rem; }
  .pickc-body .ses-blurb { max-width: 62ch; line-height: 1.65; }
}

/* Browsers without subgrid keep equal columns and a reserved title area, so
   the speaker cards still line up on the common case of 2-4 line titles. */
@supports not (grid-template-rows: subgrid) {
  @media (min-width: 82rem) {
    .pickc { display: flex; }
    .pickc-title { min-height: 6.5rem; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .day-tab:hover, .pickc:hover { transform: none; }
}

/* A session whose copy has not arrived yet. Stated plainly rather than left
   blank, which reads as a broken card. */
.ses-pending {
  font-size: var(--t-small); font-style: italic;
  color: var(--muted); margin: 0;
}
.pickc-body { display: flex; flex-direction: column; gap: .6rem; }
.pickc-body:empty { display: none; }

/* =========================================================================
   Mobile containment  (audit 2026-09-09, FAIL-1 + WARN-1)
   -------------------------------------------------------------------------
   Grid and flex children default to min-width:auto, so they refuse to shrink
   below their content's min-content width. Combined with .spk-face at 9-11rem
   and .spk-shot at flex-shrink:0, the agenda rows were forced wider than the
   viewport: 471px against a 390px screen on the French programme. Because body
   carries overflow-x:hidden there was no horizontal scroll to recover it, so
   room names and session titles were clipped and unreachable.

   French ran ~4x worse than English purely on string length, so test FR first.

   The same min-width:0 fix already exists at .spk-txt and .pickc > *, but the
   latter is scoped to min-width:82rem and so never reached a phone.
   ========================================================================= */
@media (max-width: 39.99rem) {
  .slot, .slot-body, .quiet-list, .pick-grid, .quiet { min-width: 0; }
  .slot > *, .slot-body > *, .quiet-list > *,
  .pick-grid > *, .pickc > *, .quiet > * { min-width: 0; }

  /* A 176px portrait cannot sit beside text on a 390px screen. Stack it and
     bring it down to 104px, which still reads as a person, not a thumbnail. */
  .spk { flex-direction: column; align-items: flex-start; gap: .75rem; min-width: 0; }
  .spk > * { min-width: 0; }
  /* nowrap keeps "SPEAKER" on one line on desktop, but the French label
     "CONFÉRENCIER OU CONFÉRENCIÈRE" is wider than a phone card and pushed
     the Thursday plenary 165px off screen. Let it wrap here. */
  .spk-badge { white-space: normal; letter-spacing: .03em; }  /* .08em made the single word CONFÉRENCIÈRE ~5px wider than a 360px card */
  .spk-face, .spk-xl .spk-face { width: 6.5rem; height: 6.5rem; }
  .spk-initials, .spk-xl .spk-initials { font-size: 2rem; }

  /* WARN-1: the bar stacks to ~250px on a phone, which turns the gradient's
     transparent bottom 22% into a ~55px window that content scrolls through.
     The fade is right on desktop where the bar is one short row; here it is
     opaque or nothing. */
  .schedule-bar { background: var(--paper-2); }
}

/* Active day tab. The tabs filter rather than jump (see programme.js), so the
   selected day has to be unmistakable, not a hover-weight tint. */
.day-tab.is-active {
  background: var(--ink); color: var(--white);
  border-color: var(--ink);
}
.day-tab.is-active:hover { transform: none; }

/* --- Plenary items with neither speakers nor copy -------------------------- */
/* Closing ceremony, opening logistics and similar: a chip, a room and a title.
   Given a hero card's padding and type scale they read as an error. */
.feature-bare { padding: 1.4rem 1.5rem; }
.feature-bare .feature-title {
  font-size: clamp(1.25rem, 1.05rem + .6vw, 1.5rem);
  max-width: none; line-height: 1.25;
}
.feature-bare .feature-top { margin-bottom: .5rem; }

/* --- Speaker rows link through to the profile ------------------------------ */
.spk-link {
  display: flex; align-items: center; gap: 1.15rem;
  text-decoration: none; color: inherit; width: 100%;
}
.spk-xl .spk-link { flex-direction: column; align-items: flex-start; gap: .85rem; }
.spk-more {
  display: block; margin-top: .4rem;
  font-size: var(--t-small); font-weight: 700; color: var(--cyan-deep);
}
.spk:hover .spk-more { text-decoration: underline; }

/* A plenary whose only content is its hosts: the heading leads, the people
   follow. Stacked the other way the card opened on two portraits and buried
   the session name underneath them. */
.feature-plain .feature-body { order: 1; }
.feature-plain .spk-list { order: 2; }

/* Session abstracts are now grouped into paragraphs. */
.ses-blurb p + p { margin-top: .75rem; }

/* French pages: original English session title under the French one (matches
   Whova). Clearly secondary, still 16px and full contrast on the white card. */
.ses-title-en {
  margin: -.35rem 0 .25rem;
  font-size: var(--t-small); font-weight: 600; font-style: italic;
  color: var(--body); line-height: 1.4;
}
