/* ============================================================
   uni-student.css — the student-app band on the Universities / ESP page
   (ko/solutions/universities.html: #roleplay, #speak, #terms, #writing,
   #routine). Contract: bar-esp-student.md (+ its user ruling); rulings per
   round in bar-esp-student-progress.md. Round 3.

   STRUCTURE is speechify.com's: a platform switcher (recording + synced
   steps), the two-box "Create any Podcast" chapter (≈58/42), a before/after
   pair, and the "More ways" segmented tabs.

   BOX STYLE is the B2C individuals page's #daily (css/individuals.css):
   - radius --radius--2xl on all four corners, overflow clipped;
   - tall/two-up boxes: two system 100 rungs, each mixed 35% with white;
     body inset 11% of the box (.iv-daily__card .iv-daily__body);
   - wide boxes: grey-50 wash picking up a 100 rung from 35% down; body inset
     max(1.25rem, 9.14%) of the text column (.iv-daily__wide .iv-daily__body);
   - text order: title (h3; h1 on wide boxes, h3 once stacked), then ONE grey
     line (body-l; body-2xl on wide boxes at every width).
   PHONES are the preview's CSS mockup (user ruling, 2026-10-06; ported from
   css/esp-preview.css .ep-phone): grey-1000 bezel, grey-200 rim + lift shadow,
   white 9:41 status bar, no island, screen radius concentric with the frame.
   Every app image is an unaltered screenshot or crop, shown whole.
   ============================================================ */

.us-chapter { padding-block: var(--sp-40); }

/* ---- Chapter opener (§5.4): pill → heading → at most one line ---- */
.us-head { max-width: 46rem; }
.us-head--center { margin-inline: auto; text-align: center; }
.us-head__title { color: var(--color--grey-1000); }
.us-head__line {
  margin-top: var(--sp-20);
  max-width: 40rem;
  font-size: var(--fs-body-l);
  line-height: var(--lh-body);
  color: var(--color--grey-800);
}
.us-head--center .us-head__line { margin-inline: auto; }

/* ---- Boxes: #daily's grounds, verbatim constructions ---- */
.us-box,
.us-wide {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius--2xl);
  background-color: var(--color--white);
}
.us-box {
  --_from: var(--color--yellow-100);
  --_to: var(--color--blue-100);
  background-image: linear-gradient(180deg,
    color-mix(in oklab, var(--_from) 35%, var(--color--white)),
    color-mix(in oklab, var(--_to) 35%, var(--color--white)));
}
.us-box[data-tint='yellow-blue']  { --_from: var(--color--yellow-100); --_to: var(--color--blue-100); }
.us-box[data-tint='blue-green']   { --_from: var(--color--blue-100);   --_to: var(--color--green-100); }
.us-box[data-tint='pink-purple']  { --_from: var(--color--pink-100);   --_to: var(--color--purple-100); }
.us-box[data-tint='yellow-green'] { --_from: var(--color--yellow-100); --_to: var(--color--green-100); }
.us-box[data-tint='yellow-pink']  { --_from: var(--color--yellow-100); --_to: var(--color--pink-100); }
.us-box[data-tint='green-blue']   { --_from: var(--color--green-100);  --_to: var(--color--blue-100); }
.us-wide {
  --_tint: var(--color--purple-100);
  background-image:
    linear-gradient(180deg, transparent 35%, color-mix(in oklab, var(--_tint) 60%, transparent) 75%, var(--_tint) 100%),
    linear-gradient(var(--color--grey-50), var(--color--grey-50));
}

/* Tall-box body: #daily's 11% of the box (padding % resolves on the box). */
.us-box__body { position: relative; z-index: 3; padding: 11% 11% 0; }
.us-box__title {
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: var(--lh-snug);
  letter-spacing: var(--kern-heading);
  color: var(--color--grey-1000);
}
.us-box__text {
  margin-top: var(--sp-8);
  font-size: var(--fs-body-l);
  line-height: var(--lh-body);
  color: var(--color--grey-800);
}
/* Wide-box body: #daily's max(1.25rem, 9.14%) of the text column (a grid item,
   so % resolves on its column). */
.us-wide__body { position: relative; z-index: 2; padding-inline: max(1.25rem, 9.14%); }
/* #daily's wide body (.iv-daily__wide--cols .iv-daily__body): the column's full
   height, title at the top (7%), the last group pinned to the foot (9%). */
.us-rp__body,
.us-stage .us-wide__body {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-block: 7% 9%;
}
.us-wide__title {
  font-size: var(--fs-h1);
  font-weight: 500;
  line-height: var(--lh-tight);
  letter-spacing: var(--kern-headline);
  color: var(--color--grey-1000);
}
.us-wide__text {
  margin-top: var(--sp-16);
  max-width: 26rem;
  font-size: var(--fs-body-2xl);   /* at every width, as #daily's wide cards */
  line-height: var(--lh-body);
  color: var(--color--grey-800);
}

/* ---- The phone: the preview's CSS mockup (.ep-phone), renamed ---- */
.us-phone {
  --screen-r: calc(var(--radius--2xl) - var(--sp-4));
  position: relative;
  z-index: 1;
  padding: var(--sp-4);
  border-radius: var(--radius--2xl);
  background: var(--color--grey-1000);
  box-shadow: 0 0 0 0.12rem var(--color--grey-200), var(--shadow--card-large);   /* §6 ladder, forest-tinted, never pure black */
}
.us-phone__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 2.2rem;
  padding-inline: 1.5rem 1.3rem;
  border-radius: var(--screen-r) var(--screen-r) 0 0;
  background: var(--color--white);
  font-size: var(--fs-label);   /* §4.1 label row, not below it */
  font-weight: 500;
  color: var(--color--grey-1000);
}
.us-phone__bar svg { width: 2.6rem; height: auto; }
/* The bar takes the colour of the screenshot's own top row: white, or the app's
   #f7f7f7 ground (sampled; --color--grey-50 is black 4% = #f5f6f6, not a match). */
.us-phone--grey .us-phone__bar { background: #f7f7f7; }
.us-phone__screen {
  position: relative;
  overflow: hidden;
  border-radius: 0 0 var(--screen-r) var(--screen-r);
  background: var(--color--white);
}
.us-phone__screen video,
.us-phone__screen img { display: block; width: 100%; height: auto; }
/* Phones that run off a box's foot: the box's overflow cuts them. */
.us-box .us-phone { position: absolute; }

/* A real UI crop shown whole, as a card. Each crop carries an even 48px
   (source) margin, ≈ 4% of its width; the radius is 3.6% of the card's own
   width (the vertical radius scaled by the crop's aspect), so it stays inside
   that margin at every width. */
.us-card {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 3.6% / calc(3.6% * var(--ar, 1));
  background: var(--color--white);
  box-shadow: var(--shadow--card);
}

/* Floating word-game tiles (#terms), as #daily's flag tiles float round their phone. */
.us-floats { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.us-float {
  position: absolute;
  height: auto;
  display: block;
  border-radius: 12%;   /* the tile's own corner, scaled with it */
  background: var(--color--white);
  box-shadow: var(--shadow--card);
  transform: rotate(var(--r, 0deg));
}

/* ============================================================
   2. #roleplay — the band's opener (pill → h2), then #daily's wide box: text
   left, the whole phone, steps that follow the recording.
   ============================================================ */
.us-rp {
  display: flex;
  align-items: stretch;
  margin-top: var(--sp-40);
}
/* The text column is as wide as its own lines; the phone is centred in what is
   left, so text → phone equals phone → box edge. The inset is the one the
   58% column gave (9.14% of it = 5.3% of the box). */
.us-rp__body { flex: 0 1 auto; min-width: 0; padding: 4.2% 0 5.4% max(1.25rem, 5.484%); }   /* the same title inset as #routine's 60% column: 7% / 9% / 9.14% of it */
.us-rp__media { flex: 1 1 0; }
/* The whole phone, sized to one 1440×900 screen under the nav: 18.8rem wide is
   ≈ 754px tall, the box ≈ 830px with its 2rem top and foot. */
.us-rp__media { position: relative; display: grid; justify-items: center; align-content: center; padding-block: var(--sp-32); }
/* Device-sized (user, 2026-10-06: "핸드폰 사이즈로 알맞게"): 14.4rem = 260px at
   1440, about a real phone's width on screen. The whole phone sits inside. */
.us-rp__phone { width: 14.4rem; }
.us-rp__now { display: none; }

.us-steps {
  list-style: none;
  margin: var(--sp-32) 0 0;
  padding: 0;
  display: grid;
  gap: var(--sp-4);
}
.us-step {
  display: grid;
  grid-template-columns: 2.4rem minmax(0, 1fr);
  column-gap: var(--sp-12);
  align-items: center;
  width: 100%;
  min-height: 44px;
  padding: var(--sp-8) 0;
  border: 0;
  border-radius: var(--radius--l);
  background: transparent;
  font: inherit;
  text-align: left;
  color: inherit;
  cursor: pointer;
}
.us-step:hover .us-step__t { color: var(--color--grey-1000); }
.us-step__n {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--radius--circle);
  background: var(--color--white);
  font-size: var(--fs-body-s);
  font-weight: 500;
  color: var(--color--grey-800);
  transition: var(--transition);
}
.us-step__t {
  font-size: var(--fs-body-l);
  line-height: var(--lh-body);
  color: var(--color--grey-800);
}
/* The playing step shows in its number (user, 2026-10-06: "흰색 박스랑
   프로그레스 바 없애는 방향으로… 숫자 쪽에 컬러로 표시"): the number turns into a
   filled green disc. No bar and no filling ring — a ring that fills is the progress
   bar again. The disc is the homepage's own green — brand-400, the primary-button colour
   (user, 2026-10-11: "아보링고 홈페이지 초록색 컬러에 맞춰줘"; was brand-800). */
.us-step.is-on .us-step__n,
.us-rp__now .us-step__n { background: var(--color--brand-400); color: var(--color--white); }
/* Played steps return to the pending look: colour marks the current number only (user ruling). */

/* Pause / play for the looping recording (WCAG 2.2.2), in the gap right of the
   phone's foot. */
.us-rp__toggle {
  position: absolute;
  z-index: 3;
  right: var(--sp-32);
  bottom: var(--sp-32);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--radius--circle);
  background: var(--color--white);
  color: var(--color--grey-1000);
  box-shadow: var(--shadow--card);
  cursor: pointer;
  transition: box-shadow 300ms var(--ease-global);
}
.us-rp__toggle[hidden] { display: none; }
.us-rp__toggle svg { width: 1rem; height: 1rem; }
.us-rp__toggle .us-rp__icon-play { display: none; }
.us-rp__toggle.is-paused .us-rp__icon-play { display: block; }
.us-rp__toggle.is-paused .us-rp__icon-pause { display: none; }
.us-rp__toggle:hover { box-shadow: var(--shadow--card-large); }

/* ============================================================
   3–4. #speak, #terms — two boxes, ≈58 / 42 (Speechify "Create any Podcast")
   ============================================================ */
.us-duo {
  display: grid;
  grid-template-columns: minmax(0, 58fr) minmax(0, 42fr);
  gap: var(--sp-20);
  margin-top: var(--sp-40);
}
/* Speechify's two-box rows (user, 2026-10-06: "speechify.com에 맞춰서"): a
   landscape wide box (≈ 1.43) and a near-square narrow one (≈ 1.03), 490px tall
   at 1440. */
.us-duo__wide { aspect-ratio: 700 / 512; }
/* The narrow box takes the row's height and never sets it (its card is sized
   to the space left, not the other way round). */
.us-duo__narrow { display: flex; flex-direction: column; contain: size; }
/* One inset for the pair: 11% of the NARROWER box. In the 58fr box that is
   11% × 42/58 = 7.97% of its own width, so both titles share a top line. The
   wide box's text keeps clear of the phone on its right. */
.us-duo__wide .us-box__body { padding: 7.97% calc(7.97% + 13.6rem + var(--sp-16)) 0 7.97%; }
/* The phone, as Speechify's podcast card: its top beside the title, only the
   upper part in view, running off the foot. 13.6rem = 245px at 1440. --cut is
   the share of the screen left in view: #speak stops between the student's
   "Explanation" line and the next bubble; #terms below the meaning and its
   audio button. */
.us-duo__phone {
  --cut: 0.59;
  width: 13.6rem;
  left: auto;
  top: auto;
  right: 7.97%;
  bottom: calc(-1 * ((1 - var(--cut)) * (13.6rem - 0.8rem) * 2.1668 + 0.4rem));
}
.us-terms__wide .us-duo__phone { --cut: 0.6; }
.us-duo__stage {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 11%;   /* the shared inset above (from the text), below and at the sides */
}
/* The quiz card takes a little more of its box so its options read at ≥ 10px. */
/* Right-hand cards: whole, centred, scaled to the space under the text. */
.us-duo__stage .us-card { width: auto; height: auto; max-width: 100%; max-height: 100%; min-height: 0; }

/* Lower-left floats (real crops): #speak's second sent sentence with its
   "Explanation", #terms' word game. Each keeps the pair's shared inset
   (7.97cqw = 11% of the narrower box) from the box edges, from the text above
   and from the phone, at every width: the box is a size container, and the
   float is as large as the space left by the text (title 2 lines + line
   --lines lines) and the phone allows. */
@media (min-width: 961px) {
  .us-duo__wide { container-type: size; }
  .us-float-card {
    --lines: 2;
    --ins: 7.97cqw;
    --room-h: calc(100cqh - 3 * var(--ins) - var(--fs-h3) * 2.4 - var(--sp-8) - var(--fs-body-l) * 1.7 * var(--lines));
    --room-w: calc(100cqw - 3 * var(--ins) - 13.6rem);
    position: absolute;
    z-index: 2;
    left: var(--ins);
    bottom: var(--ins);
    width: min(var(--room-w), var(--room-h) * var(--ar));
    height: auto;
  }
}
.us-copy-nogame { display: none; }

/* ============================================================
   5. #writing — before / after; both cards whole.
   ============================================================ */
.us-ba {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  gap: var(--sp-20);   /* 2rem */
  margin-top: var(--sp-40);
}
/* The cards sit on the box's title inset (11%), as #speak/#terms' crops do. */
.us-ba__sheets {
  display: grid;
  gap: var(--sp-16);
  margin: var(--sp-24) 11% 0;
  padding-bottom: 11%;
}
/* One direction cue, straddling the 2rem gap between the pair. */
.us-ba__cue {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius--circle);
  background: var(--color--white);
  color: var(--color--grey-1000);
  box-shadow: var(--shadow--card);
}
.us-ba__cue svg { width: 1.1rem; height: 1.1rem; }

/* ============================================================
   6. #routine — segmented tabs over one #daily wide box: text left, phone
   right, the phone running off the foot.
   ============================================================ */
.us-routine { margin-top: var(--sp-32); }
.us-tabs {
  display: flex;
  width: max-content;
  max-width: 100%;
  margin-inline: auto;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border-radius: var(--radius--l);   /* §9.9 */
  background: var(--color--grey-50);
  box-shadow: 0 0 0 1px var(--rung);   /* §6 rung 8, the ring that replaces a border */
}
.us-tab {
  min-height: 44px;
  padding: 0.5em 1.3em;
  border: 0;
  border-radius: var(--radius--l);   /* §9.9 */
  background: transparent;
  font: 500 var(--fs-body-s) / var(--lh-body) var(--font-sans, inherit);
  color: var(--color--grey-800);
  cursor: pointer;
  transition: background-color 300ms var(--ease-global), box-shadow 300ms var(--ease-global);
}
.us-tab:hover { color: var(--color--grey-1000); }
.us-tab[aria-selected='true'] {
  background: var(--color--white);
  color: var(--color--grey-1000);
  box-shadow: var(--shadow--card-xsmall);
}
.us-stage {
  --_tint: var(--color--blue-100);
  display: grid;
  grid-template-columns: minmax(0, 60fr) minmax(0, 40fr);
  align-items: center;
  margin-top: var(--sp-24);
  aspect-ratio: 1241 / 520;
}
.us-stage__media { align-self: stretch; position: relative; }
/* #daily's wide-card balance: text left, one device right, taller than the box
   and running off its foot. Device-sized, as #roleplay's. */
.us-stage__phone { position: absolute; left: 39.3%; top: 9%; width: 14.4rem; transform: translateX(-50%); }   /* text → phone ≈ phone → edge */
.us-stage .us-phone__screen { display: grid; }
.us-stage .us-phone__screen img { grid-area: 1 / 1; opacity: 0; transition: opacity 300ms var(--ease-global); }
.us-stage .us-phone__screen img.is-on { opacity: 1; }

/* §10.1 focus: the accent ring, 3px off the control, never animated. */
.us-tab:focus-visible,
.us-step:focus-visible,
.us-rp__toggle:focus-visible { outline: 2px solid var(--color--accent); outline-offset: 3px; }

/* ============================================================
   Tablet / phone — #daily's stacked column: every box 30rem, centred, the
   section heads on the same left edge.
   ============================================================ */
@media (max-width: 960px) {
  .us-head:not(.us-head--center) { max-width: 30rem; margin-inline: auto; }
  .us-wide,
  .us-duo__wide,
  .us-duo__narrow,
  .us-ba__box { width: 100%; max-width: 30rem; margin-inline: auto; aspect-ratio: auto; }
  .us-duo, .us-ba { justify-items: stretch; }

  /* #daily's stacked wide cards: top padding sp-40, body 0 11%, title to h3. */
  .us-wide { padding-top: var(--sp-40); }
  .us-wide__body { padding: 0 11%; }
  .us-wide__title { font-size: var(--fs-h3); line-height: var(--lh-snug); letter-spacing: var(--kern-heading); }

  /* #roleplay: title, line, then the phone, then the steps. */
  .us-rp { display: flex; flex-direction: column; align-items: stretch; }
  .us-rp__body { padding-inline: 0; }
  .us-rp__body { display: contents; }
  .us-rp__copy { order: 1; padding: 7% 11% 0; }   /* #daily stacked: 4rem + 7% from the top */
  .us-rp__media { order: 2; display: block; padding: var(--sp-24) 11% 0; }
  .us-rp__phone { width: min(100%, 14rem); margin-inline: auto; }
  .us-rp__toggle { position: relative; right: auto; bottom: auto; margin: var(--sp-12) auto 0; }
  .us-rp .us-steps { order: 3; margin-top: var(--sp-16); padding: 0 11% 11%; }

  .us-duo { grid-template-columns: minmax(0, 1fr); }
  .us-duo__wide { display: flex; flex-direction: column; aspect-ratio: auto; }
  .us-duo__narrow { contain: none; }
  .us-box .us-phone { position: relative; left: auto; top: auto; right: auto; bottom: auto; }
  .us-duo__wide .us-box__body { padding: 11% 11% 0; }
  /* Stacked: the phone under the text, its upper part only, cut at the same
     screen share as on desktop. */
  .us-duo__phone {
    width: 12.6rem;
    order: 2;
    margin: var(--sp-16) auto calc(-1 * ((1 - var(--cut)) * (12.6rem - 0.8rem) * 2.1668 + 0.4rem));
  }
  .us-duo__stage .us-card { width: 88%; max-width: none; max-height: none; }
  /* Stacked, the tile sits beside the title in the box's top-right corner,
     clear of the text and of the phone below. */
  /* Stacked: #speak's float hides (its title is backed by the phone's own
     bubble); the game sits under the text, at the inset, above the phone. */
  .us-speak__float { display: none; }
  .us-terms__game { order: 1; align-self: flex-start; width: 52%; margin: 11% 11% 0; }
  .us-duo__wide .us-box__body { order: 0; }

  /* Stacked: a flex column so the cue can overlap the 2rem gap (negative
     margins), turned to point down. */
  .us-ba { display: flex; flex-direction: column; gap: var(--sp-20); }
  .us-ba__cue { position: relative; left: auto; top: auto; align-self: center; margin-block: calc(-1 * (var(--sp-20) / 2 + 1.5rem)); transform: rotate(90deg); }

  .us-stage { display: block; aspect-ratio: auto; }
  .us-stage .us-wide__body { display: block; padding: 7% 11% 0; }
  /* Two lines held for the title and two for the line, so the box and its phone
     keep one height as the tabs change. */
  .us-stage .us-wide__title { min-height: 2.4em; }
  .us-stage .us-wide__text { min-height: 3.4em; }
  .us-stage__media { position: static; }
  .us-stage__phone { position: relative; left: auto; top: auto; transform: none; width: min(64%, 14rem); margin: var(--sp-24) auto -36%; }
}
@media (max-width: 640px) {
  .us-tab { padding-inline: 1em; }
  .us-br { display: none; }
  /* The step that is playing, live, right above the phone; the list follows. */
  .us-rp__now {
    display: flex;
    align-items: center;
    gap: var(--sp-12);
    margin-bottom: var(--sp-16);
    font-size: var(--fs-body-l);
    line-height: var(--lh-body);
    color: var(--color--grey-1000);
  }
  .us-rp__now .us-step__n { flex: none; }
}

/* ---- §4.1.2 Hangul: headings 1.2 / −0.016em, body lines 1.7, keep-all ---- */
:lang(ko) .us-box__title,
:lang(ko) .us-wide__title { line-height: var(--lh-heading); letter-spacing: var(--kern-heading); word-break: keep-all; }
:lang(ko) .us-chapter p,
:lang(ko) .us-step__t,
:lang(ko) .us-tab { word-break: keep-all; }
:lang(ko) .us-head__line,
:lang(ko) .us-box__text,
:lang(ko) .us-wide__text,
:lang(ko) .us-step__t,
:lang(ko) .us-rp__now { line-height: var(--lh-ko-body); }

@media (prefers-reduced-motion: reduce) {
  .us-step__n, .us-tab, .us-stage .us-phone__screen img { transition: none; }
}

/* At the narrowest phones the 단원 line takes a third line; hold three. */
@media (max-width: 360px) {
  .us-stage .us-wide__text { min-height: 5.1em; }
}

/* Lower-left floats where they would drop below a readable size: between 961
   and 1199px the text column wraps tighter and the floats shrink to ~140px, so
   they step out. #speak's title is backed by the phone's own bubble; #terms'
   line drops its game clause for as long as the game is not on screen. The same
   holds whenever the boxes stack (≤ 960px), where the game would turn the box
   into a tower (user: "박스도 길쭉해서"). */
@media (max-width: 1199px) {
  .us-speak__float,
  .us-terms__game { display: none; }
  .us-copy-game { display: none; }
  .us-copy-nogame { display: inline; }
}
