/* universities.css — Universities · ESP page.
   Rebuilt 2026-10-01 against bar-universities.md, and aligned in round 4 with
   its sibling `schools.css` so the two simplified solution pages share one
   idiom: the §9.3.1 hero (centred, one CTA, one wide photo), §5.3 panels that
   alternate with plain sections, and the site's own `.pill`, `.btn` and spacing
   tokens rather than values invented here. */

.uni-section { scroll-margin-top: calc(var(--nav-h) + var(--sp-8)); }

/* Imagery (§9.4 R4): a §7 radius, no elevation. */
.uni-photo { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius--2xl); }
.uni-wide { position: relative; aspect-ratio: 9 / 5; }

/* Product shots keep a 4:3 stage; the composed image carries its own ground.
   The stage is capped: at full container width a 4:3 frame runs 931px tall and
   pushes the page past the 7-screen ceiling the bar sets. */
.uni-shot { margin: 0 auto; max-width: 52rem; }
.uni-shot__stage { aspect-ratio: 4 / 3; border-radius: var(--radius--2xl); overflow: hidden; }
.uni-shot__stage img { display: block; width: 100%; height: 100%; object-fit: cover; }
.uni-shot figcaption {
  margin-top: var(--sp-16);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color--grey-800);
  text-align: center;
  margin-inline: auto;
  max-width: 48ch;
}

/* Section pill (§5.4 opener) without an arrow: it labels, it doesn't link. */
.uni-pill { padding: 0.4em 1.2em; border-radius: 1rem; font-size: max(var(--fs-body-xs), 12px); }

/* The line under a heading — one size across the page. */
.uni-line {
  margin-top: var(--sp-20);
  font-size: var(--fs-body-l);
  line-height: var(--lh-body);
  color: var(--color--grey-800);
  margin-inline: auto;
  max-width: 46ch;
}

/* ---- 1. Hero: centred, then one wide photo (§9.3.1) ----------------- */
.uni-hero { padding-block: var(--sp-40); text-align: center; }
.uni-hero__title { margin-inline: auto; }

/* Headings carry a `characters` max-width, so a centred block needs the box
   centred too — text-align alone leaves it flush to the gutter. */
.uni-block .h1,
.uni-panel .h1,
.uni-close .h1 { margin-inline: auto; }
.uni-hero__cta { margin-top: var(--sp-32); }
.uni-hero__photo { margin-top: var(--sp-40); }
.uni-hero__photo picture { display: block; height: 100%; }

/* ---- Centred story sections: heading, line, then one wide shot ------- */
.uni-block { padding-block: var(--sp-40); text-align: center; }
.uni-block__photo { margin-top: var(--sp-40); }

/* ---- An asymmetric two-column row — §5.2's house pattern, at the sibling
   page's 54/46 and 2.0rem gap. The wide half carries the shot. ---------- */
.uni-split { padding-block: var(--sp-40); }
.uni-split__grid {
  display: grid;
  grid-template-columns: minmax(0, 54fr) minmax(0, 46fr);
  gap: 2rem;
  align-items: center;
  text-align: start;
}
.uni-split__text > * + * { margin-top: var(--sp-20); }
.uni-split__text .uni-line { margin-inline: 0; }
.uni-split__text .uni-note {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color--grey-800);
}
.uni-split__grid .uni-shot { max-width: none; width: 100%; }

/* ---- A §5.3 panel, so panels alternate with plain sections ----------- */
.uni-panel {
  margin-inline: var(--sp-8);
  padding-block: var(--sp-56);
  border-radius: var(--radius--2xl);
  background: var(--color--sand-100);
  text-align: center;
}
/* §3.2: a tint pairs with its own family's ink — the heading too, not just the
   body. `schools.css` ships the same value on its sand panel. */
/* Client 2026-10-01: no brown (sand-1000) type. */
.uni-panel .h1 { color: var(--color--grey-1000); }
.uni-panel .uni-line,
.uni-panel .uni-shot figcaption { color: var(--color--grey-800); }

/* ---- Closing section: opens with its heading, no pill. A plain white
   section since 2026-10-01 (user request), so it no longer sits on sand
   next to the #ops panel. */
/* The §5.3 outro panel (sand-100, its own ink), as on the Schools and
   Publishers pages (client, 2026-10-10). No brown type: heading grey-1000,
   line grey-800. */
.uni-close {
  margin: 0 var(--sp-8);
  padding-block: var(--sp-64);
  border-radius: var(--radius--2xl);
  background: var(--color--sand-100);
  color: var(--color--grey-1000);
  text-align: center;
}
.uni-close .h1 { color: var(--color--grey-1000); }
.uni-close .uni-line { color: var(--color--grey-800); }
.uni-close__cta { margin-top: var(--sp-32); }

/* ---- Responsive (§10.3): the photo turns portrait, buttons go wide --- */
@media (max-width: 860px) {
  .uni-hero__photo { aspect-ratio: 4 / 5; }
  .uni-split { padding-block: var(--sp-40); }
.uni-split__grid { grid-template-columns: minmax(0, 1fr); text-align: center; }
  .uni-split__text .uni-line { margin-inline: auto; }
}

@media (max-width: 640px) {
  .uni-hero__cta,
  .uni-close__cta { display: flex; width: 100%; justify-content: center; }
}

/* ---- §4.1.2 Hangul setting. Sizes and weights are unchanged; only leading and
   tracking move, to tokens already on the ladder. Same override `schools.css`
   ships, which is why the KO sibling reads correctly and this page did not. ---- */
:lang(ko) .uni-section h1,
:lang(ko) .uni-section h2 {
  line-height: var(--lh-heading);
  letter-spacing: var(--kern-heading);
  word-break: keep-all;
}
:lang(ko) .uni-section p,
:lang(ko) .uni-section figcaption { line-height: var(--lh-ko-body); word-break: keep-all; }

/* ======================================================================
   #ops — running your programme (the teacher dashboard). bar-uni-ops.md.
   Lattice "Employee growth" (lattice.com/platform/grow), set in the house
   system: a §5.3 sand panel straight after the hero; a sticky left column
   (pill → heading → line, a live index of the five cards, one CTA); five
   equal §9.4 cards on the right. Each card is a pastel tile (a token gradient,
   its own hue pair) with ONE widget centred on it and running off the tile's
   bottom edge — an HTML/CSS redraw of a client teacher screen (round 3: real
   labels and values, secondary text as skeleton bars, like Lattice's tiles) —
   then a label, an H3 and a line.
   Scroll-spy: js/uni-ops.js. Without JS the index is plain anchor links.
   Round 2 (2026-10-01) follows the coordinator's rulings in
   bar-uni-ops-progress.md.
   ====================================================================== */

.uni-ops {
  margin-inline: var(--sp-8);
  padding-block: var(--sp-56);          /* §5.3 panel padding at every width */
  border-radius: var(--radius--2xl);
  background: var(--color--sand-100);
}
.uni-ops__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-32); }

/* ---- Left column: opener (§5.4), index, CTA. Vertical rhythm lives in
   custom properties so short windows can tighten it (see the sticky block). */
.uni-ops__aside {
  --ops-gap-lede: var(--sp-20);
  --ops-gap-index: var(--sp-24);
  --ops-gap-cta: var(--sp-24);
  --ops-row: 2.52rem;
}
.uni-ops__title {
  margin-top: var(--sp-8);              /* .pill + h2 (§4.3) */
  line-height: var(--lh-tight);         /* §4.1's h2 row: 1.0 (KO: §4.1.2 below) */
  color: var(--forest-ink);             /* client 2026-10-01: this section's type is the ink, not the sand pair */
}
/* Each sentence (EN) / phrase (KO) balances on its own, so a break never strands
   a runt ("Shaped to", "덜어요.") and the two halves stay two halves. */
.uni-ops__phrase { display: block; text-wrap: balance; }
/* EN (2026-10-12): "carried beyond the classroom." is wider than the column, so
   the second phrase broke onto two lines and the title ran to three. That made
   the left column too tall to stay sticky (K–12's #teach sticks), so the EN title
   balances as one sentence over two lines instead. */
:lang(en) .uni-ops__title { text-wrap: balance; }
:lang(en) .uni-ops__phrase { display: inline; }
.uni-ops__lede {
  margin-top: var(--ops-gap-lede);
  font-size: var(--fs-body-l);
  line-height: var(--lh-body);
  color: var(--forest-ink);
}

/* The index — Lattice Grow's list, copied at the client's request (2026-10-01:
   "lattice랑 똑같이"): no row fill, muted items with the active one in the
   panel's ink, a 0.72rem ring dot on a 2px rail that fills (sand-400) down to the
   active item (--ops-progress, set by js/uni-ops.js). Measured on lattice.com:
   1.2rem/1.3 text, 0.48rem 0.48rem 0.48rem 0.96rem padding, dot sand-100 with a
   1px sand-200 ring, rail ink at 8%, 0.3s ease. Inactive items are the sand
   midpoint between 600 and 800 (2.9:1, the same contrast as Lattice's #889494) —
   a recorded exception to AA for this list, chosen by the client; the active item
   (sand-1000, 6.15:1), the heading and the CTA carry the section at full contrast. */
.uni-ops__index { margin-top: var(--ops-gap-index); }
.uni-ops__list {
  --ops-dot: 0.72rem;
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}
.uni-ops__list::before,
.uni-ops__list::after {
  content: '';
  position: absolute;
  left: 0;
  top: calc(var(--ops-row) / 2);
  width: 2px;
  height: calc(100% - var(--ops-row));
  background: rgb(0 31 31 / 0.08);
}
.uni-ops__list::after {
  background: var(--color--sand-400);
  transform-origin: top;
  transform: scaleY(var(--ops-progress, 0));
  transition: transform var(--dur) var(--ease-global);
}
.uni-ops__list li { position: relative; z-index: 1; }
.uni-ops .uni-ops__list li a.uni-ops__link {
  /* not an inline link: no §8.5 underline (this selector outweighs styles.css's
     `li a:not(…)` and wins on order) */
  background-image: none;
}
.uni-ops__link {
  position: relative;
  display: flex;
  border-radius: var(--radius--s);      /* §7: the focus ring follows a rounded box */
  /* The box starts one dot-width left of the rail so the focus ring wraps the
     dot instead of cutting it; padding and the dot's offset add the same width
     back, so nothing moves on screen. */
  margin-left: calc(-1 * var(--ops-dot));
  align-items: center;
  min-height: var(--ops-row);
  padding: 0.48rem 0.48rem 0.48rem calc(0.96rem + var(--ops-dot));
  font-size: var(--fs-body-l);
  line-height: var(--lh-body);
  color: color-mix(in srgb, var(--forest-ink) 45%, #fff);   /* the ink, lightened — same Lattice contrast step, now on the black axis */
  transition: color var(--dur) var(--ease-global);
}
.uni-ops__linktext { text-wrap: balance; }
.uni-ops__link:hover,
.uni-ops__link[aria-current='true'] { color: var(--forest-ink); }
.uni-ops__dot {
  position: absolute;
  left: calc(var(--ops-dot) / 2 + 1px);   /* centred on the 2px rail (box starts one dot-width left) */
  top: 50%;
  width: var(--ops-dot);
  height: var(--ops-dot);
  margin-top: calc(var(--ops-dot) / -2);
  border-radius: var(--radius--circle);
  background: var(--color--sand-100);
  box-shadow: inset 0 0 0 1px var(--color--sand-200);
}
.uni-ops__dot::after {
  content: '';
  position: absolute;
  inset: 25%;
  border-radius: var(--radius--circle);
  background: var(--color--sand-200);
  transition: background-color var(--dur) var(--ease-global);
}
.uni-ops__link[aria-current='true'] .uni-ops__dot { box-shadow: inset 0 0 0 1px var(--color--sand-400); }
.uni-ops__link[aria-current='true'] .uni-ops__dot::after { background: var(--color--sand-800); }

.uni-ops__cta { margin-top: var(--ops-gap-cta); }

/* ---- Right column: five equal §9.4 cards ---- */
.uni-ops__cards { display: grid; gap: var(--sp-24); }
.uni-ops__card {
  display: flex;                        /* §9.4: 0.4rem padding and internal gap, overflow hidden */
  flex-direction: column;
  gap: var(--sp-4);
  overflow: hidden;
  padding: var(--sp-4);
  border-radius: var(--radius--l);
  background: #fff;
  box-shadow: var(--shadow--card);
  scroll-margin-top: calc(var(--nav-h) + var(--ops-stick, var(--sp-24)));
}
/* One hue pair per card, from the 100–200 rungs; neighbours never share a family. */
.uni-ops__card[data-hue='meadow'] { --ops-a: var(--color--yellow-100); --ops-b: var(--color--green-200); }
.uni-ops__card[data-hue='sky']    { --ops-a: var(--color--blue-100);   --ops-b: var(--color--purple-200); }
.uni-ops__card[data-hue='peach']  { --ops-a: var(--color--pink-100);   --ops-b: var(--color--yellow-200); }
.uni-ops__card[data-hue='mint']   { --ops-a: var(--color--teal-200);   --ops-b: var(--color--blue-100); }
.uni-ops__card[data-hue='lilac']  { --ops-a: var(--color--violet-100); --ops-b: var(--color--pink-200); }

/* The tile: one box for all five, 1.9:1 at every width, holding one client
   screenshot (.uni-ops__shot, below). */
.uni-ops__tile {
  position: relative;
  margin: 0;
  aspect-ratio: 1.9 / 1;
  overflow: hidden;
  border-radius: var(--radius--m);      /* concentric: 1.2rem card − 0.4rem padding */
  background: linear-gradient(150deg, var(--ops-a) 10%, var(--ops-b) 90%);
}

/* The product shot sits where the redrawn panel used to: the same inset, the
   same §7 radius and §6 rung, running off the tile's bottom edge. Real client
   screenshots (assets/universities/ops), not a redraw — client, 2026-10-01. */
.uni-ops__shot {
  position: absolute;
  left: 11%;
  top: 4.3%;
  width: 78%;
  height: auto;
  display: block;
  border-radius: var(--radius--m);
  box-shadow: var(--shadow--card-large);
}

.uni-ops__body { padding: var(--sp-16) var(--sp-12) var(--sp-12); }
.uni-ops__label {
  font-size: var(--fs-label);           /* §4.1's label row: 0.7rem / 500 */
  font-weight: 500;
  line-height: var(--lh-body);
  color: var(--forest-ink);             /* client 2026-10-01: black type across this section */
}
.uni-ops__h3 {
  margin-top: var(--sp-4);
  font-size: var(--fs-h5);
  font-weight: 500;
  line-height: var(--lh-heading);       /* §4.1's h5 row: 1.2 */
  letter-spacing: var(--kern-heading);
  color: var(--forest-ink);
}
.uni-ops__text {
  margin-top: var(--sp-8);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--forest-ink);
}

/* ---- ≥ 1081: two columns, 45 / 55 (§5.2's asymmetric pair). On the §10.3
   set: at 961 the column (647–670px tall) does not fit a 700–768 window and the
   tiles drop to 454px, so the pair starts above the 1080 breakpoint. ---- */
@media (min-width: 1081px) {
  .uni-ops__grid {
    grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
    gap: var(--sp-20);
    align-items: start;
  }
  /* Five equal cards beside the sticky column (Lattice's are one size). */
  .uni-ops__cards { grid-template-rows: repeat(5, 1fr) auto; }
}
/* Sticky where the column fits under the nav; js/uni-ops.js measures it and
   adds .is-static if it would still run off the bottom. */
@media (min-width: 1081px) and (min-height: 560px) {
  .uni-ops { --ops-stick: var(--sp-24); }
  .uni-ops__aside {
    position: sticky;
    top: calc(var(--nav-h) + var(--ops-stick));
  }
  .uni-ops__aside.is-static { position: static; }
  /* The column carries one more line than K–12's (.uni-ops__aux). Where it would
     overflow, js/uni-ops.js first tightens it to the short-window rhythm below
     (.is-tight) so it keeps sticking, and only drops to static if that still fails. */
  .uni-ops__aside.is-tight {
    --ops-gap-lede: var(--sp-12);
    --ops-gap-index: var(--sp-16);
    --ops-gap-cta: var(--sp-16);
    --ops-row: 2rem;
  }
  .uni-ops__aside.is-tight .uni-ops__link { padding-block: 0.2rem; }
}
/* Short laptop windows (1280×700, 1280×720, 1081×700): same pieces, tighter. */
@media (min-width: 1081px) and (max-height: 820px) {
  .uni-ops { --ops-stick: var(--sp-16); }
  .uni-ops__aside {
    --ops-gap-lede: var(--sp-12);
    --ops-gap-index: var(--sp-16);
    --ops-gap-cta: var(--sp-16);
    --ops-row: 2rem;
  }
  .uni-ops__link { padding-block: 0.2rem; }
}

/* ---- ≤ 1080: one centred column, in DOM order — opener, index, CTA, cards.
   Capped at 34rem so the cards keep the desktop tile's proportions. ---- */
@media (max-width: 1080.98px) {
  .uni-ops__grid { max-width: calc(34rem + 2 * var(--gutter)); }
}
@media (max-width: 640px) {
  .uni-ops__grid { max-width: calc(26rem + 2 * var(--gutter)); }
  .uni-ops__cta { display: flex; width: 100%; white-space: normal; text-align: center; }
}

/* ---- §4.1.2 Hangul. The section h2 and p already take the page's
   `:lang(ko) .uni-section` rules; add the h3 and the index, and keep the label
   on the Latin row (§4.1.2: labels, tags, buttons stay as the Latin row). ---- */
:lang(ko) .uni-ops__h3 {
  line-height: var(--lh-heading);
  letter-spacing: var(--kern-heading);
  word-break: keep-all;
}
/* The index items are navigation labels — §4.1.2's label row (Latin leading). */
:lang(ko) .uni-ops__link { word-break: keep-all; }
:lang(ko) .uni-section .uni-ops__label { line-height: var(--lh-body); }

/* 2026-10-10: the "start without materials" aside under the #ops lede, and
   the new FAQ before the #talk close panel. */
.uni-ops__aux { margin-top: var(--sp-12); font-size: var(--fs-body); line-height: var(--lh-body); color: var(--forest-ink); }
:lang(ko) .uni-ops__aux { line-height: var(--lh-ko-body); word-break: keep-all; }
.uni-faq { padding-bottom: var(--sp-64); }
