/* /apply — admission form.
   Design tokens only, scoped to .page-apply. */

/* ── Page-local lines ──────────────────────────────────────────────────────
   The shared light border token is #E7E1D6, a pale warm hairline tuned for
   editorial pages. On a form it disappears: a field you cannot see the edge of
   does not read as something to type in. These are deliberately heavier and
   navy-tinted so every input has a visible boundary on the cream canvas. Dark
   mode already has enough contrast, so it keeps the shared token.

   2px, not 1.5px: a 1.5px border rounds down to 1px on a 1x display, so the
   half-pixel buys nothing on exactly the screens that needed it most. Fields
   and the card carry the full weight; supporting blocks stay on a hairline so
   the page does not read as a stack of boxes. */
body.page-apply {
  --ap-line: rgba(19, 35, 75, .24);
  --ap-line-strong: rgba(19, 35, 75, .38);
  --ap-line-w: 2px;
  --ap-line-w-soft: 1px;

  /* Stage and header surfaces.
     These MUST come from the raw palette, never from --navy / --navy-deep.
     Those two are semantic roles, and the dark theme remaps --navy to
     graphite-100 — a near-white foreground colour. Using it as a surface
     produced a stage that faded from #F2F3F5 down to near-black with white
     headline text sitting on the pale end: invisible copy on a band that
     looked broken. The palette tokens are never redefined per theme, so they
     stay a surface in both. */
  --ap-stage-from: var(--ice-palette-navy-800, #13234b);
  --ap-stage-to: var(--ice-palette-navy-900, #0c1a38);
  --ap-stage-glow: rgba(217, 112, 44, .2);
  --ap-header-bg: var(--ice-palette-navy-900, #0c1a38);

  /* ── Type scale, deliberately smaller than the rest of the site ──────────
     /apply ships `bodyClass="page-course page-apply"`, which pulls in
     `body.page-course main :is(h1,h2,h3,p,li,dd)` from ice-design-system.css.
     Every one of those declarations is `!important`, so nothing written here
     against `h1` or `p` can ever win — an earlier attempt to shrink the hero
     had no effect at all and the headline stayed at 65px.

     The tokens are the documented way through: the !important rules read
     these, so redefining them re-scales the page from inside the system
     instead of starting an !important war.

     Smaller on purpose. The editorial scale is tuned for pages that are read;
     this one is filled in. A 65px display headline over a form pushed the
     first input most of a screen down and made the page read as a brochure
     rather than an application. */
  --ice-type-h1-size: clamp(1.5rem, 3.2vw, 2.2rem);
  --ice-type-h1-line: 1.14;
  --ice-type-h1-track: -.018em;

  --ice-type-h2-size: clamp(1.28rem, 2.1vw, 1.7rem);
  --ice-type-h2-line: 1.2;
  --ice-type-h2-track: -.014em;

  --ice-type-h3-size: clamp(1rem, 1.3vw, 1.1rem);
  --ice-type-h3-line: 1.32;

  --ice-type-body-size: clamp(.93rem, 1vw, 1rem);
  --ice-type-body-line: 1.62;
}

html[data-theme='dark'] body.page-apply {
  --ap-line: var(--ice-color-border, rgba(127, 127, 127, .42));
  --ap-line-strong: var(--ice-color-border, rgba(127, 127, 127, .42));
  --ap-line-w: 1px;
  --ap-line-w-soft: 1px;

  --ap-stage-from: var(--ice-palette-graphite-800, #313338);
  --ap-stage-to: var(--ice-palette-graphite-950, #1e1f22);
  --ap-stage-glow: rgba(217, 112, 44, .13);
  --ap-header-bg: var(--ice-palette-graphite-900, #232428);
}

/* ── Header ────────────────────────────────────────────────────────────────
   The shared header is built to float transparently over a dark hero image:
   white ink, white-alpha hairlines, and a dark scrim gradient behind it.
   /apply has no hero image — it is a light utility page on cream — so that
   treatment fails twice over: the scrim washes a grey band across the top of
   the page, and white ink lands on a near-white background.

   Put it in normal flow as a solid navy bar instead, which is what /notices
   already does for the same reason. The white ink and hairlines then land on
   navy exactly as designed, and nothing bleeds onto the canvas.

   This also removes the reason the hero reserved ~200px of top padding: with
   the header in flow there is nothing to clear, so the form rises to where it
   belongs instead of sitting below the fold. */
body.page-apply header.site {
  position: relative;
  background: var(--ap-header-bg);
  /* In dark mode --navy-deep resolves to the same graphite as the canvas, so
     without this the nav has no edge and floats into the page. On light navy
     it is barely visible, which is the intent. */
  border-bottom: 1px solid var(--header-hair, rgba(255, 255, 255, .14));
}

body.page-apply header.site::before { content: none; }

/* ── Stage ─────────────────────────────────────────────────────────────────
   A navy band carrying only the headline, with the form card pulled up onto
   its lower edge.

   The previous attempt put the form in a right-hand column. It was visible
   without scrolling, which is what I had optimised for — and it was wrong.
   A right rail is the newsletter-signup position: the eye files it as
   furniture beside the real content, however early it appears. Being above
   the fold is not the same as being the subject.

   Centre plus scale is what makes something the subject. The card is centred,
   wide, elevated, and it overlaps two backgrounds — so it reads as the object
   the page is built around rather than an aside. */
/* Deliberately compact. This is a form, not a campaign page: an oversized
   display headline over two ragged centred lines pushed the first input a
   screen down and made the page read as a brochure. The band now states what
   the page is in as little vertical space as it can, and hands over. */
body.page-apply main .ap-stage {
  padding: clamp(14px, 2vw, 22px) 0 clamp(84px, 8vw, 104px);
  background:
    radial-gradient(120% 140% at 50% 0%, var(--ap-stage-glow), transparent 62%),
    linear-gradient(180deg, var(--ap-stage-from), var(--ap-stage-to));
  color: #fff;
  text-align: center;
}

body.page-apply main .ap-stage__inner { max-width: 820px; }

body.page-apply main .ap-crumb {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin: 0 0 11px;
  font-size: .78rem;
  color: rgba(255, 255, 255, .62);
}

body.page-apply main .ap-crumb a { color: rgba(255, 255, 255, .82); }

body.page-apply main .ap-eyebrow {
  margin: 0 0 7px;
  font-size: .69rem;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--terracotta-soft, #e8a87c);
}

/* One line on a laptop, two on a phone, and never the three-deep display
   block it was. The ceiling is ~36px rather than ~49px. */
body.page-apply main .ap-stage h1 {
  margin: 0 0 8px;
  color: #fff;
  font-size: clamp(1.5rem, 3.4vw, 2.25rem);
  line-height: 1.14;
  letter-spacing: -.018em;
  text-wrap: balance;
}

/* A wider measure so the lede sets as one line at desktop width instead of two
   short centred ones, which is what made it look like ad copy. */
body.page-apply main .ap-stage__lede {
  margin: 0 auto;
  max-width: 78ch;
  font-size: clamp(.92rem, 1.3vw, 1rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, .78);
}

/* ── Form zone ─────────────────────────────────────────────────────────── */

body.page-apply main .ap-formzone { padding: 0 0 clamp(28px, 5vw, 56px); }

/* The sticky "Apply for 2083/84" bar points at this page. On mobile it covers
   the bottom of the form it is advertising, so it costs conversions on the one
   page where it can only ever be a no-op. */
body.page-apply .sticky-cta { display: none; }

body.page-apply main .ap-formcol {
  max-width: 660px;
  margin-inline: auto;
  /* Pulls the card up onto the navy band. */
  /* The pull MUST stay smaller than the stage's bottom padding, or the card
     rides up over the lede and clips it — which is exactly what happened when
     the stage was compacted and this value was left at -108px against 94px of
     padding. Keep the two in step if either changes. */
  margin-top: clamp(-74px, -6vw, -50px);
  position: relative;
  z-index: 2;
}

body.page-apply main .ap-support { padding: clamp(16px, 3vw, 32px) 0 clamp(28px, 5vw, 56px); }

/* NOTE: never use a `padding: X 0` shorthand on an element that also carries
   .wrap — .wrap sets the site gutter via padding-inline, and the shorthand
   silently zeroes it, dumping content against the viewport edge. Sections wrap
   an inner .wrap instead. */

@media (min-width: 900px) {
  /* Supporting facts run across the full width beneath the form, never beside
     it — nothing sits at the same optical level as the fields. */
  body.page-apply main .ap-aside {
    max-width: var(--ice-container-wide, 1100px);
    margin-inline: auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(20px, 3vw, 32px);
    align-items: start;
  }
  body.page-apply main .ap-aside .ap-stats { grid-column: 1 / -1; }
}

/* At-a-glance figures — the reason to keep reading. */
body.page-apply main .ap-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  margin: 0 0 22px;
  padding: 0;
  /* The grid gap shows through as the cell dividers, so this is a line colour,
     not a surface — it has to track the page lines or the dividers vanish. */
  background: var(--ap-line);
  border: var(--ap-line-w-soft) solid var(--ap-line);
  border-radius: 12px;
  overflow: hidden;
}

body.page-apply main .ap-stats > div {
  margin: 0;
  padding: 11px 10px;
  background: var(--ice-color-surface, var(--course-paper, transparent));
}

body.page-apply main .ap-stats dt {
  margin: 0 0 3px;
  font-size: .64rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ice-color-text-muted);
}

body.page-apply main .ap-stats dd {
  margin: 0;
  font-size: clamp(1rem, 3.4vw, 1.35rem);
  font-weight: 700;
  line-height: 1.15;
}

body.page-apply main .ap-callnow {
  margin: 14px 0 0;
  text-align: center;
  font-size: .94rem;
  color: var(--ice-color-text-muted);
  line-height: 1.6;
}

/* Included-at-no-cost block. The free hostel and the Koteshwor bus are the two
   facts that answer "Tathali is too far", which is the objection that has cost
   this college students before — so they get their own treatment rather than
   being buried in a bullet list. */
body.page-apply main .ap-included {
  margin: 0;
  padding: 18px 20px;
  border: var(--ap-line-w-soft) solid var(--ap-line);
  border-radius: 14px;
  background: var(--ice-color-surface-sunken, rgba(127, 127, 127, .06));
}

body.page-apply main .ap-included__head {
  margin: 0 0 14px;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ice-color-text-muted);
}

body.page-apply main .ap-included ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }

body.page-apply main .ap-included li {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: 'tag name' '. desc';
  gap: 3px 10px;
  align-items: center;
}

body.page-apply main .ap-included__tag {
  grid-area: tag;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--ice-color-accent, #c41e3a);
  /* Every filled role in this palette ships an explicit ink; #fff was not it
     (white on terracotta-400 measures 2.43:1). */
  color: var(--ice-color-on-accent, #0c1a38);
  font-size: .64rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
}

body.page-apply main .ap-included li b { grid-area: name; font-weight: 700; font-size: 1.02rem; }
body.page-apply main .ap-included li span:last-child {
  grid-area: desc;
  color: var(--ice-color-text-muted);
  font-size: .91rem;
  line-height: 1.55;
}

body.page-apply main .ap-promises { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }

body.page-apply main .ap-promises li {
  display: grid;
  gap: 3px;
  padding-left: 26px;
  position: relative;
  line-height: 1.55;
}

body.page-apply main .ap-promises li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .5em;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ice-color-accent, #c41e3a);
}

body.page-apply main .ap-promises b { font-weight: 700; }
body.page-apply main .ap-promises span { color: var(--ice-color-text-muted); font-size: .94rem; }

/* ── Card ──────────────────────────────────────────────────────────────── */

/* Opaque, not translucent, and genuinely raised: it sits across the seam
   between the navy band and the cream canvas, so it has to read as a solid
   object lying on top of both. The shadow is what sells that. */
body.page-apply main .ap-formcard {
  padding: clamp(24px, 3.6vw, 44px);
  border: 1px solid var(--ap-line);
  border-radius: 20px;
  background: var(--ice-color-surface, #fffdf9);
  box-shadow:
    0 1px 2px rgba(12, 26, 56, .06),
    0 18px 44px -12px rgba(12, 26, 56, .28),
    0 44px 90px -40px rgba(12, 26, 56, .32);
}

html[data-theme='dark'] body.page-apply main .ap-formcard {
  background: var(--ice-color-surface-raised, #26282c);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, .7);
}

body.page-apply main .ap-progress {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 5px;
  margin-bottom: 12px;
}

body.page-apply main .ap-progress__seg {
  height: 4px;
  border-radius: 999px;
  background: var(--ice-color-border, rgba(127, 127, 127, .3));
  transition: background .28s ease;
}

body.page-apply main .ap-progress__seg.is-done,
body.page-apply main .ap-progress__seg.is-now { background: var(--ice-color-accent, #c41e3a); }
body.page-apply main .ap-progress__seg.is-now { opacity: .6; }

/* Secondary text on this page is muted with the ink token, never with
   `opacity`. Opacity fades a string toward whatever is behind it, so the same
   declaration lands at a different ratio on the white card, the cream canvas
   and the graphite card — which is how 37 nodes on this page were sitting
   between 2.5:1 and 4.3:1 in light and 9 more in dark. `--ice-color-text-muted`
   is defined per theme and clears AA on both. Keep opacity for bars, scrims
   and animation; not for words. */
body.page-apply main .ap-stepcount {
  margin: 0 0 12px;
  font-size: .78rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ice-color-text-muted);
}

body.page-apply main .ap-step { border: 0; margin: 0; padding: 0; min-width: 0; }

body.page-apply main .ap-step legend {
  padding: 0;
  font-size: clamp(1.15rem, 2.6vw, 1.4rem);
  font-weight: 700;
  line-height: 1.3;
}

body.page-apply main .ap-hint { margin: 5px 0 16px; color: var(--ice-color-text-muted); line-height: 1.55; font-size: .95rem; }

body.page-apply main .ap-field { margin-bottom: 18px; }

body.page-apply main .ap-field label,
body.page-apply main .ap-field .ap-label {
  display: block;
  margin-bottom: 7px;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ice-color-text-muted);
}

body.page-apply main .ap-req { color: var(--ice-color-text-action, #c41e3a); }

/* Reads as a quiet aside next to the uppercase label, not part of it — so the
   field visibly does not demand an answer. */
body.page-apply main .ap-optional {
  opacity: .55;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}

body.page-apply main .ap-field input[type='text'],
body.page-apply main .ap-field input[type='tel'],
body.page-apply main .ap-field select,
body.page-apply main .ap-field textarea {
  width: 100%;
  padding: 13px 14px;
  border: var(--ap-line-w) solid var(--ap-line);
  border-radius: 10px;
  background: var(--ice-color-surface, transparent);
  color: inherit;
  font: inherit;
  font-size: 1.02rem;
}

body.page-apply main .ap-field textarea { resize: vertical; }

body.page-apply main .ap-field input:focus-visible,
body.page-apply main .ap-field select:focus-visible,
body.page-apply main .ap-field textarea:focus-visible {
  outline: 2px solid var(--ice-color-accent, #c41e3a);
  outline-offset: 2px;
}

body.page-apply main .ap-field small { display: block; margin-top: 6px; color: var(--ice-color-text-muted); line-height: 1.5; }

/* The single field the whole page exists to collect. Sized like a code entry,
   because that is what it is: one number, typed once, from memory. */
body.page-apply main .ap-rankfield input[type='text'] {
  padding: 14px 18px;
  border-width: 2px;
  border-color: var(--ap-line-strong);
  border-radius: 14px;
  font-size: clamp(1.75rem, 5.4vw, 2.4rem);
  font-weight: 700;
  letter-spacing: .14em;
  text-align: center;
}

body.page-apply main .ap-rankfield input[type='text']::placeholder {
  font-weight: 600;
  letter-spacing: .14em;
  /* `--ice-color-text-muted`, not `opacity:.26`.
     This is the one field the whole /apply page exists to collect, and its
     placeholder is the only thing in the box telling a visitor what shape of
     value goes in it. At .26 it measured 1.76:1 in light and 2.20:1 in dark:
     under the 4.5:1 placeholder floor, and under even the 3:1 large-text floor,
     on a screen an applicant is reading outdoors on a phone.

     Opacity was also the wrong instrument for the same reason ice-answers.css
     gives at the top of its file — it composites toward whatever is behind, so
     one value lands at three different ratios across the field, the card and
     the two themes. The muted role is already tuned per theme.

     `opacity:1` is explicit because Firefox still applies its own default
     placeholder opacity, which would re-dim the tokened colour. */
  color: var(--ice-color-text-muted);
  opacity: 1;
}

body.page-apply main .ap-rankfield small { text-align: center; }

body.page-apply main .ap-note { margin: 0; font-size: .9rem; color: var(--ice-color-text-muted); line-height: 1.55; }

/* ── Pass-list match ───────────────────────────────────────────────────── */

body.page-apply main .ap-found { margin: 0 0 18px; }

body.page-apply main .ap-found__status {
  margin: 0;
  padding: 11px 13px;
  border-radius: 9px;
  background: var(--ice-color-surface-sunken, rgba(127, 127, 127, .09));
  font-size: .92rem;
  line-height: 1.55;
}

body.page-apply main .ap-found__card {
  padding: 16px;
  border: 1px solid var(--ice-color-accent, #c41e3a);
  border-radius: 12px;
  background: rgba(196, 30, 58, .06);
}

body.page-apply main .ap-found__name {
  margin: 0 0 12px;
  font-size: clamp(1.2rem, 3.4vw, 1.5rem);
  font-weight: 700;
  line-height: 1.25;
}

body.page-apply main .ap-found__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin: 0 0 16px;
}

body.page-apply main .ap-found__meta div { min-width: 0; }

body.page-apply main .ap-found__meta dt {
  margin: 0 0 2px;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ice-color-text-muted);
}

body.page-apply main .ap-found__meta dd { margin: 0; font-size: .96rem; font-weight: 600; }

/* --ice-color-text is a FOREGROUND role, used here as a foreground — the safe
   half of the lesson that made the stage band white-on-white. It flips with the
   theme, so this reads in both; the card's inherited ink is the muted secondary
   grey, which measures 4.27:1 at this size in light mode and is the wrong
   emphasis for a result disclosure besides. The wash is a translucent overlay
   rather than a token so it tints whatever surface it lands on.

   No accent rule down one edge: this already sits inside a bordered, tinted
   card, so a second bordered box within it is one frame too many. The amber
   wash alone separates it from the identity above. */
body.page-apply main .ap-found__flag {
  margin: 0 0 14px;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(184, 124, 20, .18);
  color: var(--ice-color-text, inherit);
  font-size: .9rem;
  line-height: 1.55;
}

body.page-apply main .ap-found__actions { display: flex; flex-wrap: wrap; gap: 9px; }

/* ── Choices ───────────────────────────────────────────────────────────── */

body.page-apply main .ap-choices { display: grid; gap: 9px; margin-bottom: 20px; }

body.page-apply main .ap-choice { display: block; cursor: pointer; }
body.page-apply main .ap-choice input { position: absolute; opacity: 0; pointer-events: none; }

body.page-apply main .ap-choice__body {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border: var(--ap-line-w) solid var(--ap-line);
  border-radius: 10px;
  transition: border-color .18s ease, background .18s ease;
}

body.page-apply main .ap-choice__body b { font-weight: 600; }
body.page-apply main .ap-choice__body small { color: var(--ice-color-text-muted); white-space: nowrap; font-size: .85rem; }

body.page-apply main .ap-choice input:checked + .ap-choice__body {
  border-color: var(--ice-color-accent, #c41e3a);
  background: rgba(196, 30, 58, .07);
}

body.page-apply main .ap-choice input:focus-visible + .ap-choice__body {
  outline: 2px solid var(--ice-color-accent, #c41e3a);
  outline-offset: 2px;
}

body.page-apply main .ap-pills { display: flex; flex-wrap: wrap; gap: 8px; }
body.page-apply main .ap-pill { cursor: pointer; }
body.page-apply main .ap-pill input { position: absolute; opacity: 0; pointer-events: none; }

body.page-apply main .ap-pill span {
  display: inline-block;
  padding: 9px 16px;
  border: var(--ap-line-w) solid var(--ap-line);
  border-radius: 999px;
  font-size: .94rem;
  transition: border-color .18s ease, background .18s ease;
}

body.page-apply main .ap-pill input:checked + span {
  border-color: var(--ice-color-accent, #c41e3a);
  background: rgba(196, 30, 58, .1);
  font-weight: 600;
}

body.page-apply main .ap-pill input:focus-visible + span {
  outline: 2px solid var(--ice-color-accent, #c41e3a);
  outline-offset: 2px;
}

/* ── Actions ───────────────────────────────────────────────────────────── */

body.page-apply main .ap-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 22px;
}

body.page-apply main .ap-actions .btn { flex: 1 1 auto; justify-content: center; text-align: center; }

/* The shared .btn rule sets `display`, which outranks the `hidden` attribute —
   without this, Back and Submit stay visible on every step. */
body.page-apply main .ap-actions .btn[hidden] { display: none; }

body.page-apply main .ap-error {
  margin: 16px 0 0;
  padding: 11px 14px;
  border-radius: 9px;
  background: rgba(196, 30, 58, .12);
  font-size: .93rem;
  line-height: 1.5;
}

body.page-apply main .ap-privacy { margin: 16px 0 0; font-size: .85rem; color: var(--ice-color-text-muted); line-height: 1.55; }

/* ── Done ──────────────────────────────────────────────────────────────── */

body.page-apply main .ap-done { text-align: center; padding: clamp(16px, 3vw, 34px) 0; }

body.page-apply main .ap-done__tick {
  width: 56px;
  height: 56px;
  margin: 0 auto 18px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ice-color-accent, #c41e3a);
  color: #fff;
  font-size: 1.7rem;
}

body.page-apply main .ap-done h2 { margin: 0 0 10px; }
body.page-apply main .ap-done p { margin: 0 0 12px; line-height: 1.62; }
body.page-apply main .ap-done__meta { font-size: .92rem; opacity: .8; }
body.page-apply main .ap-done__next { margin-top: 20px; }

/* ── What happens next ─────────────────────────────────────────────────── */

body.page-apply main .ap-next { padding-block: clamp(28px, 5vw, 60px); }

body.page-apply main .ap-timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: apstep;
  display: grid;
  gap: 20px;
}

@media (min-width: 900px) {
  body.page-apply main .ap-timeline { grid-template-columns: repeat(4, 1fr); gap: 26px; }
}

body.page-apply main .ap-timeline li {
  counter-increment: apstep;
  padding-top: 42px;
  position: relative;
  line-height: 1.6;
}

body.page-apply main .ap-timeline li::before {
  content: counter(apstep);
  position: absolute;
  top: 0;
  left: 0;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--navy, #13234b);
  color: #fff;
  font-size: .85rem;
  font-weight: 700;
}

html[data-theme='dark'] body.page-apply main .ap-timeline li::before {
  background: var(--ice-color-text-accent, #8fa8dd);
  color: #10141c;
}

body.page-apply main .ap-timeline b { display: block; margin-bottom: 5px; }
body.page-apply main .ap-timeline p { margin: 0; color: var(--ice-color-text-muted); font-size: .95rem; }

/* Was a disclaimer about IOE allocating seats. True, but common knowledge, so
   it spent the closing slot of the page restating something the reader already
   knew. The same space now carries the offer to call the guardian, which is
   what the optional guardian fields in step 2 are actually for. */
body.page-apply main .ap-parents {
  margin: clamp(24px, 4vw, 40px) 0 0;
  padding: clamp(16px, 2.5vw, 24px);
  border-radius: 12px;
  background: var(--ice-color-surface-sunken, rgba(127, 127, 127, .08));
  line-height: 1.66;
}

/* ── Come and see it ───────────────────────────────────────────────────── */

body.page-apply main .ap-see { padding-block: clamp(28px, 5vw, 60px); }

body.page-apply main .ap-gallery {
  display: grid;
  gap: 16px;
  margin: 24px 0 28px;
  grid-template-columns: 1fr;
}

@media (min-width: 760px) {
  body.page-apply main .ap-gallery { grid-template-columns: repeat(3, 1fr); }
}

body.page-apply main .ap-gallery figure { margin: 0; }
body.page-apply main .ap-gallery img { width: 100%; height: auto; display: block; border-radius: 12px; }
body.page-apply main .ap-gallery figcaption {
  margin-top: 9px;
  font-size: .88rem;
  color: var(--ice-color-text-muted);
}

body.page-apply main .ap-see .cta-row { display: flex; flex-wrap: wrap; gap: 10px; }

/* ── Live IOE window strip ─────────────────────────────────────────────────
   Sits above the hero, so the deadline is the first thing read. Amber, not
   crimson: crimson is the brand's action colour and is already carrying the
   Apply button in the header, so a crimson bar here would compete with the
   thing we want clicked. */

body.page-apply main .ap-deadline {
  background: linear-gradient(100deg, #7a3d09, #a8560f 58%, #7a3d09);
  color: #fff8ef;
  border-bottom: 1px solid rgba(0, 0, 0, .28);
}

/* One line, always. This strip sits above the hero, so every pixel it takes
   is a pixel of delay before the first input. It carries the date and nothing
   else; the reasoning that used to sit under it moved into the form's own
   step copy, where it is read instead of scrolled past. */
body.page-apply main .ap-deadline__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 12px;
  padding-block: 8px;
}

body.page-apply main .ap-deadline__flag {
  margin: 0;
  flex: 0 0 auto;
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .17);
  border: 1px solid rgba(255, 255, 255, .34);
  font: 800 .6rem/1.35 var(--sans);
  letter-spacing: .07em;
  text-transform: uppercase;
}

body.page-apply main .ap-deadline__body {
  margin: 0;
  line-height: 1.4;
  font-size: .88rem !important;
}

body.page-apply main .ap-deadline__body b {
  font-size: .92rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Window shut. Drop the urgency colour rather than shouting a dead date. */
body.page-apply main .ap-deadline.is-closed {
  background: var(--ice-palette-navy-900, #0c1a38);
}

/* Window not open yet. The amber above means "act on this today", and a list
   that has not published cannot be acted on, so the strip steps down to the
   same navy the closed state uses. It steps back up to amber by itself when
   `data-opens` passes — apply-deadline.js owns the class and the flag. */
body.page-apply main .ap-deadline.is-pending {
  background: var(--ice-palette-navy-900, #0c1a38);
}

/* ── Free, and directly under the form ────────────────────────────────────
   Hostel, bus and the visit are the three facts that decide the answer in most
   Nepali households, and they were sitting in an aside two screens down. Three
   short items immediately below the card instead. */

body.page-apply main .ap-free {
  list-style: none;
  display: grid;
  gap: 10px;
  margin: 18px 0 0;
  padding: 0;
  grid-template-columns: 1fr;
}

@media (min-width: 620px) {
  body.page-apply main .ap-free { grid-template-columns: repeat(3, 1fr); }
}

body.page-apply main .ap-free li {
  padding: 11px 13px;
  border: var(--ap-line-w-soft) solid var(--ap-line);
  border-radius: 10px;
  background: var(--ice-color-surface-sunken, rgba(127, 127, 127, .06));
  font-size: .86rem !important;
  line-height: 1.45 !important;
}

body.page-apply main .ap-free b {
  display: block;
  margin-bottom: 2px;
  color: var(--ice-color-text-accent, #a8560f);
  font-weight: 800;
}

body.page-apply main .ap-free span { color: var(--ice-color-text-muted); }

/* ── In-form story nugget ─────────────────────────────────────────────────
   The "did you know" material used to be a six-card section below the form.
   It was six screens of scrolling for a page whose only job is a submission,
   and a student never reached it. One short line per step instead, inside the
   card, revealed by the step they are already on: it costs no scroll, it is
   read because it sits under the field they just filled, and each line carries
   the one fact that makes the next click feel urgent.

   No JavaScript. Each nugget lives inside its own fieldset, so it appears and
   disappears with the step for free. */

/* No left accent bar. The colour cue is already carried by the "Did you know"
   label, so a bar only adds the stuck-on-tab look; a hairline the whole way
   round reads as a quieter aside and matches the other supporting blocks. */
/* The "Did you know" panels carry the two facts that most often decide a
   family's answer — the free hostel and the free bus — and they were reading as
   fine print beside the field the student was actually typing into. So they now
   glow: a soft accent halo that breathes, on a warmer panel.

   The halo is a pseudo-element carrying a STATIC box-shadow whose OPACITY is
   animated, rather than an animated box-shadow on the panel itself. Same look,
   but it composites instead of repainting a blur on every frame next to a live
   text input — which matters, because most of these students are filling this
   in on an inexpensive Android phone.

   An inner sheen sweep was tried first and cut: white-on-cream at this size was
   invisible in every frame, so it was complexity that bought nothing.

   Under prefers-reduced-motion the animation stops and the halo holds at a
   brighter resting value, so the emphasis survives without the movement. */

body.page-apply main .ap-nugget {
  position: relative;
  isolation: isolate;
  margin: 20px 0 0;
  padding: 12px 14px;
  border: var(--ap-line-w-soft) solid
    color-mix(in srgb, var(--ice-color-text-accent, #a8560f) 42%, var(--ap-line));
  border-radius: 10px;
  background: color-mix(in srgb, var(--ice-color-text-accent, #a8560f) 11%, transparent);
}

body.page-apply main .ap-nugget::before {
  content: '';
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: 11px;
  pointer-events: none;
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ice-color-text-accent, #a8560f) 55%, transparent),
    0 0 18px 2px color-mix(in srgb, var(--ice-color-text-accent, #a8560f) 46%, transparent),
    0 0 44px 6px color-mix(in srgb, var(--ice-color-text-accent, #a8560f) 22%, transparent);
  opacity: .25;
  animation: ap-nugget-breathe 3.4s ease-in-out infinite;
}

@keyframes ap-nugget-breathe {
  0%, 100% { opacity: .22; }
  50%      { opacity: .95; }
}

@media (prefers-reduced-motion: reduce) {
  body.page-apply main .ap-nugget::before { animation: none; opacity: .6; }
}

body.page-apply main .ap-nugget p {
  position: relative;
  margin: 0;
  font-size: .88rem !important;
  line-height: 1.55 !important;
}

body.page-apply main .ap-nugget b {
  color: var(--ice-color-text-accent, #a8560f);
  font-weight: 800;
  letter-spacing: .01em;
}

body.page-apply main .ap-nugget b::after {
  content: ' · ';
  opacity: .5;
}

/* ── Plan the visit ────────────────────────────────────────────────────────
   A route through the campus, in the order we actually walk it, beside the one
   box that says how to book. */

body.page-apply main .ap-visit {
  display: grid;
  gap: clamp(18px, 3vw, 30px);
  margin: clamp(22px, 3.5vw, 34px) 0 clamp(24px, 4vw, 38px);
  grid-template-columns: 1fr;
  align-items: start;
}

@media (min-width: 940px) {
  body.page-apply main .ap-visit { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
}

body.page-apply main .ap-visit__list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: apvisit;
  display: grid;
  gap: 16px;
}

body.page-apply main .ap-visit__list li {
  counter-increment: apvisit;
  position: relative;
  padding-left: 46px;
  line-height: 1.62;
}

body.page-apply main .ap-visit__list li::before {
  content: counter(apvisit);
  position: absolute;
  top: 1px;
  left: 0;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--navy, #13234b);
  color: #fff;
  font-size: .85rem;
  font-weight: 700;
}

html[data-theme='dark'] body.page-apply main .ap-visit__list li::before {
  background: var(--ice-color-text-accent, #8fa8dd);
  color: #10141c;
}

body.page-apply main .ap-visit__list b { display: block; margin-bottom: 4px; }
body.page-apply main .ap-visit__list span { display: block; font-size: .94rem; color: var(--ice-color-text-muted); }

body.page-apply main .ap-visit__aside {
  padding: clamp(18px, 2.6vw, 26px);
  border: var(--ap-line-w) solid var(--ap-line-strong);
  border-radius: 14px;
  background: var(--ice-color-surface-sunken, rgba(127, 127, 127, .07));
}

body.page-apply main .ap-visit__head {
  margin: 0 0 8px;
  font: 800 .68rem/1.3 var(--sans);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ice-color-text-accent, #a8560f);
}

body.page-apply main .ap-visit__aside p { line-height: 1.66; }
body.page-apply main .ap-visit__aside .cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 16px 0 0;
}

body.page-apply main .ap-visit__note {
  margin: 14px 0 0;
  font-size: .87rem;
  color: var(--ice-color-text-muted);
}

iframe[name='apply-sink'] { display: none; }
