/* Career — Figma 388:56 (default), 388:245 (expanded), 388:470 (start-up detail) */

.career-top { display: flex; gap: 23px; align-items: flex-start; }

.profile-card {
  flex: 1 1 auto;
  height: 181px;
  background: var(--panel);
  border-radius: 20px;
  box-shadow: var(--sh-2);
  display: flex;
  align-items: center;
  gap: 38px;
  padding: 0 40px 0 25px;
}

.profile-card__avatar {
  flex: 0 0 128px;
  width: 128px; height: 128px;
  border-radius: 50%;
  background: var(--placeholder);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.profile-card__avatar img { width: 96px; height: auto; }

.profile-card__name { font-family: var(--font-hand); font-size: 45px; line-height: 1.05; font-weight: 400; }
.profile-card__meta { color: var(--ink-2); font-size: 16px; margin-top: 6px; }
.profile-card__meta span { display: block; }
.profile-card__cta { margin-left: auto; }

/* 286 / 1124 of the 1440 frame's content area — the fixed px width of the frame
   expressed as its share of whatever the content area is now. */
/* The slot holds the row's geometry (286 / 1124 of the 1440 frame). The panel
   inside it is absolutely placed, so opening the full list drops it down over
   the page instead of pushing `.career-body` and the visa banner around. */
.saved-rail-slot {
  position: relative;
  flex: 0 1 25.45%;
  min-width: 240px;
  height: 180px;
  z-index: 20;
}
/* while the list is open the slot rises above the scrim */
.main.is-saved-open .saved-rail-slot { z-index: 22; }

.saved-rail {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 180px;
  overflow: hidden;
  transition: height var(--panel-ms) var(--ease-out), box-shadow var(--panel-ms) var(--ease-out);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 18px;
}
/* The head row is the height of the label (16px) so the 24px arrow button
   overhangs it evenly — that is how 388:56 has it: label 18..34 from the panel
   top, arrow box 13..37. */
.saved-rail__head {
  display: flex; align-items: center; justify-content: space-between;
  height: 16px;
}

/* 388:56 replaced the flat glyph with a brick-red accent arrow button. It is
   the same control as the toolbar ⤢, so it carries the same two icons. */
.saved-rail__toggle {
  flex: 0 0 24px;
  width: 24px; height: 24px;
  margin-right: -5px;          /* icon box ends 13px from the panel edge, per the frame */
  display: grid; place-items: center;
  border-radius: 6px;
  color: var(--accent);
  transition: background .15s ease;
}
.saved-rail__toggle:hover { background: var(--accent-tint); }
.saved-rail__toggle img { width: 24px; height: 24px; }
.saved-rail__toggle .icon-collapse { display: none; }
.saved-rail.is-open .saved-rail__toggle .icon-collapse { display: block; }
.saved-rail.is-open .saved-rail__toggle .icon-expand { display: none; }

/* Open: the panel grows to fit the whole list, capped so it can never run off
   the bottom of a short window — the list scrolls inside it past that point. */
.saved-rail.is-open {
  height: var(--saved-open-h, 420px);
  box-shadow: var(--sh-4);
}
.saved-rail.is-open .saved-rail__list {
  max-height: calc(var(--saved-open-h, 420px) - 52px);
  overflow-y: auto;
}

.saved-rail__list { margin-top: 15px; }

/* The scrim behind the open list. It covers the page, not the rail: the rail's
   slot sits above it, so the list stays crisp while everything else recedes. */
.saved-scrim {
  position: fixed;
  inset: 0;
  z-index: 18;
  background: rgba(27, 25, 22, .22);
  backdrop-filter: blur(2px);
  animation: savedScrimIn .18s ease-out;
}
.saved-scrim[hidden] { display: none; }
/* the corner pigeon sits above the page, so it recedes with everything else */
body.saved-open .mascot { opacity: .3; filter: blur(2px); pointer-events: none; transition: opacity .18s ease; }
@keyframes savedScrimIn { from { opacity: 0; } to { opacity: 1; } }

/* Each row opens the listing it names, so it is a <button> now. A button is
   inline-block and centre-aligned by default and the rows are full-width text,
   so the three defaults have to be put back before the drawn spacing means
   anything again. base.css already zeroes button padding, so `padding-bottom`
   below is the only inset the row has. */
.saved-rail__item {
  display: block;
  width: 100%;
  text-align: left;
  cursor: pointer;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
/* `:last-child` is element-agnostic, so it still finds the bottom row now that
   the rows are buttons. `:last-of-type` is the belt to that braces: if anything
   non-button ever ends up inside the list (an empty state, a JS sentinel) the
   last row must still lose its rule rather than draw a line into thin air. */
.saved-rail__item:last-child,
.saved-rail__item:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }

/* Each saved title now sits on a tinted pill (402:71 peach, 402:73 sage).
   The drawn rect runs from 7px left of the text column to 33px short of its
   right edge, and is 24px tall around 20px of text. */
.saved-rail__title {
  display: block;
  margin: 0 33px 0 -7px;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--accent-tint);
  font-size: 15px; font-weight: 500; line-height: 20px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: filter .15s ease, border-color .15s ease;
}
.saved-rail__item[data-tone="sage"] .saved-rail__title { background: var(--green-tint); }
/* The pill is the only part of the row that is already a drawn object, so it is
   the part that answers the pointer — it lightens and its hairline picks up the
   accent. Nothing moves: the rail is a fixed-height box and a row that shifted
   would push the ones under it. Focus mirrors hover so the keyboard sees the
   same row highlighted that the global focus ring is already outlining. */
.saved-rail__item:hover .saved-rail__title,
.saved-rail__item:focus-visible .saved-rail__title {
  filter: brightness(1.05);
  border-color: var(--accent-line);
}
/* a <span> inside a button, so it needs the block it used to get for free */
.saved-rail__sub { display: block; font-size: 13px; color: var(--ink-2); margin-top: 2px; }

/* The head's live tally of what is in the rail. Small enough to read as an
   annotation on the eyebrow rather than a second label, and it has to cancel
   the eyebrow's 1.2px tracking or the digits drift apart inside the pill. */
.saved-rail__count {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--border-soft);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-3);
}

/* Shown by JS when the last bookmark comes off. Sits where the first row would
   have been, so the panel does not read as broken — just empty. No `display`
   here on purpose: it is toggled with [hidden]. */
.saved-rail__empty { font-size: 13px; line-height: 1.5; color: var(--ink-3); margin-top: 16px; }

/* --- toolbar --------------------------------------------------------------- */

/* The wide start-ups panel is pulled 29px up to sit level with this row, so the
   row would otherwise peek out above it. It goes fully hidden while the panel is
   open and comes back when it closes — visibility rather than display, so the
   panel does not jump 65px up the page mid-swipe. */
.career-page.is-startups-wide .career-tools {
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--panel-ms) var(--ease-in), visibility 0s linear var(--panel-ms);
}

.career-tools {
  display: flex; align-items: center; gap: 22px;
  margin: 27px 0 10px;
  opacity: 1;
  transition: opacity var(--panel-ms) var(--ease-out);
}
.expand-toggle {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 6px;
}
.expand-toggle:hover { background: var(--accent-tint); }
.expand-toggle img { width: 28px; height: 28px; }
.expand-toggle .icon-collapse { display: none; }
.is-expanded .expand-toggle .icon-collapse { display: block; }
.is-expanded .expand-toggle .icon-expand { display: none; }

/* base.css ships .tag--internship / --research / --oncampus; the fourth variant
   lives here because NEW GRAD is a career-listing category and nothing else on
   the site draws one. Same shape as the other three, only the pair swapped. */
.tag--newgrad { background: var(--newgrad-tint); color: var(--newgrad); }

.filters { display: flex; gap: 26px; }
.filter {
  font-size: 10px; font-weight: 600; letter-spacing: .5px;
  color: var(--ink-3);
  padding-bottom: 3px;
  border-bottom: 2px solid transparent;
}
.filter[data-cat="internship"] { color: var(--accent); }
.filter[data-cat="research"]   { color: var(--green); }
.filter[data-cat="oncampus"]   { color: var(--amber); }
.filter[data-cat="newgrad"]    { color: var(--newgrad); }
.filter.is-on { border-bottom-color: currentColor; }
.filter:hover { border-bottom-color: color-mix(in srgb, currentColor 40%, transparent); }

/* --- body grid ------------------------------------------------------------- */

/* Default state is a straight 50/50 split — the listings side and the start-ups
   side each get half of the content area. The detail state keeps the frame's
   proportion (464 : 643 -> 0.722fr : 1fr). */
/* --- one place for every duration in this screen --------------------------
   Defined on the page body, not on `.career-body`, because `.career-tools` is
   a *sibling* of `.career-body` and has to read them too. career.js reads them
   back with getComputedStyle, so the reduced-motion block below is all it takes
   to switch the choreography off everywhere at once.

   ONE vocabulary drives both expansions — the listings grid and the start-ups
   directory: the panel that leaves flies out over `--panel-ms`, the content
   that arrives rises `--rise-from` with a `--stagger-ms` step. */
.career-page {
  --panel-ms:       300ms;   /* whichever half slides off / back again        */
  --card-ms:        260ms;   /* a revealed card rising into place             */
  --card-out-ms:    200ms;   /* ... and dropping back out                     */
  --stagger-ms:      24ms;   /* per-card entry delay                          */
  --stagger-out-ms:  18ms;   /* per-card exit delay                           */
  --rise-from:       28px;   /* how far BELOW its resting place a card starts */
  --fall-to:         22px;   /* how far below it drops on the way out         */
  --ease-out: cubic-bezier(.22, .9, .32, 1);
  --ease-in:  cubic-bezier(.45, 0, .85, .35);

  /* NEW GRAD is the fourth listing category, and the only one base.css does not
     ship a token pair for — the other three (accent / green / amber) are global
     because other pages use them, this one is only ever a career listing. A
     desaturated slate keeps it legible next to the three warm hues without
     reading as a fourth "warning" colour.
     Contrast checked against the three pairs it sits beside: #4a6572 on
     #dbe4e8 is 4.79:1, between internship (5.12:1) and research (4.34:1) and
     far clear of on-campus (2.51:1), so both hexes stand as drawn. As a filter
     label on the page ground it is 5.54:1. */
  --newgrad:      #4a6572;
  --newgrad-tint: #dbe4e8;
}

.career-body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 17px;
  align-items: stretch;
  position: relative;
}
.career-body.is-expanded { grid-template-columns: minmax(0, 1fr); }
.career-body.is-expanded .startups:not(.is-flying) { display: none; }

.career-body.is-detail { grid-template-columns: minmax(280px, 0.722fr) minmax(0, 1fr); }
.career-body.is-detail .jobs:not(.is-held) { display: none; }

/* A listing's detail is the mirror image of a start-up's: the pane takes the
   RIGHT column and it is the start-ups panel that steps aside, so the grid the
   student was just reading stays put on the left and they keep their place in
   it. That is why this state holds the plain 50/50 split rather than the
   detail state's 0.722 : 1 — neither side is subordinate here. `:not(.is-flying)`
   for the same reason it is there on `.is-expanded`: the panel has to stay
   painted while it flies out, and only then drop. */
.career-body.is-job-detail { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.career-body.is-job-detail .startups:not(.is-flying) { display: none; }

/* the start-ups panel taking the whole content width */
.career-body.is-startups-wide { grid-template-columns: minmax(0, 1fr); }
/* `.is-held` is the listings grid parked over its own rect while the start-ups
   panel sweeps across it — it has to stay painted until the panel covers it. */
.career-body.is-startups-wide .jobs:not(.is-held) { display: none; }

/* One rule for both states: the card keeps roughly its drawn width and the column
   count follows the space it is given — 2 up compact and 4 up expanded at 1440,
   more as the viewport grows. The 47% keeps two columns even in the narrow
   compact rail, where 234px would not fit twice. */
.jobs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(234px, 47%), 1fr));
  gap: 16px 18px;
}
/* `.is-leaving` keeps a card on screen for its exit animation after the grid
   has already gone back to eight. */
.jobs > .job:nth-child(n + 9):not(.is-leaving) { display: none; }
.is-expanded .jobs > .job:nth-child(n + 9) { display: flex; }
.job.is-filtered { display: none !important; }

/* --- expand / collapse choreography ---------------------------------------
   Transform and opacity only, so nothing here touches layout. */

@keyframes jobRise {
  from { opacity: 0; transform: translateY(var(--rise-from)); }
  to   { opacity: 1; transform: none; }
}
@keyframes jobFall {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(var(--fall-to)); }
}

.jobs > .job.is-rising {
  animation: jobRise var(--card-ms) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger-ms));
  transition: none;
}
.jobs > .job.is-leaving {
  display: flex;
  z-index: 2;
  pointer-events: none;
  animation: jobFall var(--card-out-ms) var(--ease-in) both;
  animation-delay: calc(var(--i, 0) * var(--stagger-out-ms));
  transition: none;
}
.jobs > .job.is-rising:hover,
.jobs > .job.is-leaving:hover { transform: none; }

.job {
  position: relative;
  display: flex;
  min-height: 150px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: var(--sh-3);
  overflow: hidden;
  /* The card lifted on hover long before it did anything when clicked — the
     audit's finding 2. It opens a detail pane now, so the lift is honest and
     the pointer is allowed to say so. `tabindex="0"` on the article makes it a
     keyboard target too, hence the focus ring. */
  cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.job:hover { transform: translateY(-2px); box-shadow: var(--sh-4); }
.job:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Which card the open pane belongs to. Border + elevation only, never the
   transform — a selected card must not sit permanently lifted or hovering it
   would have nothing left to say. */
.job.is-selected { border-color: var(--accent); box-shadow: var(--sh-4); }
.job::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 6px;
  background: var(--accent);
}
.job[data-cat="research"]::before { background: var(--green); }
.job[data-cat="oncampus"]::before { background: var(--amber); }
.job[data-cat="newgrad"]::before  { background: var(--newgrad); }
.job[data-cat="plain"]::before    { background: var(--accent); }

.job__body { flex: 1 1 auto; padding: 16px 20px 0 22px; min-width: 0; }
.job__top { display: flex; align-items: flex-start; gap: 8px; }
.job__actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.job__warn {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--danger);
  color: #fff; font-size: 10px; font-weight: 600;
  display: grid; place-items: center;
}

.job .job__warn { cursor: help; }
.job .job__warn:focus-visible { outline: 2px solid var(--danger); outline-offset: 2px; }

/* hover preview for the ! (js/career.js) */
.warn-tip {
  position: fixed;
  z-index: 60;
  width: max-content;
  max-width: 260px;
  padding: 10px 12px 11px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-top: 3px solid var(--danger);
  border-radius: 10px;
  box-shadow: var(--sh-2);
  pointer-events: none;
  animation: warnTipIn .14s ease-out;
}
.warn-tip::before {
  content: '';
  position: absolute;
  top: -9px; left: calc(var(--arrow-x, 50%) - 6px);
  border: 6px solid transparent;
  border-bottom-color: var(--danger);
}
.warn-tip.is-above { border-top: 1px solid var(--border); border-bottom: 3px solid var(--danger); }
.warn-tip.is-above::before { top: auto; bottom: -15px; border-bottom-color: transparent; border-top-color: var(--danger); }
.warn-tip__head { font-size: 10px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; color: var(--danger); }
.warn-tip__body { margin-top: 4px; font-size: 12.5px; line-height: 1.4; color: var(--ink); }
.warn-tip__more { margin-top: 5px; font-size: 11px; color: var(--ink-3); }
@keyframes warnTipIn { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }

.job__title { font-family: var(--font-serif); font-size: 16px; margin-top: 22px; }
.job__company { font-size: 12px; font-weight: 500; color: var(--ink-2); margin-top: 6px; }
.job__loc {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--ink-2); margin-top: 5px;
}
.job__loc img { width: 6px; height: 6px; }

.bookmark { line-height: 0; opacity: .85; }
.bookmark img { width: 21px; height: 21px; }
.bookmark:hover { opacity: 1; }
.bookmark.is-on img { filter: none; }
.bookmark:not(.is-on) img { filter: grayscale(1) opacity(.55); }

/* --- start-ups panel ------------------------------------------------------- */

.startups {
  /* the panel starts level with the toolbar, 29px above the listings grid */
  margin-top: -29px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 25px 18px 20px 23px;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* --- the listings ⤢: the start-ups panel leaves ----------------------------
   Pin the panel over the rect it occupies right now (`fixed`, so neither
   `.main`'s clip nor a panel's scroll box crops it), then translate it off the
   right edge. Transform and opacity only. */
.startups.is-flying {
  position: fixed;
  z-index: 4;
  margin: 0;
  will-change: transform;
}
/* the transition is a second class so the panel can be *placed* off screen
   without animating, then animated back from there */
.startups.is-moving {
  transition: transform var(--panel-ms) var(--ease-in),
              opacity   var(--panel-ms) linear;
}
.startups.is-moving.is-back { transition-timing-function: var(--ease-out), linear; }

.startups.is-gone { transform: translateX(calc(100% + 80px)); opacity: 0; }

/* --- the directory ↗: the start-ups panel itself sweeps ---------------------
   The other expansion moves the SAME panel, and only that panel. It is pinned
   over the FULL content width it is about to occupy and starts offset to the
   right by exactly the gap between that box and its half-width home, so the
   opening move is a leftward sweep across the listings grid. The grid does not
   go anywhere: it is parked over its own rect (`.jobs.is-held`) one layer down
   and is simply covered, then dropped once the panel is over it. Closing runs
   the identical move in reverse and uncovers it again. Transform only — no
   width animates, so nothing here can move the page. */
.jobs.is-held {
  position: fixed;
  z-index: 3;                 /* under the sweeping panel, which is 4 */
  margin: 0;
}
/* the panel keeps the wide arrangement for the whole sweep, in both directions,
   so its insides never reflow mid-flight */
.startups.is-sweep .startups__wide { display: block; }
.startups.is-sweep .startups__list { flex: 0 0 38%; }
/* the offset pose: full width already, but sitting over its half-width home */
.startups.is-swept { transform: translateX(var(--sweep-x, 0px)); }
/* a sweep settles into a resting place at both ends, so it eases out both ways */
.startups.is-moving.is-sweep { transition-timing-function: var(--ease-out), linear; }

.startups__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; flex: 0 0 auto; }
.startups__title { font-family: var(--font-hand); font-size: 24px; font-weight: 400; color: var(--title-ink); }
.startups__back img { transition: transform .28s var(--ease-out); transform: rotate(-90deg); }
.is-startups-wide .startups__back img { transform: rotate(90deg); }

.startups__body {
  display: flex;
  gap: 20px;
  flex: 1 1 auto;
  min-height: 0; min-width: 0;
}
/* The 5px of padding is headroom for the hover scale: the enlarged card grows
   ~2.5px past its box on every side, and without the padding that overflow
   would grow the scroll box and flash a scrollbar. The matching negative
   margins put the column back exactly where it was drawn. */
.startups__list {
  display: flex; flex-direction: column; gap: 12px;
  padding: 5px 13px 5px 5px;
  margin: -5px -5px -5px -5px;
  flex: 1 1 auto; min-height: 0; min-width: 0;
  overflow-y: auto;
}
.is-startups-wide .startups__list { flex: 0 0 38%; }

.startup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--sh-1);
  padding: 16px;
  cursor: pointer;
  transition: box-shadow var(--card-ms) var(--ease-out),
              border-color var(--card-ms) var(--ease-out),
              transform var(--card-ms) var(--ease-out);
}
.startup__row { display: flex; gap: 12px; align-items: flex-start; }
/* The logo was a bare grey square — a placeholder that shipped. None of these
   companies has a mark, so the square becomes a monogram instead: the same
   serif the card's name is set in, at the size a two-letter lockup wants, with
   the half-pixel of tracking that stops the pair touching. `--placeholder` is
   still the fallback fill for any start-up without a tint below. */
.startup__logo {
  flex: 0 0 48px;
  width: 48px; height: 48px;
  border-radius: 10px;
  background: var(--placeholder);
  display: grid;
  place-items: center;
  font-family: var(--font-serif);
  font-size: 16px;
  letter-spacing: .5px;
  color: var(--ink-2);
  user-select: none;
}
/* One tint each, drawn from the four category pairs this page already uses, so
   the directory reads as four distinct records at a glance without introducing
   a fifth palette. The tint is the fill and the full-strength hue is the ink —
   the same relationship every `.tag` on the page has. */
.startup[data-startup="duolingo"]   .startup__logo { background: var(--green-tint);   color: var(--green); }
.startup[data-startup="astrobotic"] .startup__logo { background: var(--accent-tint);  color: var(--accent); }
.startup[data-startup="aurora"]     .startup__logo { background: var(--amber-tint);   color: var(--amber); }
.startup[data-startup="skild"]      .startup__logo { background: var(--newgrad-tint); color: var(--newgrad); }
.startup__name { font-family: var(--font-serif); font-size: 18.5px; line-height: 1.2; }
.startup__meta { font-size: 13px; color: var(--ink-3); margin-top: 3px; }
.startup__blurb { font-size: 14px; line-height: 1.5; color: var(--ink-2); margin-top: 14px; }

/* The contact row is laid out in every card at every moment — that is what
   keeps the list from jumping as the pointer crosses it. Only its paint is
   toggled, and the card's own growth is a transform, so neither the siblings
   nor the panel ever move. */
.startup__apply { margin-left: 0; }
.startup__apply.is-applied { background: var(--green); }
.startup.is-applied { border-color: var(--green); }

.startup__foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  margin-top: 16px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity var(--card-ms) var(--ease-out),
              transform var(--card-ms) var(--ease-out),
              visibility 0s linear var(--card-ms);
}
.startup__foot > img { width: 32px; height: 32px; }

/* hover — and its keyboard mirror, so the footer is reachable without a mouse
   (tabbing to a card, or to the bookmark inside it, reveals the same row) */
.startup:hover,
.startup:focus-visible,
.startup:focus-within {
  border-radius: 18px;
  border-color: var(--accent-line);
  box-shadow: var(--sh-4);
  transform: scale(1.02);
  z-index: 1;
}
.startup:hover .startup__foot,
.startup:focus-visible .startup__foot,
.startup:focus-within .startup__foot {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity var(--card-ms) var(--ease-out),
              transform var(--card-ms) var(--ease-out),
              visibility 0s;
}
.startup:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* line-md:discord is two layers in the frame (388:115) — the body outline and
   the eyes — and the outline is 28.7x22.67, not square. Drawing it alone in a
   32px box stretched it and lost the eyes. Both layers sit at the frame's own
   insets inside a 32px box, so the outline keeps its aspect. */
.icon-discord {
  position: relative;
  display: block;
  flex: 0 0 32px;
  width: 32px; height: 32px;
  overflow: hidden;
}
.icon-discord .icon-discord__body,
.icon-discord .icon-discord__eyes {
  position: absolute;
  display: block;
  width: auto; height: auto;
}
.icon-discord .icon-discord__body { top: 16.67%; right: 8.22%;  bottom: 18.75%; left: 8.34%; }
.icon-discord .icon-discord__eyes { top: 43.75%; right: 31.25%; bottom: 43.75%; left: 31.25%; }

/* the email contact, alongside the Discord and Instagram marks */
.startup__mail { display: block; line-height: 0; opacity: .9; transition: opacity .15s ease; }
.startup__mail:hover { opacity: 1; }
.startup__mail img { width: 32px; height: 32px; }

/* `is-open` is now nothing but a *selected* marker — the card whose detail is
   showing. The enlarge-and-reveal above belongs to the pointer, not to state,
   so no card is ever stuck in it. */
.startup.is-open {
  border-color: var(--accent);
  box-shadow: var(--sh-3);
}

/* --- start-ups: the swipe-over directory view ------------------------------
   Drawn with the components this screen already has — eyebrow, serif title,
   meta row, blurb, and the category tags — so a directory record and a job
   card read as the same product. */

.startups__wide {
  display: none;
  flex: 1 1 auto; min-width: 0; min-height: 0;
  padding-right: 8px;
  overflow-y: auto;
}
.is-startups-wide .startups__wide { display: block; }

/* The directory arrives exactly the way the newly revealed job cards do —
   `jobRise`, `--card-ms`, `--rise-from`, a `--stagger-ms` step per row — and
   leaves exactly the way they leave. It needs no pin of its own: the panel it
   sits in is the thing that sweeps, so the block rides along with it and keeps
   its geometry for free. career.js squeezes `--stagger-out-ms` so the last row
   is gone by the time the sweep ends and the panel is half width again. */
.startups__wide.is-rising > * {
  animation: jobRise var(--card-ms) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger-ms));
}
.startups__wide.is-leaving {
  display: block;
  z-index: 4;
  overflow: hidden;
  pointer-events: none;
  will-change: transform;
}
.startups__wide.is-leaving > * {
  animation: jobFall var(--card-out-ms) var(--ease-in) both;
  animation-delay: calc(var(--i, 0) * var(--stagger-out-ms));
}

/* The record now opens on an identity row rather than a bare heading: the
   monogram beside the name and meta line, so the card you clicked in the left
   list and the record you land on carry the same mark. */
.startups__wide-id {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 10px;
}
/* the title's own top margin was the gap under the eyebrow; the row owns that
   spacing now, and leaving it would push the text block off the logo's centre */
.startups__wide-id .startups__wide-title { margin-top: 0; }

/* Same monogram as the list card (it keeps `.startup__logo`), scaled to the
   record's heading. The radius grows with it so the corner keeps its share of
   the square: 10/48 on the card, 12/56 here. The tint comes from a `data-tone`
   JS sets when it swaps records, because the wide panel is one node reused for
   all four — there is no `[data-startup]` ancestor to key off. */
.startups__wide-logo {
  flex: 0 0 56px;
  width: 56px; height: 56px;
  border-radius: 12px;
  font-size: 22px;
}
.startups__wide-logo[data-tone="peach"] { background: var(--accent-tint);  color: var(--accent); }
.startups__wide-logo[data-tone="sage"]  { background: var(--green-tint);   color: var(--green); }
.startups__wide-logo[data-tone="amber"] { background: var(--amber-tint);   color: var(--amber); }
.startups__wide-logo[data-tone="slate"] { background: var(--newgrad-tint); color: var(--newgrad); }

.startups__wide-title { font-family: var(--font-serif); font-size: 26px; margin-top: 10px; }
.startups__wide-meta { font-size: 12.5px; color: var(--ink-3); margin-top: 4px; }
.startups__wide-blurb { font-size: 13px; color: var(--ink-2); margin-top: 14px; }
.startups__wide-label { margin-top: 22px; }

.startups__roles { margin-top: 10px; }
.startups__role {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.startups__role:last-child { border-bottom: 0; }
.startups__role-name { font-family: var(--font-serif); font-size: 16px; }
.startups__role-meta { margin-left: auto; font-size: 12px; color: var(--ink-3); }

.startups__wide-foot {
  display: flex; align-items: center; gap: 10px;
  margin-top: 14px;
}
.startups__wide-foot > img { width: 32px; height: 32px; }
.startups__wide-foot .btn { margin-left: auto; }

.startup-detail {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 26px 30px;
  min-height: 0;
  display: none;
}
.is-detail .startup-detail { display: block; }
/* Opening a detail is ONE animation: the pane rises in, on the same token as a
   job card. Nothing swipes — see career.js `openDetail`. */
.startup-detail.is-rising { animation: jobRise var(--card-ms) var(--ease-out) both; }
.startup-detail__title { font-family: var(--font-hand); font-size: 30px; font-weight: 400; margin-bottom: 18px; }
.startup-detail__body p { font-size: 14px; line-height: 1.55; color: var(--ink-2); margin-bottom: 16px; }

.is-detail .startups__title { font-size: 20px; }

/* --- a listing's own detail pane -------------------------------------------
   Same construction as `.startup-detail` — a panel that is simply not there
   until its state class is on `.career-body`, and that arrives on the one
   animation this screen uses for anything appearing (`jobRise`, `--card-ms`).
   The difference is which side it lands on: this pane takes the RIGHT column
   and the start-ups panel is the half that leaves, so the grid the student was
   reading stays where it was. That is also why it carries the start-ups
   panel's -29px: it occupies that panel's slot, and that slot starts level
   with the toolbar row rather than with the listings grid. */
.job-detail {
  display: none;
  margin-top: -29px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 26px 30px;
  min-height: 0;
}
.is-job-detail .job-detail { display: block; }
.job-detail.is-rising { animation: jobRise var(--card-ms) var(--ease-out) both; }

.job-detail__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 16px;
}
/* The same arrow the start-ups panel uses for "put this away", turned the same
   way by the same transition — pointing right, back toward the column the pane
   came out of. Sharing the treatment is the point: one gesture, one glyph. */
.job-detail__close img {
  transform: rotate(90deg);
  transition: transform .28s var(--ease-out);
}

.job-detail__title { font-family: var(--font-serif); font-size: 24px; line-height: 1.25; }
.job-detail__company { font-size: 13px; font-weight: 500; color: var(--ink-2); margin-top: 7px; }
/* `.job__loc` one step up — this is the heading block of a pane, not the last
   line of a 234px card, so the pin and the text can both afford a pixel. */
.job-detail__loc {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--ink-2); margin-top: 6px;
}
.job-detail__loc img { width: 7px; height: 7px; }

/* Term, pay and deadline: a label column and a value column, ruled off top and
   bottom so the facts read as a block of data rather than more prose. The
   labels borrow the eyebrow's 11px instead of the block's 12.5px so the left
   column stays subordinate to the answers beside it. */
.job-detail__facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 9px 18px;
  margin: 20px 0 0;
  padding: 14px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  font-size: 12.5px;
}
.job-detail__facts dt {
  font-size: 11px; font-weight: 600; letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 1px;             /* pulls the smaller label onto the value's baseline */
}
.job-detail__facts dd { margin: 0; color: var(--ink); }

.job-detail__body { margin-top: 18px; }
.job-detail__body p { font-size: 13px; color: var(--ink-2); margin-bottom: 16px; }

.job-detail__label { margin-top: 20px; }

/* Deliberately NOT `.tag`: a tag on this page means a category, and a category
   is a thing you can filter by. These are the skills the posting asks for and
   nothing on the page keys off them, so they are outlined rather than filled —
   present, countable, and clearly not one of the four coloured labels. */
.job-detail__skills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.job-detail__skill {
  display: inline-flex; align-items: center;
  height: 24px; padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-alt);
  font-size: 11.5px; color: var(--ink-2);
}

/* The extra restriction on the four warn cards, spelled out. It reuses the visa
   banner's own soft/line pair so the two notices are recognisably the same
   voice, and it repeats the `!` dot the card carried so the student can see
   which mark they just clicked through.
   `display` is scoped to `:not([hidden])` on purpose — this element is toggled
   with the attribute, and an unqualified `display:flex` here is exactly the
   shape of the bug base.css's `[hidden]` rule exists to stop. */
.job-detail__visa {
  align-items: flex-start;
  gap: 10px;
  margin-top: 20px;
  padding: 12px 14px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: 12px;
}
.job-detail__visa:not([hidden]) { display: flex; }
.job-detail__visa .job__warn { flex: 0 0 16px; margin-top: 1px; }
.job-detail__visa p { font-size: 12.5px; color: var(--ink-2); }

/* wraps, because the pane is half the content width and gets narrower still */
.job-detail__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }

/* --- visa banner ----------------------------------------------------------- */

/* Stays the centred notice it is in the frame, but as a share of the content
   area (866 / 1124) so it scales with the page instead of stranding. */
.visa {
  margin: 16px 0 0;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: 12px;
  padding: 20px 24px;
  display: flex;
  align-items: center;
  gap: 24px;
}
.visa__body { min-width: 0; }

.visa__eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .16em;
  color: color-mix(in srgb, var(--accent) 62%, var(--panel));
}
.visa__title {
  font-family: var(--font-hand);
  font-size: 23px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--accent);
  margin: 7px 0 5px;
}
.visa__status { font-size: 12.5px; color: var(--ink-2); }

/* Not `.btn`: this one is the strip's single action and reads at 13px beside a
   23px heading, where .btn's 44px/18px would out-shout the heading itself. */
.visa__cta {
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  height: 42px;
  padding: 0 20px;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font-size: 13.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: filter .15s ease;
}
.visa__cta:hover { filter: brightness(1.08); }

@media (max-width: 780px) {
  .visa { flex-direction: column; align-items: flex-start; gap: 16px; }
  .visa__cta { margin-left: 0; }
}

/* --- message a founder ------------------------------------------------------
   The composer that replaces five dead "Message →" buttons and four dead
   mailto: links. It is base.css's `.modal` with a width: 520px is about 62
   characters at the textarea's 13px, which is the width a message this length
   wants to be read at, and `width:100%` lets it give that up on a phone rather
   than overflow the backdrop's 24px padding. */
.modal.msg {
  width: 100%;
  max-width: 520px;
  padding: 28px 30px 24px;
}
.msg__title { font-family: var(--font-hand); font-size: 28px; font-weight: 400; margin-top: 6px; }
.msg__meta { font-size: 12.5px; color: var(--ink-3); margin-top: 4px; }

/* a real <label>, so it carries the eyebrow's sizing rather than its class —
   and it has to be block or the textarea would sit on the same line as it */
.msg__label {
  display: block;
  margin-top: 18px;
  font-size: 11px; font-weight: 600; letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* The draft is the point of the modal, so the field is sized like something you
   are expected to write in: panel fill against the modal's lighter `--panel-alt`
   so the box reads as sunken, and 1.6 line-height because the prefilled template
   is six short paragraphs. Vertical resize only — horizontal would break the
   modal's width. */
.msg__body {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  font-size: 13px; line-height: 1.6;
  color: var(--ink);
  resize: vertical;
  transition: border-color .15s ease;
}
.msg__body:focus-visible {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.msg__note { font-size: 12px; color: var(--ink-3); margin-top: 10px; }

.msg__actions {
  display: flex; align-items: center; gap: 10px;
  justify-content: flex-end;
  flex-wrap: wrap;
  margin-top: 18px;
}
/* Pushed to the far left of the action row by its own auto margin. It carries
   NO `display` — it is toggled with [hidden], and an author display here is the
   exact bug base.css's global `[hidden]` rule was added to end. */
.msg__done { font-size: 12.5px; color: var(--green); margin-right: auto; }

/* --- full-height page: one screen, no document scroll ----------------------
   On a normal desktop viewport the screen is a flex column that fills the
   viewport exactly: the profile row and the toolbar keep their intrinsic
   height, `.career-body` takes every pixel that is left, and the visa banner
   is the last band, sitting on the bottom edge. Overflow is absorbed inside
   the two panels (`.jobs` and `.startups__list`), never by the page.
   Below 1101px wide or 700px tall the page falls back to normal document
   flow and is allowed to scroll. */

@media (min-width: 1101px) and (min-height: 700px) {

  .career-page .app { height: 100vh; min-height: 0; }

  /* Height and flow only — the padding stays the canonical gutter from
     base.css so this page frames its content like every other one. */
  .career-page .main {
    height: 100vh;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .career-page .career-top,
  .career-page .career-tools { flex: 0 0 auto; }

  .career-page .career-body { flex: 1 1 auto; min-height: 0; }

  /* Build B's strip spans the content column rather than sitting centred at
     77% — it reads as a status bar for the listings above it, not as a card. */
  .career-page .visa { flex: 0 0 auto; width: 100%; }

  /* Two columns compact, four expanded — fixed counts so the card proportion
     stays sane however wide the screen gets. Rows share the height the body
     row hands down, from a floor that keeps the card legible up to a cap that
     stops a tall viewport stretching a card out of shape. */
  .jobs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: minmax(140px, 240px);
    align-content: start;
    min-height: 0;
    overflow: hidden auto;
  }
  .career-body.is-expanded .jobs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* An open listing takes the right-hand column, so the expanded grid has to
     drop back from four columns to two while it is there — four across half the
     content width is a row of slivers. Opening a detail therefore never has to
     collapse the grid, which is what lets a saved item deep in the list (cards
     9-16 only exist expanded) be opened straight from the rail. */
  .career-body.is-expanded.is-job-detail .jobs { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* the row, not the frame, sets the card height here */
  .job { min-height: 0; }

  .startup-detail { overflow: hidden auto; }
  /* same contract as the other panes on this screen: the page never scrolls, so
     a listing longer than the column scrolls inside its own box */
  .job-detail { overflow: hidden auto; }
}

/* --- narrow: the two-column rows stack ------------------------------------- */

/* --- reduced motion --------------------------------------------------------
   Zeroing the durations is enough: career.js reads them back for its own
   timers, so the state still switches, just without the choreography. */

@media (prefers-reduced-motion: reduce) {
  .saved-scrim { animation: none; backdrop-filter: none; }
  .career-page {
    --panel-ms: 0ms;
    --card-ms: 0ms;
    --card-out-ms: 0ms;
    --stagger-ms: 0ms;
    --stagger-out-ms: 0ms;
    --rise-from: 0px;
    --fall-to: 0px;
  }
  .startups__back img,
  .job-detail__close img,
  .saved-rail__title,
  .career-body,
  .career-page .visa,
  .job { transition: none; }
  .warn-tip { animation: none; }

  /* the detail pane rises on `jobRise`, which the zeroed tokens above already
     flatten — this only stops the animation being *scheduled* at all, so a pane
     that is display:none until its state class lands never flickers on arrival */
  .job-detail.is-rising { animation: none; }

  /* the start-up cards still reveal their contact row — just without the
     growth, and with no transition to carry it */
  .startup,
  .startup__foot { transition: none; }
  .startup:hover,
  .startup:focus-visible,
  .startup:focus-within { transform: none; }
}

/* --- narrow: the two-column rows stack ------------------------------------- */

@media (max-width: 1100px) {
  .career-top { flex-wrap: wrap; }
  .saved-rail { flex: 1 1 100%; }

  .career-body,
  .career-body.is-detail,
  .career-body.is-job-detail { grid-template-columns: minmax(0, 1fr); }

  /* no left half to swipe over once everything is one column */
  .startups__body { flex-direction: column; }
  .is-startups-wide .startups__list { flex: 1 1 auto; }

  /* nothing to sit level with once the panel is below the grid — and the job
     pane borrows that offset from the panel whose slot it takes, so it drops
     the offset in the same breath */
  .startups { margin-top: 0; }
  .job-detail { margin-top: 0; }

  .visa { max-width: 100%; }
}


/* --- phones ------------------------------------------------------------------ */
@media (max-width: 900px) {
  .career-top { gap: 14px; }
  .profile-card { height: auto; gap: 14px; padding: 16px; flex-wrap: wrap; border-radius: 16px; }
  .profile-card__avatar.avatar { width: 64px; height: 64px; flex: 0 0 64px; font-size: 24px; }
  .profile-card > div:not(.profile-card__avatar) { flex: 1 1 0; min-width: 0; }
  .profile-card__name { font-size: 30px; }
  .profile-card__meta { font-size: 13px; }
  .profile-card__cta { margin-left: 0; width: 100%; justify-content: center; }

  .saved-rail-slot { flex: 1 1 100%; min-width: 0; height: 132px; }
  .saved-rail { height: 132px; border-radius: 16px; }
  /* room to read the whole title once the list is open on a narrow screen */
  .saved-rail.is-open .saved-rail__title { white-space: normal; margin-right: 0; }

  .career-tools { gap: 14px; margin: 18px 0 10px; }
  .filters { gap: 14px; overflow-x: auto; scrollbar-width: none; flex-wrap: nowrap; }
  .filters::-webkit-scrollbar { display: none; }
  .filter { white-space: nowrap; font-size: 11px; padding-block: 6px 3px; }

  .jobs { grid-template-columns: minmax(0, 1fr); }
  .startups, .startup-detail, .job-detail { padding: 18px 16px; border-radius: 16px; }

  .visa { padding: 16px; }
  .visa__cta { width: 100%; justify-content: center; }

  .modal.msg { padding: 22px 18px 18px; }
  .warn-tip { max-width: calc(100vw - 32px); }
}
