/* SEEK2LRN — Find a Tutor: scoped styles (all under .s2t-page so nothing leaks). */
.s2t-page, .s2t-page *, .s2t-page *::before, .s2t-page *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ---- the editorial design ----
   The landing's editorial look (seek2lrn-landing/assets/css/landing-editorial.css,
   the "Editorial light" style in design-system/DESIGN_SYSTEM.md): a white page,
   Roboto Slab 300 for display type and Inter 300/400 for everything else, flat
   blue and ink, square corners, no gradients and no shadows. Lists sit between
   2px ink rules with hairlines between their rows, as the landing's educator
   rows do. The layout, the row geometry and every reserved height below are
   the page's own and unchanged; only the surface changed. */
.s2t-page {
  --s2e-blue: #1558D6;
  --s2e-blue-dark: #0E3FA3;
  --s2e-ink: #16203A;
  --s2e-muted: #475569;
  --s2e-line: #E3E8F3;
  --s2e-tint: #EEF3FC;
  --s2e-display: 'Roboto Slab', Georgia, serif;
  --s2e-body: 'Inter', 'Segoe UI', Arial, sans-serif;

  /* square, as the landing is: the radius tokens stay so the geometry below
     keeps its shape, at zero */
  --s2-r: 0px;
  --s2-r-sm: 0px;
  /* the white margin above and below the photo slice (it sits flush left) */
  --s2-frame: 18px;

  font-family: var(--s2e-body);
  font-weight: 300;
  color: var(--s2e-ink);
  background: #fff;
}
.s2t-page a { text-decoration: none; }

/* the wrap only has to be wide enough not to cap .s2t-layout below its own
   1280 — the layout and the banner are what actually set the page's width */
.s2t-page .s2t-wrap { max-width: none; margin: 0 auto; padding: 2rem 4vw 4rem; }
/* centred header */
.s2t-page .s2t-head { text-align: center; }
.s2t-page .s2t-head h1 { font-family: var(--s2e-display); font-size: clamp(2.6rem, 5vw, 4.4rem); font-weight: 300; line-height: 1; letter-spacing: -0.03em; color: var(--s2e-ink); }
.s2t-page .s2t-head h1 em { font-style: normal; color: var(--s2e-blue); }
.s2t-page .s2t-count { font-size: 0.95rem; color: var(--s2e-muted); margin-top: 0.8rem; }
/* the search bar under the headline: square, ruled in ink, the Search button
   blue on its end, as the landing's hero search */
.s2t-page .s2t-hsearch {
  display: flex; align-items: center; gap: 0.75rem;
  max-width: 780px; height: 60px; margin: 1.8rem auto 0;
  padding-left: 1.1rem;
  background: #fff; border: 1px solid var(--s2e-ink);
}
.s2t-page .s2t-hsearch:focus-within { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
.s2t-page .s2t-hsearch svg { width: 20px; height: 20px; flex: none; color: var(--s2e-muted); }
.s2t-page .s2t-hsearch input { flex: 1; min-width: 0; height: 100%; border: 0; outline: none; background: transparent; font-family: inherit; font-size: 1.05rem; font-weight: 300; color: var(--s2e-ink); }
.s2t-page .s2t-hsearch input::placeholder { color: var(--s2e-muted); }
.s2t-page .s2t-hsearch button {
  flex: none; align-self: stretch; margin: -1px -1px -1px 0; padding: 0 1.8rem;
  border: 1px solid var(--s2e-blue); background: var(--s2e-blue); color: #fff;
  font-family: inherit; font-size: 1rem; font-weight: 500; cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.s2t-page .s2t-hsearch button:hover { background: var(--s2e-ink); border-color: var(--s2e-ink); }
.s2t-page .s2t-hsearch button:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
@media (max-width: 560px) {
  .s2t-page .s2t-hsearch { height: 52px; }
  .s2t-page .s2t-hsearch button { padding: 0 1rem; }
}
.s2t-page .s2t-notice { margin: 1rem auto 0; max-width: 640px; padding: 0.7rem 1rem; background: #fff7e6; border: 1px solid #f0c97a; color: #7a5a16; font-size: 0.82rem; font-weight: 400; text-align: center; }
/* The page wrap and the results column are containers: the sidebar and the
   rows respond to the width their column gets (the @container rules below),
   not to the screen's, so the page can be framed or narrowed without the rows
   going wrong. The wrap is a plain block (never auto-margined inside a grid),
   so it still fills its width as a size container. */
.s2t-page .s2t-wrap { container: s2t-page / inline-size; }
.s2t-page .s2t-main { container: s2t-results / inline-size; }

/* ---- three-column shell: video rail + filter sidebar | results | video rail
   + roadmaps rail ----
   Named grid areas, not source order, so the two side rails can be pushed
   below one another (not below the results) as the page narrows. */
.s2t-page .s2t-layout {
  display: grid;
  /* each side rail is exactly one landing-sized video wide; the filters and the
     roadmaps panel share that width */
  /* pure ratios, so every laptop gets the same proportions: 11.4vw is the landing
     bar's width at 1440 (164px), and the bars keep its 1:3 shape */
  --s2t-bar-w: max(11.4vw, 150px); /* floor: the filters stop fitting below ~150px */
  grid-template-columns: var(--s2t-bar-w) minmax(0, 1fr) var(--s2t-bar-w);
  grid-template-areas: "left main right";
  gap: 2.8vw; align-items: start; max-width: none; margin: 2.5rem auto 0;
}
.s2t-page .s2t-side-left { grid-area: left; }
.s2t-page .s2t-side-right { grid-area: right; }
/* the sidebar rides along as the results scroll; it scrolls internally on short
   viewports so the tick card can never be cut off with no way to reach it */
/* it pins below the fixed nav (58px; the page's own padding-top clears the
   same bar), and its scrollbar is a thin hairline rather than a grey slab */
.s2t-page .s2t-side { position: sticky; top: calc(58px + 1.25rem); display: flex; flex-direction: column; gap: 2rem; max-height: calc(100vh - 58px - 2.5rem); overflow-y: auto; scrollbar-width: thin; scrollbar-color: #C9D2E3 transparent; }
.s2t-page .s2t-main { grid-area: main; min-width: 0; }

/* ---- the video rails ----
   The landing's "from anyone" educator bars, ported flat and borderless: no
   crossfade script here, just a muted, looping loop. Two per side, same width
   as the panel below them so the left rail's videos and its Filters panel
   share one edge. */
/* one video above and one below each side panel, exactly the landing's vertical
   .s2e-bar: (48vw - 36px) / 4 wide, 1:3, centred in its column */
.s2t-page .s2t-bar { position: relative; margin: 0 auto; width: var(--s2t-bar-w); aspect-ratio: 1 / 3; flex: 0 0 auto; min-width: 0; overflow: hidden; background: var(--s2e-line); }
.s2t-page .s2t-bar video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }

/* ---- the roadmaps rail ----
   What used to repeat on every tutor card, shown once: a single dark teaser
   that runs the rest of the right column's sticky height, beside the filters
   column on the left. */
.s2t-page .s2t-road-rail { flex: 1 1 auto; min-height: 220px; display: flex; flex-direction: column; }
/* desktop: video, panel, video is taller than a screen, so the side columns scroll
   with the page rather than pinning (and scrolling inside themselves) */
.s2t-page .s2t-side { position: static; max-height: none; overflow: visible; }
.s2t-page .s2t-road { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.s2t-page .s2t-road-rail .s2t-r-card { flex: 1 1 auto; height: 100%; justify-content: center; gap: 0.6rem; padding: 1rem 1.1rem 1.2rem; }
.s2t-page .s2t-road-k { display: block; font-size: 0.8rem; font-weight: 500; color: var(--s2e-muted); text-align: center; }

/* ---- the two sidebar panels ----
   No floating cards any more: each panel opens under a 2px ink rule, the way
   the landing's lists and its curricula table do. */
.s2t-page .s2t-float { background: none; border-top: 2px solid var(--s2e-ink); }

/* filter card (sidebar): controls stack, each with a visible label */
.s2t-page .s2t-filters { display: flex; flex-direction: column; gap: 1rem; padding: 1rem 0 0; }
.s2t-page .s2t-filters-head { display: flex; align-items: center; }
.s2t-page .s2t-panel-title { font-family: var(--s2e-display); font-size: 1.4rem; font-weight: 300; line-height: 1.2; color: var(--s2e-ink); }
.s2t-page .s2t-field { display: flex; flex-direction: column; gap: 0.35rem; }
.s2t-page .s2t-field-label { font-size: 0.8rem; font-weight: 500; color: var(--s2e-muted); }
/* controls: white, square, ruled in ink (an ink edge also clears the 3:1
   contrast a form control's boundary needs, which a hairline would not) */
.s2t-page .s2t-search { display: flex; align-items: center; gap: 8px; background: #fff; border: 1px solid var(--s2e-ink); padding: 0 14px; height: 44px; }
.s2t-page .s2t-search:focus-within { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
.s2t-page .s2t-search svg { width: 17px; height: 17px; color: var(--s2e-muted); flex-shrink: 0; }
.s2t-page .s2t-search input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: 0.92rem; font-weight: 300; color: var(--s2e-ink); }
.s2t-page .s2t-search input::placeholder { color: var(--s2e-muted); }
.s2t-page .s2t-select { width: 100%; height: 44px; border: 1px solid var(--s2e-ink); border-radius: 0; background: #fff; font-family: inherit; font-size: 0.9rem; font-weight: 300; color: var(--s2e-ink); padding: 0 0.8rem; cursor: pointer; }
.s2t-page .s2t-select:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
.s2t-page .s2t-seg { display: flex; border: 1px solid var(--s2e-ink); overflow: hidden; background: #fff; }
.s2t-page .s2t-seg button { flex: 1; min-width: 0; font-family: inherit; font-size: 0.8rem; font-weight: 400; padding: 0 0.3rem; height: 42px; border: none; background: transparent; color: var(--s2e-ink); cursor: pointer; }
.s2t-page .s2t-seg button + button { border-left: 1px solid var(--s2e-ink); }
.s2t-page .s2t-seg button.on { background: var(--s2e-blue); color: #fff; }
.s2t-page .s2t-seg button:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: -4px; }
.s2t-page .s2t-shuffle { font-family: inherit; font-size: 0.88rem; font-weight: 400; padding: 0 1rem; height: 44px; border: 1px solid var(--s2e-ink); background: transparent; color: var(--s2e-ink); cursor: pointer; transition: background-color 0.2s ease, color 0.2s ease; }
.s2t-page .s2t-shuffle:hover { background: var(--s2e-ink); color: #fff; }
.s2t-page .s2t-shuffle:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }

/* ---- quick-filter tick card ---- */
.s2t-page .s2t-ticks { padding: 1rem 0 0; }
.s2t-page .s2t-ticks-head { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem 0.7rem; margin-bottom: 0.8rem; }
.s2t-page .s2t-ticks-count { font-size: 0.8rem; font-weight: 400; color: var(--s2e-blue); }
.s2t-page .s2t-ticks-clear { margin-left: auto; font-family: inherit; font-size: 0.8rem; font-weight: 400; color: var(--s2e-blue); background: none; border: 0; padding: 0.2rem 0; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.s2t-page .s2t-ticks-clear:hover { color: var(--s2e-ink); }
.s2t-page .s2t-ticks-clear:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
/* one column inside the sidebar; the stacked layout below widens it back to two */
.s2t-page .s2t-ticks-groups { display: grid; grid-template-columns: 1fr; gap: 0.9rem; }
.s2t-page .s2t-tick-group { border: none; padding-top: 0.6rem; margin: 0; display: flex; flex-wrap: wrap; gap: 0.45rem 0.6rem; }
.s2t-page .s2t-tick-group legend { font-size: 0.8rem; font-weight: 500; color: var(--s2e-muted); padding: 0 0 0.55rem; margin: 0; width: 100%; border-bottom: 1px solid var(--s2e-line); }
/* square chips; a ticked one takes the blue. The idle edge is #7C879B, not a
   hairline: on the white page the edge is the chip's only boundary, and it
   needs 3:1 against white (WCAG 1.4.11) */
.s2t-page .s2t-tick { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.84rem; font-weight: 300; color: var(--s2e-ink); background: #fff; border: 1px solid #7C879B; padding: 0.35rem 0.7rem 0.35rem 0.5rem; cursor: pointer; user-select: none; }
.s2t-page .s2t-tick input { width: 15px; height: 15px; accent-color: var(--s2e-blue); cursor: pointer; flex-shrink: 0; }
.s2t-page .s2t-tick:has(input:checked) { background: var(--s2e-tint); border-color: var(--s2e-blue); font-weight: 400; color: var(--s2e-blue-dark); }
.s2t-page .s2t-tick:has(input:focus-visible) { outline: 2px solid var(--s2e-blue); outline-offset: 1px; }

/* under 860px (tablets): the videos drop (there's no width left to give them without
   squeezing the tutor rows) and the right rail moves under the left one, in
   the same narrow column, rather than under the results — "roadmaps below the
   filters" per the board's layout call. Both rails unstick: two sticky panels
   stacked in one grid column fight each other on scroll. */
/* ---- desktop: the page ends where the left column's second video ends ----
   The left rail (video, filters, quick filters, video) sets the height of the whole
   three-column block. The results column contributes no height of its own
   (contain: size) and stretches to that height: heading and search at the top,
   the tutor list scrolling inside, the pager on the bottom line. The right rail
   stretches too: video at the top, roadmaps filling the middle, the second video
   ending on the same line as the left one and the pager. */
@container s2t-page (min-width: 861px) {
  .s2t-page .s2t-layout { align-items: stretch; }
  .s2t-page .s2t-main { contain: size; display: flex; flex-direction: column; min-height: 0; }
  /* align-content: start, so a short (filtered) list keeps natural card heights
     instead of stretching its rows to fill the column */
  /* no inner scroll: app.js puts exactly as many cards on a page as fit here */
  .s2t-page .s2t-main .s2t-grid { flex: 1 1 auto; min-height: 0; overflow: visible; align-content: start; margin-bottom: 0; }
  .s2t-page .s2t-main .s2t-empty { flex: 1 1 auto; }
  .s2t-page .s2t-main .s2t-pager { flex: 0 0 auto; margin-top: 0; padding-top: 1rem; }
  .s2t-page .s2t-side-right { display: flex; flex-direction: column; }
  .s2t-page .s2t-side-right .s2t-road-rail { flex: 1 1 auto; }
  .s2t-page .s2t-side-right .s2t-bar:last-child { margin-top: auto; }
}

@container s2t-page (max-width: 860px) {
  .s2t-page .s2t-bar { display: none; }
  .s2t-page .s2t-layout { grid-template-columns: 240px minmax(0, 1fr); grid-template-areas: "left main" "right main"; gap: 1.75rem 2rem; }
  .s2t-page .s2t-side { position: static; max-height: none; overflow: visible; }
  .s2t-page .s2t-road-rail { min-height: 0; }
}

/* under 760px: one column. The sidebar stacks above the results and lays its
   controls out in a row so it doesn't push the tutors off the screen; the
   roadmaps rail drops to the bottom, after the results, same as any other
   footer teaser. */
@container s2t-page (max-width: 760px) {
  .s2t-page .s2t-layout { grid-template-columns: 1fr; grid-template-areas: "left" "main" "right"; gap: 1.25rem; }
  .s2t-page .s2t-filters { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 0.8rem; }
  .s2t-page .s2t-filters-head { flex: 1 0 100%; }
  .s2t-page .s2t-field { flex: 1 1 190px; }
  /* the three gender buttons look stretched if the row lets them fill it */
  .s2t-page .s2t-field:has(.s2t-seg) { flex: 0 1 320px; }
  .s2t-page .s2t-shuffle { flex: 0 0 auto; }
  .s2t-page .s2t-ticks-groups { grid-template-columns: repeat(2, 1fr); gap: 1rem 2rem; }
  .s2t-page .s2t-road-rail { min-height: 160px; }
}

@container s2t-page (max-width: 590px) {
  .s2t-page .s2t-ticks-groups { grid-template-columns: 1fr; }
}

/* ---- tutor rows ------------------------------------------------------------
   One tutor per row, as the landing's educator rows are: the rows sit between
   2px ink rules with a hairline between each, on the white page. The photo is
   a slice flush with the row's left edge, with a white margin above and below
   it; right of it, the details, then hairline dividers split off the three
   offers. No card surface, no lift, no shadow. */
.s2t-page .s2t-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; margin-bottom: 2rem; border-top: 2px solid var(--s2e-ink); border-bottom: 2px solid var(--s2e-ink); }
.s2t-page .s2t-grid:empty { border: 0; }
.s2t-page .s2t-empty { padding: 3rem 1rem; text-align: center; color: var(--s2e-muted); }

.s2t-page .s2t-tcard {
  /* drives the slice's width AND where the monogram centres on it — the two
     must track each other, and they change at two breakpoints */
  --s2-slice-w: 21%;
  position: relative; overflow: hidden; isolation: isolate;
  /* double the original 152: the photo is sized by height, so a taller row is
     also what makes the photo fill its slice instead of sitting in a corner of it */
  display: flex; min-height: 304px;
  background: #fff;
  color: var(--s2e-ink);
}
.s2t-page .s2t-tcard + .s2t-tcard { border-top: 1px solid var(--s2e-line); }

/* the panel layers: photo slice, then the fade painted over the whole card */
.s2t-page .s2t-t-media { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
/* flush with the row's left edge, --s2-frame of white above and below it */
.s2t-page .s2t-t-slice {
  position: absolute; top: var(--s2-frame); bottom: var(--s2-frame); left: 0;
  width: var(--s2-slice-w); overflow: hidden;
  background: var(--s2e-tint);
  display: flex; align-items: center; justify-content: center;
}
/* No photo: the initials, set in the display face on the slice's tint and
   centred on the slice by hand (they are painted outside it, after the
   spacer, so the slice's crop can never clip them) */
.s2t-page .s2t-t-initials {
  position: absolute; top: 50%;
  left: calc(var(--s2-slice-w) / 2);
  transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--s2e-display); font-size: 2.4rem; font-weight: 300; letter-spacing: -0.02em;
  color: var(--s2e-blue);
  user-select: none;
}
/* The photo is sized by HEIGHT: it fills the slice top to bottom and its width
   falls out of its own aspect ratio, so the whole frame is visible instead of a
   horizontal band through the middle of it. (`object-fit: cover` on the full
   slice scaled a portrait up until it covered the width — on a 600×800 source
   that showed about 39% of the image's height.)

   Centred, and the slice's overflow crops what spills: at this row height almost
   every real photo is WIDER than the slice, so this is a symmetric crop rather
   than a mat. It used to carry its own right-edge mask; the slice is a framed
   panel now, and a framed photo does not need to dissolve sideways. */
.s2t-page .s2t-t-photo {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  height: 100%; width: auto; max-width: none;
}
/* The monogram gives way only to a photo that has actually LOADED (render.js
   stamps data-ok on load) — not merely to one that has been requested, which
   left the slice empty for the length of a lazy fetch. :has() re-evaluates both
   ways, so the monogram is also back the instant onerror removes a dead image. */
.s2t-page .s2t-t-media:has(.s2t-t-photo[data-ok]) .s2t-t-initials { display: none; }
/* the fade the client asked removed lived here (a linear-gradient painted over
   the photo slice); .s2t-t-fade is still emitted in render.js as an aria-hidden
   spacer div but is no longer styled, so it paints nothing */

/* The content clears the photo slice: 28% starts it where the fade is already
   past 70%, and it is fully solid a fraction later. No column gap — the
   dividers' own padding is the gap, and every pixel not spent here is a pixel
   the tutor's name gets. */
.s2t-page .s2t-t-body {
  position: relative; z-index: 1; flex: 1; min-width: 0;
  display: flex; align-items: center;
  padding: 1.3rem 1.2rem 1.3rem calc(23% + 1.2rem);
}

.s2t-page .s2t-t-id { flex: 1; min-width: 0; }
/* one line, ellipsised: the row is wide enough that almost nothing truncates,
   and a wrapping name would break the equal row heights */
/* Two lines, with the height of two reserved either way. One line ellipsised
   was fine when the row had two divisions; with four the name column is ~185px
   and one line truncated most of the roster. Reserved, so a one-line name and a
   two-line name still produce the same row height. */
.s2t-page .s2t-t-name {
  min-height: 2.3em;
  font-family: var(--s2e-display); font-size: 1.3rem; font-weight: 300; line-height: 1.15;
  letter-spacing: -0.01em; color: var(--s2e-ink); overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* clamped to two lines with the height reserved either way: `specialization` is
   free text, and a tutor who lists six subjects must not make their row taller
   than the one above it */
.s2t-page .s2t-t-subjects {
  margin-top: 0.35rem; font-size: 0.86rem; font-weight: 300; line-height: 1.5; color: var(--s2e-muted);
  min-height: 3em;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* height reserved whether or not there is a badge or a rating to put in it */
.s2t-page .s2t-t-meta { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.55rem; min-width: 0; min-height: 22px; }
/* the country, with its flag, as the landing's rows set it: plain text, no pill */
.s2t-page .s2t-t-where { display: inline-flex; align-items: center; gap: 0.45rem; max-width: 100%; font-size: 0.82rem; font-weight: 400; color: var(--s2e-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.s2t-page .s2t-t-flag { flex: none; width: 20px; height: 15px; object-fit: cover; box-shadow: 0 0 0 1px var(--s2e-line); }
.s2t-page .s2t-t-rating { font-size: 0.8rem; font-weight: 400; color: var(--s2e-blue); white-space: nowrap; }

/* ---- the three divisions ------------------------------------------------
   photo + identity │ group classes │ one to one. The two dividers are the same
   hairline, so "who they are", "what they run" and "book them yourself" read as
   three compartments of one row rather than one long list of details. */
/* Identity is the smallest column on the card: a name, a subject line and a
   country badge. Everything reclaimed here goes to the three offers, which is
   where a visitor actually decides something. */
.s2t-page .s2t-t-id { flex: 0 1 136px; min-width: 104px; display: flex; flex-direction: column; justify-content: center; }
/* "Everything reclaimed here goes to the three offers" (above) was true only in
   theory: with cta/road already pinned to their own floor, id never actually
   gave up width, because nothing forced it to shrink before this. Groups
   existing is the trigger the client asked for — reclaim identity's width for
   it, same floor for cta/road either way. */
.s2t-page .s2t-tcard:has(.s2t-g-card) .s2t-t-id { flex-basis: 116px; }
.s2t-page .s2t-t-groups,
.s2t-page .s2t-t-cta {
  align-self: stretch; display: flex; flex-direction: column; justify-content: flex-start;
  border-left: 1px solid var(--s2e-line); margin-left: 1rem; padding-left: 1rem;
}
/* The two offers share whatever the identity column leaves. With classes on
   sale the carousel takes the lion's share; with none, the group column
   shrinks to its reserved note and one to one grows. */
.s2t-page .s2t-t-cta { flex: 1 1 0; min-width: 112px; gap: 0.45rem; }
/* The empty state reserves exactly what a populated strip occupies (label +
   150px card + its inset). Without this a tutor with classes is ~150px taller
   than one without as soon as the layout stacks and the card's min-height stops
   being what decides the row height. */
.s2t-page .s2t-t-groups { flex: 0 1 auto; min-width: 132px; gap: 0.45rem; min-height: 192px; }
/* Groups classes existing is what earns this column its width. The stack
   (stack.js) needs only one card plus its two peeks, far less than the old
   side-scrolling strip, so 2:1:1 against cta/road; at 4:1:1 the one-to-one
   column fell to ~90px and wrapped its ask and price. */
.s2t-page .s2t-tcard:has(.s2t-g-card) .s2t-t-groups { flex: 2 1 0; }
.s2t-page .s2t-tcard:has(.s2t-g-card) .s2t-t-cta { min-width: 150px; }

/* the label above each division */
.s2t-page .s2t-t-rate-k { display: block; font-size: 0.8rem; font-weight: 500; color: var(--s2e-muted); text-align: center; }
/* the thing exists, this tutor hasn't priced it — said plainly, not hidden */
.s2t-page .s2t-t-rate-none { color: var(--s2e-muted); }
/* "No group classes" / "Sign in to see group classes" / "Loading…" */
.s2t-page .s2t-g-note { font-size: 0.86rem; font-weight: 300; color: var(--s2e-muted); }

/* ---- the group-class carousel ----
   Real cards side by side, scrolled horizontally. The strip is the only thing
   that moves, so six classes and one class occupy identical height and every
   row in the grid stays the same size. Both edges sit under a chevron, so a
   part-scrolled strip reads as "there is more this way" rather than as a card
   chopped in half. */
.s2t-page .s2t-g-strip { position: relative; flex: 0 0 auto; min-width: 0; --s2-g-fade: 24px; }
.s2t-page .s2t-g-list {
  display: flex; gap: 0.5rem; list-style: none;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; scroll-behavior: smooth; -webkit-overflow-scrolling: touch;
  /* no top inset: a 2px top padding here used to sit the group cards 2px below
     the one-to-one/roadmap cards next to them (same label, same gap, but this
     list added its own inset on top) — that was the "not vertically aligned"
     report. Left/right keep --s2-g-fade as the arrows' gutter. */
  /* No bottom padding: it left the group card 5px short of its neighbours.
     Left/right keep --s2-g-fade as the carousel arrows' gutter. */
  padding: 0 var(--s2-g-fade);
  scrollbar-width: none;
}
.s2t-page .s2t-g-list::-webkit-scrollbar { display: none; }
/* the client asked the fades gone: the ::before/::after gradient overlays that
   used to sit over the strip's edges are removed. --s2-g-fade stays — the
   .s2t-g-list padding above still uses it as the arrows' gutter, unrelated to
   the fade that painted on top of it. */

.s2t-page .s2t-g-card {
  scroll-snap-align: start;
  /* `height` was a hard 150px, which is what made this column end 46px short
     of One-to-One and 22px short of Roadmaps. It now fills the strip, and the
     strip fills the row, so all three offer columns end on the same line. */
  flex: 0 0 138px; min-width: 0; height: 100%;
  display: flex; flex-direction: column;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--s2e-ink);
}
/* The subject cover is a solid design-system fill, and NOTHING ELSE.
   It used to carry an inline motif drawn on a 68x54 viewBox with
   preserveAspectRatio="slice". The banner is far wider than 68:54, so `slice`
   scaled that artwork up and cropped it -- the `book` motif's two white pages
   (opacity .92 and .7) became huge pale slabs washed across the banner. That
   is the "white fade" on the group cards. The motif is hidden rather than
   ripped out of render.js, so restoring it later is a one-line change; if it
   comes back it needs a viewBox matching the banner's real ratio. */
/* the group-class stack (stack.js): every card shares one centred box; the
   script offsets, scales, dims and orders them so one sits in front and its
   neighbours tuck behind its edges. Replaces the old side-scrolling strip. */
.s2t-page .s2t-g-stack { position: relative; flex: 1 1 auto; min-height: 178px; }
.s2t-page .s2t-g-deck { position: absolute; inset: 0; list-style: none; }
.s2t-page .s2t-g-stack .s2t-g-card {
  position: absolute; top: 0; bottom: 0; left: 50%;
  width: min(72%, 190px); margin-left: calc(min(72%, 190px) / -2); height: auto;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.45s ease, filter 0.45s ease;
}
.s2t-page .s2t-g-stack .s2t-g-card:not(.is-front) { cursor: pointer; }
.s2t-page .s2t-g-stack .s2t-g-arrow { top: 50%; z-index: 400; }
@media (prefers-reduced-motion: reduce) {
  .s2t-page .s2t-g-stack .s2t-g-card { transition: none; }
}
.s2t-page .s2t-g-cover { display: block; height: 52px; overflow: hidden; }
.s2t-page .s2t-g-cover svg { display: none; }
.s2t-page .s2t-g-t0 { background: var(--s2e-blue); }
.s2t-page .s2t-g-t1 { background: var(--s2e-ink); }
.s2t-page .s2t-g-t2 { background: var(--s2e-blue-dark); }

.s2t-page .s2t-g-name {
  margin: 0.45rem 0.55rem 0; font-size: 0.78rem; font-weight: 500; line-height: 1.3; color: var(--s2e-ink);
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 1.95em;
}
/* clamped and reserved: 'from 6 Oct · 5 sessions · 12 seats left' wraps to two
   lines at some widths and one at others, which would make the strip — and so
   the whole row — a different height per breakpoint */
.s2t-page .s2t-g-meta {
  margin: 0.2rem 0.55rem 0; font-size: 0.68rem; font-weight: 400; line-height: 1.35; color: var(--s2e-muted);
  min-height: 2.7em;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.s2t-page .s2t-g-foot { display: flex; align-items: center; justify-content: space-between; gap: 0.3rem; margin: auto 0.55rem 0; padding: 0.4rem 0 0.5rem; }
.s2t-page .s2t-g-price { font-family: var(--s2e-display); font-size: 1rem; font-weight: 300; line-height: 1.2rem; color: var(--s2e-ink); }
.s2t-page .s2t-g-price-none { color: var(--s2e-muted); }
.s2t-page .s2t-g-enrol {
  font-size: 0.7rem; font-weight: 500; padding: 0.26rem 0.55rem;
  background: var(--s2e-blue); color: #fff; border: 1px solid var(--s2e-blue);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.s2t-page .s2t-g-enrol:hover { background: var(--s2e-ink); border-color: var(--s2e-ink); }
.s2t-page .s2t-g-enrol-off { background: transparent; color: var(--s2e-muted); border-color: var(--s2e-line); cursor: not-allowed; }

/* chevrons sit on the fades, one at each edge */
.s2t-page .s2t-g-arrow {
  /* parked over the cover art rather than the title line — a chevron sitting on
     a course name makes the name look truncated when it is not */
  position: absolute; top: 30px; transform: translateY(-50%); z-index: 3;
  display: grid; place-items: center; width: 24px; height: 24px;
  cursor: pointer;
  background: #fff; color: var(--s2e-ink); border: 1px solid var(--s2e-ink);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.s2t-page .s2t-g-arrow:hover { background: var(--s2e-ink); color: #fff; }
.s2t-page .s2t-g-arrow svg { width: 12px; height: 12px; }
.s2t-page .s2t-g-arrow:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
.s2t-page .s2t-g-prev { left: 0; }
.s2t-page .s2t-g-next { right: 0; }

@media (prefers-reduced-motion: reduce) {
  .s2t-page .s2t-g-list { scroll-behavior: auto; }
}

/* square and flat: Register is the blue one, Log in is ruled in ink; both go
   ink on hover */
.s2t-page .s2t-reg,
.s2t-page .s2t-login { text-align: center; font-size: 0.82rem; font-weight: 400; padding: 0.45rem 0.7rem; background: transparent; transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; }
.s2t-page .s2t-reg { color: #fff; background: var(--s2e-blue); border: 1px solid var(--s2e-blue); }
.s2t-page .s2t-reg:hover { background: var(--s2e-ink); border-color: var(--s2e-ink); }
.s2t-page .s2t-login { color: var(--s2e-ink); border: 1px solid var(--s2e-ink); }
.s2t-page .s2t-login:hover { background: var(--s2e-ink); color: #fff; }
.s2t-page .s2t-tcard a:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }

/* ---- the roadmaps rail ----
   The one dark thing on the row, flat: solid ink, square, its SOON tag and
   corner arrow ruled in white. A teaser for something that has not shipped
   should not look as actionable as the two offers beside it. */
.s2t-page .s2t-r-card {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; gap: 0.4rem;
  padding: 0.75rem 0.8rem 0.8rem;
  background: var(--s2e-ink);
  color: #fff;
}
.s2t-page .s2t-r-blob { display: none; }
/* the app's roadmap mark in its original frosted tile (the student/tutor roadmaps
   page before the flat pass): rounded, inner highlight, soft drop shadow */
.s2t-page .s2t-r-mark { display: grid; place-items: center; width: 100%; aspect-ratio: 1; margin: 0.4rem 0 0.2rem; border-radius: 22%; background: rgba(255, 255, 255, 0.10); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 18px 40px rgba(6, 15, 40, 0.35); outline: 1px solid rgba(255, 255, 255, 0.20); outline-offset: -1px; }
.s2t-page .s2t-r-mark svg { width: 70%; height: 70%; }
.s2t-page .s2t-r-head { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; }
.s2t-page .s2t-r-soon {
  font-size: 0.62rem; font-weight: 500; letter-spacing: 0.06em;
  padding: 0.18rem 0.4rem;
  border: 1px solid rgba(255, 255, 255, 0.85);
}
.s2t-page .s2t-r-arrow {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px;
  border: 1px solid rgba(255, 255, 255, 0.85);
  transition: transform 0.25s ease;
}
.s2t-page .s2t-r-arrow svg { width: 12px; height: 12px; }
.s2t-page .s2t-r-card:hover .s2t-r-arrow { transform: translate(2px, -2px); }
.s2t-page .s2t-r-title { font-family: var(--s2e-display); font-size: 1.15rem; font-weight: 300; letter-spacing: -0.01em; margin-top: 0.15rem; }
.s2t-page .s2t-r-copy { font-size: 0.72rem; font-weight: 400; line-height: 1.45; color: rgba(255, 255, 255, 0.78); }

/* ---- the one-to-one card ----
   Deliberately the same surface as a group card: two ways of learning with this
   tutor, presented as two offers. It asks first, then gives the two ways in. */
/* Both offer cards stretch to the row's height so their bottoms align.
   Without this they size to their own content and the row reads ragged. */
.s2t-page .s2t-t-cta, .s2t-page .s2t-t-groups { align-self: stretch; }
.s2t-page .s2t-o-card, .s2t-page .s2t-r-card { flex: 1 1 auto; }
/* The strip must FILL what is left of the column under the "GROUP CLASSES"
   heading, not take 100% of the column -- `height:100%` ignored the heading
   and pushed the strip past the column's bottom by exactly the heading's
   height, leaving the group card 14px lower than its neighbours.
   `min-height: 0` is required or the flex item refuses to shrink below its
   content and the overflow comes straight back. */
.s2t-page .s2t-g-strip { flex: 1 1 auto; min-height: 0; }
.s2t-page .s2t-g-list { height: 100%; align-items: stretch; }

.s2t-page .s2t-o-card {
  display: flex; flex-direction: column; gap: 0.45rem;
  padding: 0.75rem 0.8rem 0.8rem;
  background: #fff;
  border: 1px solid var(--s2e-ink);
}
.s2t-page .s2t-o-ask { font-size: 0.84rem; font-weight: 400; line-height: 1.3; color: var(--s2e-ink); }
/* An ABSOLUTE line box, so neither the <small> unit nor the smaller font on the
   "Price on request" variant can change this row's height. Unitless (1.4) is not
   enough: it scales with the font size, and the two variants use different ones —
   which is what made a priced card 1-3px taller than an unpriced one. */
.s2t-page .s2t-o-price { font-family: var(--s2e-display); font-size: 1.15rem; font-weight: 300; line-height: 1.5rem; min-height: 1.5rem; color: var(--s2e-ink); }
.s2t-page .s2t-o-price small { font-family: var(--s2e-body); font-size: 0.72rem; font-weight: 400; color: var(--s2e-muted); }
.s2t-page .s2t-o-price.s2t-t-rate-none { font-family: var(--s2e-body); font-size: 0.8rem; font-weight: 400; }
.s2t-page .s2t-o-acts { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.1rem; }

.s2t-page .s2t-tcard a:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }

/* ---- the row, narrower ----
   Between the sidebar's own breakpoint and a wide desktop the row still has all
   four compartments side by side, and the name is what gets squeezed: measured
   across the live roster at 1200px, the name column fell to 155px and truncated
   most of it. Trim the photo slice and the two fixed columns instead — the name
   is the one thing on this card nobody can guess from context. */
/* the results column under 960px (every screen under ~1390px used to give it
   that): the compact four-division row */
/* (was 959px: with the roadmaps column gone from the card, the full desktop row
   fits comfortably down to ~760px, so the photo keeps its morning 21% slice) */
@container s2t-results (max-width: 760px) {
  .s2t-page .s2t-tcard { --s2-slice-w: 15%; }
  .s2t-page .s2t-t-body { padding: 1.3rem 1rem 1.3rem calc(17% + 0.9rem); }
  .s2t-page .s2t-t-groups,
  .s2t-page .s2t-t-cta { margin-left: 0.85rem; padding-left: 0.85rem; }
  /* flex-basis, not width: .s2t-t-cta carries flex-basis:0 from the base rule
     above, and a plain `width` is ignored for sizing once flex-basis is
     anything but auto — this was dead until it changed to the longhand that
     actually participates in the flex calculation. */
  .s2t-page .s2t-t-cta { flex-basis: 146px; }
  .s2t-page .s2t-t-groups { flex-basis: 158px; min-width: 138px; }
  .s2t-page .s2t-t-name { font-size: 1.22rem; }
}

/* Below 1300px the two right-hand divisions drop under the details and their
   dividers turn horizontal. 1300, not 1000: between the sidebar's own 1080
   breakpoint and a wide desktop the results column is only ~800px, and three
   divisions plus a photo in that width leaves the name ~190px — measured, that
   truncated 2-3 names per page. Below 620px the photo slice becomes a top band. */
/* the results column under 620px: only then do the offers drop under the details
   (the row holds down to here; stacking any earlier made the card tall and the
   photo a thin slit on laptop widths) */
@container s2t-results (max-width: 620px) {
  .s2t-page .s2t-t-body { flex-direction: column; align-items: stretch; gap: 1rem; padding: 1.2rem 1.25rem 1.25rem calc(19% + 1.1rem); }
  .s2t-page .s2t-t-id { flex: 0 0 auto; }
  .s2t-page .s2t-t-rate-k { text-align: left; }
  .s2t-page .s2t-t-groups,
  .s2t-page .s2t-t-cta { width: auto; flex: 0 0 auto; align-self: auto; border-left: none; border-top: 1px solid var(--s2e-line); margin-left: 0; padding-left: 0; padding-top: 0.9rem; }
  /* Stacked, the one-to-one card puts its two options side by side. They are
     equal-width and nowrap: sized by whatever space was left over, "$10 /
     session" used to wrap a button onto a second line while an unpriced card did
     not — a 15px height difference decided by a price string. */
  .s2t-page .s2t-o-acts { flex-direction: row; }
  .s2t-page .s2t-o-acts a { flex: 1; }
  .s2t-page .s2t-o-price { white-space: nowrap; }
  .s2t-page .s2t-reg, .s2t-page .s2t-login { white-space: nowrap; }
  .s2t-page .s2t-reg { margin-top: 0; }
}

/* the results column under 570px (a 620px screen): the photo becomes a band on top */
@container s2t-results (max-width: 570px) {
  .s2t-page .s2t-tcard { flex-direction: column; }
  .s2t-page .s2t-t-slice { top: var(--s2-frame); bottom: auto; left: 0; right: 0; width: auto; height: 150px; }
  /* the band spans the card, so the disc centres on the card, not on a slice */
  .s2t-page .s2t-t-initials { top: calc(var(--s2-frame) + 75px); left: 50%; }
  /* The band is a wide, short banner, not the portrait-shaped slice the desktop
     row has: a height-sized photo is only ~112px wide in it and sits marooned on
     the mat. Here it fills the band and the crop takes the width instead. */
  .s2t-page .s2t-t-photo { left: 0; transform: none; width: 100%; height: 100%; object-fit: cover; object-position: center 28%; }
  /* clears the band and its frame: the name used to start 30px inside the band,
     which read as a deliberate overlap only while the photo filled its width */
  .s2t-page .s2t-t-body { padding: calc(150px + var(--s2-frame)) 1.25rem 1.25rem; }
  /* free to wrap, but always two lines tall: otherwise a long name makes
     one row 15px taller than the rest */
  .s2t-page .s2t-t-name { white-space: normal; min-height: 2.5em; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
}


/* ---- pagination ---- */
.s2t-page .s2t-pager { display: flex; justify-content: center; align-items: center; gap: 0.35rem; flex-wrap: wrap; margin-top: 1rem; }
.s2t-page .s2t-pg { min-width: 38px; height: 38px; padding: 0 0.5rem; border: 1px solid var(--s2e-ink); background: #fff; color: var(--s2e-ink); font-family: inherit; font-size: 0.88rem; font-weight: 400; cursor: pointer; }
.s2t-page .s2t-pg:hover:not(:disabled) { background: var(--s2e-ink); color: #fff; }
.s2t-page .s2t-pg.on { background: var(--s2e-blue); border-color: var(--s2e-blue); color: #fff; }
.s2t-page .s2t-pg:focus-visible { outline: 2px solid var(--s2e-blue); outline-offset: 2px; }
.s2t-page .s2t-pg:disabled { opacity: 0.4; cursor: default; }
.s2t-page .s2t-pg.dots { border: none; background: none; cursor: default; }


/* per-tick match count, and the disabled look for filters nobody matches yet */
.s2t-page .s2t-tick-n { font-size: 0.72rem; font-weight: 400; color: var(--s2e-muted); min-width: 1.1rem; text-align: center; }
.s2t-page .s2t-tick:has(input:checked) .s2t-tick-n { color: var(--s2e-blue-dark); }
.s2t-page .s2t-tick-dead { opacity: 0.45; cursor: not-allowed; }
.s2t-page .s2t-tick-dead input { cursor: not-allowed; }

/* ---- 2026-09-23: each educator a bordered card; the two offers equal width ----
   Every row is its own card with a prominent black border, spaced apart
   instead of sharing hairlines. The one-to-one and group-classes columns take
   exactly the same width whether or not the tutor has group classes (this
   replaces the 2:1 split above and the 146/158px pair in the 760px query). */
.s2t-page .s2t-grid { gap: 1rem; border-top: 0; border-bottom: 0; }
.s2t-page .s2t-tcard { border: 2px solid #000; }
.s2t-page .s2t-tcard + .s2t-tcard { border-top: 2px solid #000; }
.s2t-page .s2t-t-groups,
.s2t-page .s2t-t-cta,
.s2t-page .s2t-tcard:has(.s2t-g-card) .s2t-t-groups,
.s2t-page .s2t-tcard:has(.s2t-g-card) .s2t-t-cta { flex: 1 1 0; min-width: 0; }
@container s2t-results (max-width: 760px) {
  .s2t-page .s2t-t-groups,
  .s2t-page .s2t-t-cta { flex: 1 1 0; min-width: 0; }
}
@container s2t-results (max-width: 620px) {
  .s2t-page .s2t-t-groups,
  .s2t-page .s2t-t-cta { flex: 0 0 auto; }
}

/* ---- the photo framed inside the bordered card ----
   Now that each educator is a bordered card, the photo gets the same white
   margin on its left as above and below it (--s2-frame), instead of sitting
   flush against the border; the monogram and the details shift with it. */
.s2t-page .s2t-t-slice { left: var(--s2-frame); }
.s2t-page .s2t-t-initials { left: calc(var(--s2-frame) + var(--s2-slice-w) / 2); }
.s2t-page .s2t-t-body { padding-left: calc(23% + var(--s2-frame) + 1.2rem); }
@container s2t-results (max-width: 760px) {
  .s2t-page .s2t-t-body { padding-left: calc(17% + var(--s2-frame) + 0.9rem); }
}
@container s2t-results (max-width: 620px) {
  .s2t-page .s2t-t-body { padding-left: calc(19% + var(--s2-frame) + 1.1rem); }
}
@container s2t-results (max-width: 570px) {
  .s2t-page .s2t-t-slice { left: var(--s2-frame); right: var(--s2-frame); }
  .s2t-page .s2t-t-initials { left: 50%; }
  .s2t-page .s2t-t-body { padding-left: 1.25rem; }
}

/* the one-to-one card: its ask and price stay at the top, and Register / Log in
   sit centred in the space left below them (auto margins in the card's column)
   instead of hugging the price with an empty band underneath */
.s2t-page .s2t-o-acts { margin-top: auto; margin-bottom: auto; }

/* profile link (only when WordPress has a profile page for the tutor, see render.js) */
.s2t-page .s2t-tcard[data-profile] { cursor: pointer; }
.s2t-page .s2t-t-profile { color: inherit; text-decoration: none; }
.s2t-page .s2t-t-profile:hover { color: var(--s2e-blue); }
.s2t-page .s2t-t-more { align-self: flex-start; margin-top: 0.35rem; font-size: 0.82rem; font-weight: 500; color: var(--s2e-blue); text-decoration: none; border-bottom: 1px solid currentColor; }
.s2t-page .s2t-t-more:hover { color: var(--s2e-ink); }
