:root {
  /* Near-neutral black page. The lab's own bar colour (#05282f) is the
     accent — it is a dark teal, so it works as a fill with white on top
     rather than as a highlight: too dark to read against the page. */
  --paper: #0c0d0d;      /* page */
  --card: #131515;
  --card-2: #1a1d1d;     /* raised: inputs, hovers */
  --line: #232626;
  --line-2: #313636;

  --ink: #ffffff;
  --ink-2: #b8bcbc;
  --muted: #7c8382;

  /* Accent — sampled from the lab's menu bar. */
  --brand: #05282f;
  --brand-2: #0a3d47;    /* lifted, for hover and borders */
  --brand-3: #10525f;    /* lifted further, where the fill must be seen */
  --on-brand: #ffffff;

  /* Legible on near-black: the brand hue raised until it reads as text.
     Used for links and small marks, where #05282f would disappear. */
  --brand-lit: #5fbccb;

  /* Aliases so existing rules keep working. */
  --amber: var(--brand-3);
  --amber-ink: var(--brand-lit);

  --green: #4a9e86;
  --rust: #c0764a;
  --blue: var(--brand-lit);
  --r: 5px;

  /* One gutter, used everywhere. The page has no centred container:
     grids and images run to the edge, text is held to a readable
     measure inside them. */
  --gutter: 40px;
  --measure: 680px;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--paper); color: var(--ink);
  font-size: 15px;
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
  "Apple SD Gothic Neo", "Malgun Gothic", sans-serif; line-height: 1.6; -webkit-font-smoothing: antialiased; }
a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

.site-header { display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding: 0 var(--gutter); height: 58px; background: var(--paper);
  border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 10; }

/* Brand left, everything else right. The nav's slots are a fixed size, so
   the nav is a fixed width whatever language it is in — it does not need
   protecting from the brand, it simply cannot change. */
.brand { display: flex; align-items: baseline; gap: 9px; min-width: 0;
  font-weight: 800; font-size: 18px; letter-spacing: 2px; color: var(--ink); }
.brand small { font-weight: 400; font-size: 11px; letter-spacing: .5px;
  color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Nav and actions ride together at the right edge. */
.header-end { display: flex; align-items: center; gap: 20px; margin-left: auto;
  height: 100%; }
.acts { display: flex; align-items: center; gap: 16px; }

/* Identical slots, centred: a link's own width stops mattering, so no label
   in any language or font can shift the row. This is the whole trick — it
   beats measuring text, because it never asks how wide the text is. */
nav.main { display: grid; grid-auto-flow: column; grid-auto-columns: 96px;
  align-items: center; flex: 0 0 auto; height: 100%; }
nav.main > a { display: flex; align-items: center; justify-content: center;
  text-align: center; height: 100%; position: relative;
  font-size: 13px; color: var(--ink-2); white-space: nowrap; }
nav.main > a:hover { color: var(--ink); text-decoration: none; }
/* An underline that grows from the centre, so hover doesn't nudge anything. */
nav.main > a::after { content: ""; position: absolute; left: 50%; bottom: 14px;
  transform: translateX(-50%); width: 0; height: 1.5px; background: var(--brand-lit);
  transition: width .25s; }
nav.main > a:hover::after { width: 60%; }

/* The auth link swaps between "Log in" and "Log out" — and their Korean
   twins — so it reserves a slot too. */
.act-link { font-size: 13px; color: var(--ink-2); min-width: 62px; text-align: center; }
.act-link:hover { color: var(--ink); text-decoration: none; }


/* Each link holds both of its labels: the visible one, and the other
   language's stacked invisibly underneath. The link is therefore as wide as
   the WIDER of the two — measured by the browser in the font it actually
   loaded, so switching language cannot change any link's width, and nothing
   downstream shifts. No px is reserved by hand. */
.nav-item { position: relative; display: inline-grid; place-items: center;
  white-space: nowrap; }
.nav-item > span { grid-area: 1 / 1; }
.nav-item::after {
  content: attr(data-alt); grid-area: 1 / 1;
  visibility: hidden; pointer-events: none; height: 0;
  font-weight: 700;   /* the widest weight either label is ever drawn in */
}
.site-header nav a { color: var(--ink-2); font-size: 13px; }
.site-header nav a:hover { color: var(--ink); text-decoration: none; }
.badge { font-size: 12px; background: var(--brand); color: var(--ink);
  padding: 4px 11px; border-radius: 999px; border: 1px solid var(--brand-2);
  white-space: nowrap; }

/* A name cannot be boxed — "윤성민" is 3 characters, "Sungmin Yoon" is 12 —
   so the SLOT is boxed instead, and the badge sizes itself freely inside.
   The row only ever sees the slot, which is a fixed width in every language.
   Right-aligned within it, so the badge sits against the link beside it and
   the slack falls away from the row. */
/* A real width, not just a flex-basis. A basis is a starting size that the
   layout may still resolve against content — and `max-width: 100%` on the
   badge has no definite width to resolve against, so the badge takes its
   natural size and stretches the slot. `width` is definite; the slot is
   then 130px whatever the name, and the badge clips inside it. */
.who-slot { width: 130px; min-width: 130px; max-width: 130px; flex: 0 0 130px;
  display: flex; justify-content: center; align-items: center; overflow: hidden; }
.who-slot .badge { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }

/* No centred container: the page runs to the edges, held off them by one
   gutter. Text inside is constrained separately (see --measure) — full-width
   prose is unreadable on a wide monitor, which is why MIT runs images edge
   to edge but never body copy. */
.container { max-width: none; margin: 0; padding: 30px var(--gutter) 88px; }
@media (max-width: 700px) { :root { --gutter: 20px; } }
.eyebrow { font-size: 10px; letter-spacing: 2.2px; text-transform: uppercase;
  color: var(--brand-lit); font-weight: 700; margin-bottom: 9px; }
h1 { font-size: 23px; letter-spacing: -.3px; margin: 0 0 6px; font-weight: 700; }
h2 { font-size: 11px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--muted); margin: 34px 0 14px; font-weight: 700; }
.muted { color: var(--muted); font-size: 13px; }
.toolbar { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 32px; }

/* ── Home: the first screen ────────────────────────────────
   A tagline and three paragraphs at the same rhythm as the footer columns,
   then the work strip running off the right edge. The lede is a text block,
   not a headline: the lab says something at length, then shows the work. */
/* Four columns that use the width. The lede does not share the footer's
   grid — the footer is a sitemap in small type, this is the lab talking,
   and it earns wider measures and bigger text. Columns stretch, gaps stay
   fixed: the block should reach across the screen, not huddle. */
/* Four explicit columns: tagline, then three paragraphs. This band is always
   1 + 3 — auto-fit was wrong here, since it packs by minimum width and then
   grows them, which strands the fourth column on its own row at widths where
   three happen to fit. The columns shrink together and only fold when they
   genuinely cannot hold a readable line. */
.lede { display: grid; gap: 30px 34px; padding: 26px 0 46px;
  grid-template-columns: minmax(180px, 0.8fr) repeat(3, minmax(240px, 1fr));
  max-width: 1560px; }
/* Below this the three paragraphs can no longer hold a readable measure
   side by side, so stack them. One breakpoint, at the point of real failure
   rather than a guessed screen size. */
@media (max-width: 940px) {
  .lede { grid-template-columns: minmax(0, 520px); gap: 24px; }
}

.lede-mark { font-size: 16px; font-weight: 800; letter-spacing: 3px; color: var(--ink);
  margin-bottom: 14px; }
.lede-tag p { margin: 0; font-size: 16.5px; line-height: 1.5; color: var(--ink);
  font-weight: 500; letter-spacing: -.2px; max-width: 20ch; }

.stmt-col h2 { font-size: 11px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--brand-lit); margin: 0 0 10px; font-weight: 700; }
.stmt-col p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--ink-2); }

.strip-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; padding-top: 22px; border-top: 1px solid var(--line); margin-bottom: 16px; }
.strip-head h2 { margin: 0; }
.strip-links { display: flex; gap: 18px; }
.strip-links a { font-size: 12px; color: var(--muted); }
.strip-links a:hover { color: var(--amber-ink); text-decoration: none; }

/* Full-bleed: break out of the container, run to the right edge and past it. */
/* The strip breaks the gutter on the right and runs off the screen. */
.strip { margin-right: calc(var(--gutter) * -1); }
.strip-rail {
  display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x proximity;
  padding: 2px var(--gutter) 20px 0;
  scrollbar-width: thin; scrollbar-color: var(--line-2) transparent;
}
.strip-rail::-webkit-scrollbar { height: 7px; }
.strip-rail::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 4px; }
.strip-rail::-webkit-scrollbar-track { background: transparent; }
.strip-rail .card { flex: 0 0 265px; scroll-snap-align: start; }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 18px; }
.card { position: relative; background: transparent; border: none; border-radius: var(--r); overflow: hidden; }
.card-link { display: block; color: inherit; text-decoration: none; }
.card-link:hover { text-decoration: none; }
.card .thumb {
  display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  background: var(--card-2); border-radius: var(--r); border: 1px solid var(--line);
  transition: transform .25s ease, border-color .2s;
}
.card-link:hover .thumb { transform: scale(1.02); border-color: var(--line-2); }
.card .thumb.placeholder {
  display: flex; align-items: center; justify-content: center;
  color: #333939; font-size: 30px; font-weight: 800; letter-spacing: 3px;
}
.card .body { padding: 10px 2px 0; }
.card h3 { margin: 0; font-size: 13.5px; font-weight: 700; letter-spacing: -.1px; color: var(--ink); line-height: 1.4; }
.card h3 .ext { color: var(--muted); font-size: 13px; font-weight: 400; }
.card .year { font-size: 11px; color: var(--muted); margin-top: 3px; letter-spacing: .3px; }
.card-edit {
  position: absolute; top: 10px; right: 10px; width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8,9,9,.82); border: 1px solid var(--line-2); border-radius: 6px;
  color: var(--ink-2); font-size: 14px; opacity: 0; transition: opacity .15s;
}
.card:hover .card-edit { opacity: 1; }
.card-edit:hover { color: var(--amber); border-color: var(--amber); text-decoration: none; }

.status { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; font-weight: 800;
  display: inline-flex; align-items: center; gap: 6px; }
.status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.status.ongoing { color: var(--rust); }
.status.live { color: var(--green); }
.status.completed { color: var(--muted); }

.btn { display: inline-block; background: var(--card-2); color: var(--ink); border: 1px solid var(--line-2);
  padding: 10px 18px; border-radius: var(--r); font: inherit; font-size: 14px; cursor: pointer; }
.btn:hover { background: #1f2323; text-decoration: none; }
.btn.primary { background: var(--brand-3); color: var(--on-brand);
  border-color: var(--brand-3); font-weight: 600; }
.btn.primary:hover { background: var(--brand-2); border-color: var(--brand-lit); }
.btn.small { padding: 6px 12px; font-size: 13px; }
.launch { display: inline-block; background: var(--brand-3); color: var(--on-brand); padding: 10px 18px;
  border-radius: var(--r); font-weight: 700; font-size: 14px; }
.launch:hover { background: var(--brand-2); text-decoration: none; }
.launch.small { padding: 6px 12px; font-size: 13px; }

table.list { width: 100%; border-collapse: collapse; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
table.list th, table.list td { text-align: left; padding: 12px 15px; border-bottom: 1px solid var(--line); font-size: 14px; }
table.list th { color: var(--muted); font-weight: 700; font-size: 11px; text-transform: uppercase;
  letter-spacing: .5px; background: var(--card-2); }
table.list tr:last-child td { border-bottom: none; }




.empty { border: 1px dashed var(--line-2); border-radius: var(--r); padding: 52px; text-align: center;
  color: var(--muted); background: var(--card); }
.backlink { margin-top: 40px; display: inline-block; font-size: 14px; }

/* ── Forms ─────────────────────────────────────────────── */
form.entry { display: grid; gap: 26px; max-width: var(--measure); }
.field { display: grid; gap: 7px; }
.field label { font-size: 12px; font-weight: 700; color: var(--ink-2); letter-spacing: .4px; }
.field .req { color: #e8896f; margin-left: 2px; }
.field input, .field select, .field textarea {
  padding: 11px 13px; border: 1px solid var(--line-2); border-radius: var(--r);
  font: inherit; font-size: 15px; width: 100%; background: var(--card-2); color: var(--ink);
  transition: border-color .12s, background .12s, box-shadow .12s;
}
.field input::placeholder, .field textarea::placeholder { color: #616868; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: #3a4040; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--brand-lit); background: #1c2020;
  box-shadow: 0 0 0 3px rgba(95, 188, 203, .12);
}
.field textarea { min-height: 120px; resize: vertical; }
.field .hint { font-size: 12px; color: var(--muted); line-height: 1.5; }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 640px) { .row2 { grid-template-columns: 1fr; } }

/* File input (browsers style these badly by default) */
.field input[type="file"] { padding: 9px; font-size: 13px; cursor: pointer; color: var(--ink-2); }
.field input[type="file"]::file-selector-button {
  background: var(--card); color: var(--ink); border: 1px solid var(--line-2);
  border-radius: 4px; padding: 6px 12px; margin-right: 12px; font: inherit; font-size: 13px; cursor: pointer;
}
.field input[type="file"]::file-selector-button:hover { background: #1f2323; border-color: var(--brand-lit); }
.thumb-preview { border-radius: 6px; border: 1px solid var(--line); max-width: 180px; display: block; margin-bottom: 8px; }

/* Progressive disclosure fold */
details.more { border-top: 1px solid var(--line); padding-top: 22px; }
details.more > summary {
  cursor: pointer; font-size: 13px; font-weight: 700; color: var(--ink-2);
  list-style: none; display: flex; align-items: center; gap: 8px; letter-spacing: .3px;
}
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::before { content: "▸"; color: var(--muted); font-size: 11px; }
details.more[open] > summary::before { content: "▾"; }
details.more > summary:hover { color: var(--ink); }
details.more .inner { display: grid; gap: 26px; margin-top: 26px; }

/* People tagger */
.people { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tag {
  display: inline-flex; align-items: center; gap: 7px; background: rgba(95, 188, 203, .13);
  border: 1px solid rgba(95, 188, 203, .3); border-radius: 999px;
  padding: 5px 7px 5px 13px; font-size: 13px; color: var(--ink);
}
.tag.raw { background: var(--card-2); border-color: var(--line-2); font-style: italic; color: var(--ink-2); }
.tag button {
  background: none; border: none; cursor: pointer; color: var(--muted);
  font-size: 16px; line-height: 1; padding: 0 3px; border-radius: 3px;
}
.tag button:hover { color: #e88b80; }

/* Form actions */
.form-actions { display: flex; gap: 10px; padding-top: 4px; }

/* ── Destination picker (upload page OR external link) ─── */
.dest { border: 1px solid var(--line); border-radius: var(--r); padding: 20px; background: rgba(23,29,37,.5); display: grid; gap: 14px; }
.dest-head { display: grid; gap: 5px; }
.dest-head label { font-size: 12px; font-weight: 700; color: var(--ink-2); letter-spacing: .4px; }
.dest-opt {
  display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start;
  padding: 16px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--card); cursor: pointer; transition: border-color .15s, background .15s;
}
.dest-opt:hover { border-color: var(--line-2); }
.dest-opt:has(input[type="radio"]:checked) { border-color: var(--brand-lit); background: var(--brand); }
.dest-opt > input[type="radio"] { margin-top: 3px; accent-color: var(--amber); width: 16px; height: 16px; }
.dest-opt > span { display: grid; gap: 8px; }
.dest-opt b { font-size: 14px; color: var(--ink); font-weight: 700; }
.dest-opt .hint { font-size: 12px; color: var(--muted); line-height: 1.5; }
.dest-opt input[type="file"], .dest-opt input[name="external_url"] {
  padding: 9px 11px; border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--card-2); color: var(--ink); font: inherit; font-size: 14px; width: 100%;
}
.dest-opt input[name="external_url"]:focus, .dest-opt input[type="file"]:focus {
  outline: none; border-color: var(--amber); box-shadow: 0 0 0 3px rgba(95, 188, 203, .12);
}
.dest-opt input[type="file"]::file-selector-button {
  background: var(--paper); color: var(--ink); border: 1px solid var(--line-2);
  border-radius: 4px; padding: 5px 11px; margin-right: 10px; font: inherit; font-size: 13px; cursor: pointer;
}
.tpl-link {
  display: inline-block; font-size: 13px; color: var(--amber-ink);
  border: 1px dashed rgba(95, 188, 203, .4); border-radius: var(--r);
  padding: 8px 13px; justify-self: start;
}
.tpl-link:hover { background: rgba(95, 188, 203, .1); text-decoration: none; }

.btn.danger { color: #e88b80; border-color: #5a3230; }
.btn.danger:hover { background: #3a2220; }

/* ── Language switch ───────────────────────────────────── */
/* A control, not a link: a bordered pill, monospaced so EN and KR are the
   same width by construction. Both labels are two characters, so toggling
   changes nothing about the layout. */
.lang { display: inline-flex; align-items: center;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 10.5px; letter-spacing: .1em;
  border: 1px solid var(--line-2); border-radius: 100px; overflow: hidden; }
.lang a { color: var(--muted); padding: 5px 9px; line-height: 1.4; }
.lang a:hover { color: var(--ink); text-decoration: none; }
.lang a.on { color: var(--on-brand); background: var(--brand-3); }

/* The footer carries the same control, a touch smaller. */
.foot-base .lang { font-size: 9.5px; }
.foot-base .lang a { padding: 4px 8px; }

/* ── Narrow single-column pages (login, claim) ─────────── */
.narrow { max-width: 420px; margin: 20px auto; }
.stack { display: grid; gap: 12px; margin-top: 24px; }
.small-note { margin-top: 28px; font-size: 13px; }
.form-error {
  border: 1px solid #5a3230; background: rgba(232,139,128,.08);
  color: #e88b80; border-radius: var(--r); padding: 12px 14px; font-size: 14px; margin-top: 16px;
}

/* ── People grid ───────────────────────────────────────── */
.section-head { font-size: 13px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--muted); margin: 56px 0 20px; padding-top: 28px; border-top: 1px solid var(--line); }
.people-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 26px 20px; }
.person { display: flex; flex-direction: column; gap: 12px; }
.person .face { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--r);
  background: var(--card-2); border: 1px solid var(--line); display: block; }
.person .face.placeholder { display: flex; align-items: center; justify-content: center;
  font-size: 40px; font-weight: 800; color: #333939; }
.person-body { display: flex; flex-direction: column; gap: 3px; }
.person h3 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.1px; }
.name-alt { font-size: 13px; color: var(--ink-2); }
.person-role { font-size: 12px; color: var(--brand-lit); margin-top: 4px; letter-spacing: .2px; }
.interests { margin: 8px 0 0; padding-left: 15px; }
.interests li { font-size: 12px; color: var(--muted); line-height: 1.5; }
.person-mail { font-size: 12px; color: var(--muted); margin-top: 6px; word-break: break-all; }
.person-mail:hover { color: var(--blue); }

/* One discreet roster edit link */
.edit-roster { font-size: 13px; color: var(--muted); border: 1px solid var(--line);
  border-radius: var(--r); padding: 7px 13px; white-space: nowrap; }
.edit-roster:hover { color: var(--amber-ink); border-color: var(--amber); text-decoration: none; }

/* ── Roster bulk editor ────────────────────────────────── */
.notice { font-size: 13px; color: var(--ink-2); background: rgba(95, 188, 203, .07);
  border: 1px solid rgba(95, 188, 203, .25); border-radius: var(--r); padding: 12px 14px; margin-bottom: 20px; }
.roster-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r); }
table.roster { border-collapse: collapse; width: 100%; min-width: 1500px; background: var(--card); }
table.roster th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .6px;
  color: var(--muted); font-weight: 700; padding: 10px 8px; background: var(--card-2);
  border-bottom: 1px solid var(--line); white-space: nowrap; position: sticky; top: 0; z-index: 2; }
table.roster td { padding: 8px 6px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.roster tr:last-child td { border-bottom: none; }
table.roster input, table.roster select {
  width: 100%; background: transparent; border: 1px solid transparent;
  border-radius: 4px; padding: 7px 8px; color: var(--ink); font: inherit; font-size: 13px;
}
/* Columns sized to what they actually hold, rather than one min-width for all. */
table.roster th, table.roster td { min-width: 0; }
.col-name-ko  { width: 110px; }
.col-name-en  { width: 170px; }
.col-role     { width: 190px; }
.col-status   { width: 110px; }
.col-email    { width: 210px; }
.col-dept     { width: 330px; }
.col-sid      { width: 120px; }
.col-rno      { width: 140px; }
.col-mobile   { width: 130px; }
.col-birth    { width: 120px; }
table.roster input:hover, table.roster select:hover { border-color: var(--line-2); background: var(--card-2); }
table.roster input:focus, table.roster select:focus {
  outline: none; border-color: var(--brand-lit); background: #1c2020; box-shadow: 0 0 0 2px rgba(95, 188, 203, .12);
}
table.roster th.private-col { color: var(--amber-ink); }
table.roster td.private-col { background: rgba(95, 188, 203, .03); }
.col-photo { width: 68px; }
.col-del { width: 44px; text-align: center; }

.photo-cell { position: relative; display: block; width: 54px; height: 54px; cursor: pointer; }
.photo-cell img, .photo-cell .face-mini {
  width: 54px; height: 54px; border-radius: 6px; object-fit: cover;
  border: 1px dashed var(--line-2); background: var(--card-2); display: flex;
  align-items: center; justify-content: center; color: var(--muted);
}
.photo-cell img { border-style: solid; }
.photo-cell .face-mini svg { width: 20px; height: 20px; }
.photo-cell .photo-hover svg { width: 18px; height: 18px; }
.photo-hover { position: absolute; inset: 0; border-radius: 6px; display: flex;
  align-items: center; justify-content: center; background: rgba(8,9,9,.72);
  color: var(--amber-ink); font-size: 13px; opacity: 0; transition: opacity .12s; }
.photo-cell:hover .photo-hover { opacity: 1; }
.photo-cell.changed img { border-color: var(--green); }

.del-box input { width: 15px; height: 15px; accent-color: #d1665c; cursor: pointer; min-width: 0; }
tr.to-delete { opacity: .38; }
tr.to-delete input, tr.to-delete select { text-decoration: line-through; }
tr.new-row td { background: rgba(74, 158, 134, .04); }
tr.new-row input::placeholder { color: var(--green); opacity: .7; }

/* ── Homepage team list (tiered text; faces live on /members) ── */
.team-head { margin-top: 54px; padding-top: 28px; border-top: 1px solid var(--line); align-items: center; }
.team-more { font-size: 13px; color: var(--muted); white-space: nowrap; }
.team-more:hover { color: var(--amber-ink); text-decoration: none; }
.team { display: grid; gap: 30px; }
.tier-label {
  font-size: 10px; letter-spacing: 1.8px; text-transform: uppercase;
  color: var(--muted); font-weight: 700; margin-bottom: 10px;
}
.lead-tier { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.team-name { color: var(--ink); font-size: 15px; }
.lead-name { font-size: 16px; font-weight: 700; letter-spacing: -.2px; }
.lead-name:hover { color: var(--amber-ink); text-decoration: none; }
.team-role { font-size: 13px; color: var(--muted); font-style: italic; }
.team-alt { font-size: 13px; color: var(--line-2); }
.team-list { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 3px 20px; }
.team-list li { display: flex; align-items: baseline; gap: 8px; padding: 3px 0; }
.team-list .team-name { font-size: 13px; }
.team-list .team-role { font-size: 12px; }
.team-list.quiet .team-name { color: var(--ink-2); }
.team-list.quiet .team-role { color: var(--line-2); }
/* A name that points somewhere: subtle until hovered (MIT-style). */
.team-name.linked, .person h3 .linked { color: inherit; }
.team-name.linked:hover, .person h3 .linked:hover { color: var(--amber-ink); text-decoration: none; }
.team-name.linked::after, .person h3 .linked::after {
  content: "↗"; font-size: .72em; color: var(--line-2); margin-left: 4px;
  vertical-align: super; transition: color .12s;
}
.team-name.linked:hover::after, .person h3 .linked:hover::after { color: var(--amber-ink); }
a.lead-name:hover { color: var(--amber-ink); text-decoration: none; }

/* ── Roster editor: wider, roomier ─────────────────────── */
/* The roster is the one page that earns more width than the container. */
/* Was a hack to escape the centred container; the page is full width now. */
.roster-wide { max-width: none; }
table.roster { min-width: 1180px; }

.col-links { width: 62px; text-align: center; }
.links-btn {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  color: var(--ink-2); font: inherit; font-size: 12px; padding: 5px 9px; cursor: pointer;
  white-space: nowrap;
}
.links-btn:hover { border-color: var(--amber); color: var(--amber-ink); }
.links-count { font-weight: 700; }

/* ── Links popup ───────────────────────────────────────── */
.modal-back {
  position: fixed; inset: 0; background: rgba(5,6,6,.76); z-index: 50;
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.modal-back[hidden] { display: none; }
.modal {
  background: var(--card); border: 1px solid var(--line-2); border-radius: 10px;
  padding: 24px; width: 100%; max-width: 620px; max-height: 82vh; overflow-y: auto;
  box-shadow: 0 24px 70px rgba(0,0,0,.55);
}
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.modal-head h3 { margin: 0; font-size: 18px; letter-spacing: -.2px; }
.modal-x { background: none; border: none; color: var(--muted); font-size: 24px;
  line-height: 1; cursor: pointer; padding: 0 4px; }
.modal-x:hover { color: var(--ink); }
.modal-note { font-size: 12.5px; color: var(--muted); margin: 8px 0 18px; line-height: 1.55; }
.modal-foot { display: flex; justify-content: flex-end; margin-top: 20px;
  padding-top: 16px; border-top: 1px solid var(--line); }

.link-row { display: grid; grid-template-columns: 150px auto 1fr auto auto; gap: 8px;
  align-items: center; margin-bottom: 9px; }
.link-row .link-other[hidden] { display: none; }
.link-row select, .link-row input.link-url {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  padding: 8px 10px; color: var(--ink); font: inherit; font-size: 13px; width: 100%;
}
.link-row select:focus, .link-row input.link-url:focus {
  outline: none; border-color: var(--amber); box-shadow: 0 0 0 2px rgba(95, 188, 203, .12);
}
.link-main { display: flex; align-items: center; gap: 5px; font-size: 11.5px;
  color: var(--muted); cursor: pointer; white-space: nowrap; padding: 0 4px; }
.link-main input { accent-color: var(--amber); cursor: pointer; }
.link-main:hover { color: var(--amber-ink); }

/* ── Cell buttons (interests / links popups) ───────────── */
.col-btn { width: 66px; text-align: center; }
.cell-btn {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  color: var(--ink-2); font: inherit; font-size: 12px; padding: 6px 12px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px; min-width: 46px; justify-content: center;
}
.cell-btn:hover { border-color: var(--amber); color: var(--amber-ink); }
.cell-btn::before { content: "✎"; font-size: 11px; opacity: .75; }
.links-btn::before { content: "🔗"; }
.cell-btn-n { font-weight: 700; }

/* ── Popups ────────────────────────────────────────────── */
.modal.wide { max-width: 820px; }
.two-lang { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
@media (max-width: 720px) { .two-lang { grid-template-columns: 1fr; } }
.lang-head { font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--brand-lit); font-weight: 700; margin-bottom: 10px; }
.bullet-rows { margin-bottom: 10px; }
.bullet-row { display: grid; grid-template-columns: 12px 1fr auto; gap: 8px;
  align-items: center; margin-bottom: 7px; }
.bullet { color: var(--muted); font-size: 15px; line-height: 1; }
.bullet-text {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  padding: 8px 10px; color: var(--ink); font: inherit; font-size: 13px; width: 100%;
}
.bullet-text:focus { outline: none; border-color: var(--amber);
  box-shadow: 0 0 0 2px rgba(95, 188, 203, .12); }
.row-del { background: none; border: none; color: var(--muted); font-size: 17px;
  cursor: pointer; padding: 0 4px; line-height: 1; }
.row-del:hover { color: #e88b80; }
.link-row .link-other {
  background: var(--card-2); border: 1px solid var(--amber); border-radius: 5px;
  padding: 8px 10px; color: var(--ink); font: inherit; font-size: 13px; width: 100%;
}

/* ── Roster editor bands ───────────────────────────────── */
tr.band-row td {
  background: var(--paper); padding: 18px 8px 7px; border-bottom: 1px solid var(--line-2);
}
tr.band-row:first-child td { padding-top: 8px; }
.band {
  font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--amber-ink); font-weight: 700;
}
.band-n { font-size: 11px; color: var(--muted); margin-left: 8px; }
.fixed-cell { font-size: 13px; color: var(--muted); padding: 7px 8px; display: inline-block; }
tr.band-row.new-band td { padding-top: 26px; border-bottom-color: rgba(74, 158, 134, .35); }
tr.band-row.new-band .band { color: var(--green); }
.field .opt, .dest-head .opt { color: var(--muted); font-weight: 400; font-size: 11px;
  text-transform: lowercase; letter-spacing: .3px; margin-left: 4px; }
/* Only editors see this: a nudge that the card doesn't go anywhere yet. */
.no-dest { color: var(--rust); }
.card:not(:has(.card-link)) .thumb { opacity: .82; }

/* ── Projects table ────────────────────────────────────── */
.col-pname { width: 260px; }
.col-year  { width: 92px; }
.photo-cell.wide { width: 76px; height: 50px; }
.photo-cell.wide img, .photo-cell.wide .face-mini { width: 76px; height: 50px; border-radius: 4px; }
table.roster .col-photo:has(.wide) { width: 88px; }

/* Destination button: a dot that says what state the project is in. */
.dest-btn { min-width: 42px; }
.dest-btn::before { content: "→"; }
.dest-mark { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
.dest-btn[data-kind="none"] .dest-mark { background: var(--rust); }
.dest-btn[data-kind="page"] .dest-mark { background: var(--green); }
.dest-btn[data-kind="link"] .dest-mark { background: var(--blue); }

/* People popup */
.person-row { display: grid; grid-template-columns: 1fr auto auto auto; gap: 10px;
  align-items: center; padding: 7px 0; border-bottom: 1px solid var(--line); }
.person-row:last-child { border-bottom: none; }
.person-name { font-size: 13px; color: var(--ink); }
.person-row.raw .person-name { font-style: italic; color: var(--ink-2); }
.role-pick { display: flex; align-items: center; gap: 4px; font-size: 11px;
  color: var(--muted); cursor: pointer; white-space: nowrap; }
.role-pick input { accent-color: var(--amber); cursor: pointer; }
.role-pick:hover { color: var(--amber-ink); }
.role-pick.off { opacity: .3; cursor: default; }
.people-add { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 14px; }
.people-add select, .people-add input {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  padding: 8px 10px; color: var(--ink); font: inherit; font-size: 13px; width: 100%;
}
.people-add select:focus, .people-add input:focus { outline: none; border-color: var(--amber);
  box-shadow: 0 0 0 2px rgba(95, 188, 203, .12); }

/* Details popup */
.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.detail-grid .full { grid-column: 1 / -1; }
.detail-grid .field input {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  padding: 8px 10px; color: var(--ink); font: inherit; font-size: 13px; width: 100%;
}
.detail-grid .field input:focus { outline: none; border-color: var(--amber);
  box-shadow: 0 0 0 2px rgba(95, 188, 203, .12); }
@media (max-width: 640px) { .detail-grid { grid-template-columns: 1fr; } }

/* Destination popup reuses .dest-opt from the old form */
#dest-modal .dest-opt { margin-bottom: 10px; }
#dest-modal .dest-opt input#dest-url {
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 5px;
  padding: 8px 10px; color: var(--ink); font: inherit; font-size: 13px; width: 100%;
}

/* ── News ──────────────────────────────────────────────── */
.news-list { display: grid; gap: 14px; }
.news-card {
  display: grid; grid-template-columns: 300px 1fr;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden;
  /* A fixed height: the card's shape is the card's, not the photo's. A tall
     portrait shot would otherwise stretch the whole row. */
  height: 210px;
}
@media (max-width: 720px) {
  .news-card { grid-template-columns: 1fr; height: auto; }
  .news-shot { height: 200px; }
}

.news-shot { position: relative; background: var(--card-2); height: 100%; overflow: hidden; }
.news-shot .shots { width: 100%; height: 100%; display: block; }
.news-shot img {
  width: 100%; height: 100%; display: block;
  object-fit: cover;      /* fill the frame, crop the overflow */
  object-position: center;
}
/* `display: block` above would override the hidden attribute — HTML's hidden
   is only a UA `display: none`, and any author rule beats it. The carousel
   hides its off-screen shots with that attribute, so say so explicitly. */
.news-shot img[hidden] { display: none; }
.news-shot .shots.empty {
  display: flex; align-items: center; justify-content: center;
  color: #333939; height: 100%;
}
.news-shot .shots.empty svg { width: 30px; height: 30px; }
.shot-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  background: rgba(8,9,9,.6); border: 1px solid var(--line-2); color: var(--ink);
  width: 30px; height: 44px; cursor: pointer; font-size: 19px; line-height: 1;
  opacity: 0; transition: opacity .15s;
}
.shot-nav.prev { left: 0; border-radius: 0 4px 4px 0; border-left: none; }
.shot-nav.next { right: 0; border-radius: 4px 0 0 4px; border-right: none; }
.news-shot:hover .shot-nav { opacity: 1; }
.shot-nav:hover { background: rgba(8,9,9,.85); color: var(--amber-ink); }
.shot-dots { position: absolute; bottom: 9px; left: 0; right: 0;
  display: flex; justify-content: center; gap: 5px; }
.shot-dots span { width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255,255,255,.32); }
.shot-dots span.on { background: var(--brand-lit); }

.news-body { padding: 18px 22px; display: flex; flex-direction: column; gap: 7px;
  min-height: 0; /* let the text scroll-clip rather than push the card taller */ }
.news-cat { font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--brand-lit); font-weight: 700; }
.news-body h3 { margin: 0; font-size: 17px; font-weight: 700; letter-spacing: -.2px;
  line-height: 1.35; }
.news-text { color: var(--ink-2); font-size: 13px; line-height: 1.65; max-width: var(--measure);
  overflow: hidden; flex: 1; min-height: 0;
  /* Long posts fade out rather than stretch the card. */
  -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
}
.news-text p { margin: 0 0 9px; }
.news-text p:last-child { margin-bottom: 0; }
.news-date { margin-top: auto; padding-top: 10px; font-size: 12px; color: var(--muted); }

/* Homepage: same cards, tighter */
.news-list.compact .news-card { grid-template-columns: 200px 1fr; height: 140px; }
.news-list.compact .news-body { padding: 14px 17px; gap: 4px; }
.news-list.compact .news-body h3 { font-size: 15px; }
.news-list.compact .news-text { font-size: 12.5px; }
@media (max-width: 720px) {
  .news-list.compact .news-card { height: auto; }
  .news-list.compact .news-shot { height: 160px; }
}

/* ── News editor ───────────────────────────────────────── */
.col-date  { width: 140px; }
.col-cat   { width: 120px; }
.col-title { width: 280px; }
#body-modal textarea {
  width: 100%; background: var(--card-2); border: 1px solid var(--line-2);
  border-radius: 5px; padding: 10px 12px; color: var(--ink); font: inherit;
  font-size: 13px; line-height: 1.6; resize: vertical;
}
#body-modal textarea:focus { outline: none; border-color: var(--amber);
  box-shadow: 0 0 0 2px rgba(95, 188, 203, .12); }
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 9px; margin-bottom: 14px; }
.photo-tile { position: relative; aspect-ratio: 4 / 3; border-radius: 5px;
  overflow: hidden; border: 1px solid var(--line-2); }
.photo-tile.fresh { border-color: var(--green); }
.photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tile-x { position: absolute; top: 3px; right: 3px; width: 19px; height: 19px;
  border-radius: 50%; border: none; background: rgba(8,9,9,.8); color: var(--ink);
  cursor: pointer; font-size: 13px; line-height: 1; padding: 0; }
.tile-x:hover { background: #d1665c; }

/* ── Photo drop zone ───────────────────────────────────── */
.drop-zone {
  border: 2px dashed var(--line-2); border-radius: var(--r);
  padding: 26px 20px; text-align: center; cursor: pointer;
  transition: border-color .15s, background .15s; margin-bottom: 16px;
}
.drop-zone:hover { border-color: var(--amber); background: rgba(95, 188, 203, .04); }
.drop-zone.over { border-color: var(--green); background: rgba(74, 158, 134, .08); }
.drop-icon { color: var(--muted); margin-bottom: 8px; }
.drop-icon svg { width: 26px; height: 26px; }
.drop-zone.over .drop-icon { color: var(--green); }
.drop-text { font-size: 14px; color: var(--ink-2); font-weight: 600; }
.drop-sub { font-size: 12px; color: var(--muted); margin-top: 3px; }
.photo-tile { cursor: grab; }
.photo-tile.dragging { opacity: .4; cursor: grabbing; }
/* The row's image cell previews photo 0 and opens the photos popup —
   it is not an upload of its own. */
.photo-cell.as-btn { border: none; background: none; padding: 0; cursor: pointer; }
.photo-cell.as-btn .photo-hover { font-size: 12px; font-weight: 700; color: var(--amber-ink); }
.hidden-cell { width: 0; padding: 0 !important; border: none !important; }
/* The news editor leads with its add row, so it needs no top gap. */
tr.band-row.new-band.first td { padding-top: 8px; }
.form-actions.top { padding-top: 0; margin-bottom: 18px; }

/* ── Homepage news tiles ───────────────────────────────────
   The photo is the card: title and date ride on it. Full cards with body
   text live on /news; this is a glance. */
.news-tile { border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); }
/* One row, off the edge. Cards hold their width so the row stays a row. */
.news-rail .news-tile { flex: 0 0 250px; scroll-snap-align: start; }
.news-tile .news-shot { height: 190px; }
.news-tile .shots.empty { background: var(--card-2); }

/* A scrim, always on: the text has to survive a bright photo. */
.tile-text {
  position: absolute; inset: auto 0 0 0; padding: 34px 14px 12px;
  background: linear-gradient(180deg, transparent, rgba(4,6,6,.5) 42%, rgba(4,6,6,.88));
  pointer-events: none;
}
.tile-cat { font-size: 9px; letter-spacing: 1.4px; text-transform: uppercase;
  font-weight: 700; color: var(--brand-lit); margin-bottom: 4px; }
.tile-text h3 { margin: 0; font-size: 13.5px; font-weight: 700; line-height: 1.35;
  color: #fff; letter-spacing: -.1px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tile-date { font-size: 11px; color: rgba(255,255,255,.62); margin-top: 5px; }

/* Dots move out of the text's way. */
.shot-dots.corner { top: 9px; bottom: auto; right: 10px; left: auto; justify-content: flex-end; }
.news-tile .shot-nav { height: 38px; }

/* ── Footer ────────────────────────────────────────────────
   The lab's whole surface in four columns: the roster, what we work on,
   the newsletter, and how to reach us. Small type, dense — it is a
   sitemap, not decoration. */
/* Same background as the page, deliberately: a footer with its own colour
   reads as chrome and gets skipped. This one carries the roster, so it has
   to read as content. A rule and space do the separating instead. */
.site-foot { border-top: 1px solid var(--line); padding: 38px var(--gutter) 0; }
/* Fixed widths at an even rhythm, starting from the left margin — the slack
   collects on the right rather than being spread into the gaps. Stretching
   to meet both edges is what makes a footer look like a form; even columns
   with room after them read as a set. */
/* Flex, not grid: the columns hold different things and want different
   widths — Newsletter is a list of months, Contact is an address. A grid
   forces one width on all of them. Flex wraps on its own, so there are
   still no breakpoints to guess wrong. */
.foot-cols { display: flex; flex-wrap: wrap; gap: 34px 40px; padding-bottom: 32px;
  align-items: flex-start; justify-content: flex-start; align-content: flex-start; }
/* No shrink: a column at its stated width or it wraps to the next line.
   Letting them shrink means they squeeze unevenly and drift out of line
   rather than wrapping cleanly. */
/* Columns size to their own content between sensible bounds, rather than to
   a width I picked by eye. `ch` is measured in the actual rendered font, so
   a wider font gets a wider column instead of a wrapped one — the browser
   knows the metrics and I do not.
     min: enough for the column heading
     max: stops one column sprawling on a wide screen
   Named foot-wide/foot-narrow, not wide/narrow: the generic .narrow belongs
   to the auth pages and its `margin: 20px auto` silently broke this once. */
.foot-col { flex: 0 1 auto; min-width: 16ch; max-width: 32ch; }
.foot-col.foot-wide { min-width: 22ch; max-width: 34ch; }   /* Team: name + role */
.foot-col.foot-narrow { min-width: 12ch; max-width: 20ch; } /* Newsletter: months */

/* A column whose content doesn't exist yet. Says so rather than pretending. */
.foot-note.placeholder { color: var(--muted); font-style: italic; font-size: 11px; }

.foot-col h3 { margin: 0 0 10px; font-size: 11px; letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--ink); font-weight: 700; }
.foot-note { margin: 0 0 9px; font-size: 12px; line-height: 1.55; color: var(--ink-2); }
.foot-note a { color: var(--ink-2); }
.foot-note a:hover { color: var(--brand-lit); text-decoration: none; }
.foot-sub { font-size: 10px; letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--muted); margin: 11px 0 5px; font-weight: 700; }

/* One name per row. A packed grid saves space but reads as a word cloud;
   a single column reads as a roster. */
.foot-list { list-style: none; margin: 0; padding: 0; }
.foot-list li { display: flex; align-items: baseline; gap: 7px; padding: 0; line-height: 1.65; }
.foot-list.quiet .foot-name { color: var(--muted); }
.foot-name { font-size: 12px; color: var(--ink-2); }
a.foot-name:hover { color: var(--brand-lit); text-decoration: none; }
.foot-name.lead { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.foot-tier { display: flex; align-items: baseline; gap: 7px; margin-bottom: 9px; }
.foot-role { font-size: 10.5px; color: var(--muted); font-style: italic; }

.foot-plain { list-style: none; margin: 0; padding: 0; }
.foot-plain li { font-size: 12px; color: var(--ink-2); line-height: 1.5;
  padding: 4px 0; border-bottom: 1px solid var(--line); }
.foot-plain li:last-child { border-bottom: none; }
.foot-plain a { color: var(--ink-2); display: block; }
.foot-plain a:hover { color: var(--brand-lit); text-decoration: none; }
.issues .issue-title { color: var(--muted); margin-left: 7px; }

.foot-more { display: inline-block; margin-top: 12px; font-size: 11.5px; color: var(--muted); }
.foot-more:hover { color: var(--brand-lit); text-decoration: none; }

.foot-base { display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 16px 0 20px; border-top: 1px solid var(--line);
  font-size: 11px; color: var(--muted); }
.col-month { width: 150px; }