:root {
  --bg: #422862;
  --logo: #65458c;
  --fg: #fff;
  /* 1 design px (1920×1080 artboard); fits both dimensions so 16:9 layout never overflows */
  --u: min(calc(100vw / 1920), calc(100vh / 1080));
  --anchor: calc(724 * var(--u));      /* left edge of the active card = nav column */
  --top: calc(258 * var(--u));         /* top edge of all cards */
  --ease: cubic-bezier(.65, 0, .25, 1);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; background: var(--bg); color: var(--fg); }
html, body, input, textarea, select { font-family: 'Faculty Glyphic', sans-serif; }   /* the only typeface of the project */
body {
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}
a { color: inherit; text-decoration: none; }

/* ---------- LINK UNDERLINE — the one style for every link and underline in the project ----------
   Real text underline: thin, a little below the text, and it BREAKS around letters (g, y…) instead of crossing them.
   Values come from the tuner (Text & menu → Link underline): --ul-th (em), --ul-off (em), --ul-skip (auto | none).
   · .mail                      static underline on the text itself
   · .bdk > span (badge links)  static underline, redraws left→right on hover
   · .lt > span (list titles)   hidden, draws left→right on row hover
   The animated ones draw the underline on an ::after copy of the text (data-t), so the text itself is untouched. */
:root { --ul-th: .02; --ul-off: .2; --ul-skip: auto; }
/* plain links (.mail, .ab-link): a softer underline at rest; on hover the full line is drawn over it left→right, on leave it runs back (the ::after copy carries the bright line; data-t is set in about.js) */
.mail, .ab-link { position: relative; display: inline-block; text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--fg) 38%, transparent); text-decoration-thickness: calc(var(--ul-th) * 1em); text-underline-offset: calc(var(--ul-off) * 1em); text-decoration-skip-ink: var(--ul-skip); }
.mail::after, .ab-link::after { content: attr(data-t); position: absolute; left: 0; top: 0; white-space: nowrap; pointer-events: none; color: transparent;
  text-decoration: underline; text-decoration-color: var(--ul-c, var(--fg)); text-decoration-thickness: calc(var(--ul-th) * 1em); text-underline-offset: calc(var(--ul-off) * 1em); text-decoration-skip-ink: var(--ul-skip);
  clip-path: inset(0 100% 0 0); transition: clip-path .4s var(--ease); }
.mail:hover::after, .mail:focus-visible::after, .ab-link:hover::after, .ab-link:focus-visible::after { clip-path: inset(0); }
.ul, .bdk > span, .lt > span { position: relative; display: inline-block; }
.ul::after, .bdk > span::after, .lt > span::after {
  content: attr(data-t); position: absolute; left: 0; top: 0; white-space: nowrap; pointer-events: none; color: transparent;
  text-decoration: underline; text-decoration-color: var(--ul-c, var(--fg)); text-decoration-thickness: calc(var(--ul-th) * 1em); text-underline-offset: calc(var(--ul-off) * 1em); text-decoration-skip-ink: var(--ul-skip); }
/* line colour = the text colour of that place (the copy itself is transparent) */
.bdk > span::after, .lt > span::after { --ul-c: var(--bg); }
.bdk > span::after { transition: text-decoration-color .7s cubic-bezier(.65, 0, .25, 1); }
@keyframes ulin { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.lt > span::after { clip-path: inset(0 0 0 100%); transition: clip-path .3s var(--ease); }   /* rest: hidden; on leave it wipes away left→right */
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* ---------- header ---------- */
.top { position: fixed; inset: 0 0 auto 0; z-index: 10; pointer-events: none; height: calc(120 * var(--u)); }
.top > * { pointer-events: auto; position: absolute; }
.brand { left: calc(20 * var(--u)); top: calc(20 * var(--u)); display: flex; gap: calc(14 * var(--u)); align-items: center; font-size: var(--fs-s); line-height: var(--lh-s); }
.brand .logo { --s: max(40px, calc(58 * var(--u))); display: block; position: relative; width: var(--s); height: var(--s); flex: none; }
.brand .cube { position: absolute; inset: 0; transform-style: preserve-3d; }
.brand .face { position: absolute; inset: 0; background: var(--logo); backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.brand img { width: 100%; height: 100%; display: block; }
.brand__name { padding: 0; white-space: pre; }
.brand .caret { display: inline-block; width: max(1.5px, calc(1.6 * var(--u))); height: 1.05em; margin-left: .06em; background: #fff; vertical-align: -.14em; }
.brand .caret[hidden] { display: none; }
.nav { left: var(--anchor); top: calc(30 * var(--u)); display: flex; flex-direction: column; font-size: var(--fs-m); line-height: var(--lh-m); }
.nav a { opacity: .96; transition: opacity .2s; width: max-content; }
/* hovering a menu item blurs only the other menu items */
.stage, .brand, .mail, .counter, .listbtn, .nav a { transition: filter var(--nav-t, .35s) ease, opacity .2s; }
.stage { transition: filter var(--nav-t, .35s) ease, opacity var(--vd-t, .7s) ease, transform var(--vd-t, .7s) var(--ease); }
body:has(.nav a:hover) .nav a:not(:hover) { filter: blur(var(--nav-blur, 8px)); }
.mail { right: calc(20 * var(--u)); top: calc(30 * var(--u)); font-size: var(--fs-xs); line-height: var(--lh-xs); }

/* ---------- slider ---------- */
.stage { position: fixed; inset: 0; overflow: hidden; }
.track { position: absolute; left: 0; top: var(--top); transform-style: preserve-3d; }
.card {
  position: absolute; top: 0; left: 0;
  width: var(--cw, calc(var(--w) * var(--u))); height: var(--ch, calc(var(--h) * var(--u)));   /* --cw / --ch: set by main.js on phones (equal widths) */
  padding: max(2px, calc(var(--frame, 3) * var(--u))); background: #fff;
  box-shadow: 0 calc(6 * var(--u)) calc(18 * var(--u)) rgba(0, 0, 0, .12);
  cursor: pointer; will-change: transform; backface-visibility: hidden;
}
.card:focus { outline: none; }
.card:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.card__in { width: 100%; height: 100%; overflow: hidden; }
.card img { width: 100%; height: 100%; transform: scale(1.14); will-change: transform; transform-origin: 50% 50%; object-fit: cover; display: block; user-select: none; -webkit-user-drag: none; }

.info { position: absolute; left: var(--anchor); width: calc(min(300, var(--iw, 300)) * var(--u)); }   /* never wider than the photo (--iw = photo width, set per case) */
/* reveal: each line slides down out of the photo's shadow; Launch and colors follow with a small delay */
.rv {
  transition: opacity var(--t-in, .3s) ease calc(var(--d, 0s) * var(--t-stag, 1)),
              filter var(--t-in, .3s) ease calc(var(--d, 0s) * var(--t-stag, 1));
}
.is-out .rv, .is-pre .rv { opacity: 0; filter: blur(var(--t-blur, 10px)); }
.is-out .rv { transition: opacity var(--t-out, .3s) ease, filter var(--t-out, .3s) ease; }
.is-pre .rv { transition: none; }
.info__type { font-size: var(--fs-xs); line-height: var(--lh-xs); opacity: .85; margin-bottom: calc(14 * var(--u)); }
.info__title { font-weight: 400; font-size: var(--fs-m); line-height: var(--lh-m); margin-bottom: calc(16 * var(--u)); }
.info__desc { font-size: var(--fs-xs); line-height: var(--lh-xs); }

.meta { position: absolute; left: var(--anchor); bottom: calc(28 * var(--u)); }
.meta__label { font-size: var(--fs-xs); line-height: var(--lh-xs); opacity: .8; margin-bottom: calc(6 * var(--u)); }
.meta__date { font-size: var(--fs-xs); line-height: var(--lh-xs); margin-bottom: calc(52 * var(--u)); }
.chips { display: flex; width: calc(76 * var(--u)); min-width: 56px; height: 4px; }
.chips i { flex: 1; display: block; }

/* ---------- counter / grid button ---------- */
.counter { position: fixed; left: calc(20 * var(--u)); bottom: calc(27 * var(--u)); z-index: 10; font-size: var(--fs-xs); line-height: var(--lh-xs); opacity: .78; font-variant-numeric: tabular-nums; }
.counter span { display: inline-block; }
.counter #cur.tick { animation: tick .45s var(--ease); }
@keyframes tick { 0% { opacity: 0; transform: translateY(40%); } 100% { opacity: 1; transform: none; } }
.listbtn { position: fixed; right: calc(19 * var(--u)); bottom: calc(20 * var(--u)); z-index: 10; display: block; color: #fff; }
.listbtn .b-list, .listbtn .b-slider { display: flex; align-items: center; gap: .55em; font-size: var(--fs-xs); line-height: var(--lh-xs); white-space: nowrap; }   /* icon + text, text = xs token */
.listbtn .bi { display: block; flex: none; height: auto; }
.listbtn .b-list .bi { width: 1.4em; }
.listbtn .b-slider .bi { width: 1.55em; }
.listbtn .b-slider, .listbtn.is-open .b-list { display: none; }
.listbtn.is-open .b-slider { display: flex; }
.listbtn:hover { opacity: .7; }

/* ---------- list view ---------- */
/* view switch: the gallery sinks down, the list blurs in; on the way back the other way round */
body.list-open .stage { opacity: 0; visibility: hidden; transform: translateY(var(--vd, 100vh)); transition: filter var(--nav-t, .35s) ease, opacity var(--vd-t, .7s) ease, transform var(--vd-t, .7s) var(--ease), visibility 0s var(--vd-t, .7s); }
.list {
  --cols: calc(235 * var(--u)) calc(185 * var(--u)) calc(463 * var(--u)) calc(160 * var(--u)) calc(120 * var(--u));
  position: fixed; inset: 0; z-index: 5; overflow-x: hidden; overflow-y: auto;
  padding: calc(268 * var(--u)) calc(30 * var(--u)) calc(120 * var(--u)) calc(727 * var(--u));
  opacity: 0; visibility: hidden; transition: opacity var(--vl-t, .6s) ease, visibility 0s var(--vl-t, .6s);
}
.list.is-open { opacity: 1; visibility: visible; transition: opacity var(--vl-t, .6s) ease var(--vl-d, .15s), visibility 0s var(--vl-d, .15s); }
.lhead { display: grid; grid-template-columns: var(--cols); height: calc(26.5 * var(--u));
  font-size: var(--fs-xs); line-height: var(--lh-xs); opacity: .7; }
.lrow {
  display: block; position: relative; perspective: var(--persp, 888px); margin-top: -1px;
  opacity: 0; filter: blur(var(--vl-blur, 12px)); transition: opacity var(--vl-t, .6s) ease, filter var(--vl-t, .6s) ease;
}
.list.is-open .lrow { opacity: 1; filter: none; transition-delay: calc(var(--vl-d, .15s) + var(--i) * var(--l-stag, .04s)); }
.lhead { filter: blur(var(--vl-blur, 12px)); transition: filter var(--vl-t, .6s) ease; }
.list.is-open .lhead { filter: none; transition-delay: var(--vl-d, .15s); }
.lrow::before { content: ''; position: absolute; inset: 0; z-index: 5; }               /* steady hover target while the row turns */
.lcube { position: relative; transform-style: preserve-3d; transform-origin: 50% 50% var(--lz); transition: transform var(--lb-t, .55s) var(--ease); }
.lcube.is-cont { transform: var(--cont); }                                               /* "keep turning" mode: one more quarter turn on leave */
.lface { backface-visibility: hidden; -webkit-backface-visibility: hidden; display: grid; grid-template-columns: var(--cols); align-items: center;
  padding: calc(23.5 * var(--u)) 0; font-size: var(--fs-xs); line-height: var(--lh-xs); }
/* each row owns BOTH its lines (top and bottom), so they turn with it; neighbours' touching lines are hidden while a row is active */
.lfront { position: relative; padding-bottom: calc(23.5 * var(--u) + 2px); }
.lfront::before, .lfront::after { content: ''; position: absolute; left: 0; right: 0; height: 1px; background: rgba(255,255,255,.4); }
.lfront::before { top: 0; }
.lfront::after { bottom: 0; }
.lrow.act + .lrow .lfront::before, .lrow:has(+ .lrow.act) .lfront::after { opacity: 0; }
.lwhite { position: absolute; background: #fff; color: var(--bg); }
.lback { position: absolute; inset: 0; }
.lwhite .lt { padding-left: calc(var(--l-shift, 20) * var(--u)); }

/* where the white side starts (LIST_DIR): its position, the hinge, and how far the cube turns */
.list[data-dir="bottom"] .lrow { --hov: rotateX(90deg);  --cont: rotateX(180deg);  --lz: calc(var(--rh, 74px) * -.5); --persp: calc(var(--rh, 74px) * var(--lp, 12)); --bz: calc(var(--rh, 74px) * -1); }
.list[data-dir="top"]    .lrow { --hov: rotateX(-90deg); --cont: rotateX(-180deg); --lz: calc(var(--rh, 74px) * -.5); --persp: calc(var(--rh, 74px) * var(--lp, 12)); --bz: calc(var(--rh, 74px) * -1); }
.list[data-dir="right"]  .lrow { --hov: rotateY(-90deg); --cont: rotateY(-180deg); --lz: calc(var(--rw, 1160px) * -.5); --persp: calc(var(--rw, 1160px) * 2.2); --bz: calc(var(--rw, 1160px) * -1); }
.list[data-dir="left"]   .lrow { --hov: rotateY(90deg);  --cont: rotateY(180deg);  --lz: calc(var(--rw, 1160px) * -.5); --persp: calc(var(--rw, 1160px) * 2.2); --bz: calc(var(--rw, 1160px) * -1); }
.list[data-dir="bottom"] .lwhite { left: 0; right: 0; top: 100%; height: 100%; transform-origin: 50% 0;    transform: rotateX(-90deg); }
.list[data-dir="top"]    .lwhite { left: 0; right: 0; bottom: 100%; height: 100%; transform-origin: 50% 100%; transform: rotateX(90deg); }
.list[data-dir="right"]  .lwhite { top: 0; bottom: 0; left: 100%; width: 100%; transform-origin: 0 50%;   transform: rotateY(90deg); }
.list[data-dir="left"]   .lwhite { top: 0; bottom: 0; right: 100%; width: 100%; transform-origin: 100% 50%; transform: rotateY(-90deg); }
.list[data-dir="bottom"] .lback, .list[data-dir="top"] .lback { transform: translateZ(var(--bz)) rotateX(180deg); }
.list[data-dir="right"] .lback, .list[data-dir="left"] .lback { transform: translateZ(var(--bz)) rotateY(180deg); }
.lt { font-size: var(--fs-m); line-height: var(--lh-m); white-space: nowrap; }
.ld { max-width: calc(452 * var(--u)); }
@media (hover: hover) {
  .lrow:hover { z-index: 2; }
  .lrow:hover .lwhite .lt > span::after { clip-path: inset(0); transition: none; animation: ulin var(--ul-t, .45s) var(--ease) var(--ul-d, .15s) backwards; }
  .lrow:hover .lcube { transform: var(--hov); transition-duration: var(--lf-t, .55s); }
}

/* ---------- small screens ---------- */
@media (max-width: 760px), (max-width: 1100px) and (orientation: portrait) {
  :root { --u: calc(100vw / 760); --anchor: 20px; --top: 110px; }
  .top { height: 80px; padding-top: env(safe-area-inset-top); }
  .brand { left: 20px; z-index: 2; top: calc(16px + env(safe-area-inset-top)); gap: 10px; }
  .brand .logo { --s: 40px; }
  .nav { left: auto; right: 12px; top: calc(16px + env(safe-area-inset-top)); height: 40px; flex-direction: row; align-items: center; font-size: var(--fs-s); line-height: var(--lh-s); }
  .nav a { padding: 10px 8px; }   /* ≥44px tap area */
  .mail { display: none; }
  .meta { bottom: calc(70px + env(safe-area-inset-bottom)); }
  .info { width: calc(100vw - var(--anchor) - 20px); cursor: pointer; -webkit-tap-highlight-color: transparent; }   /* text may be wider than the photo on a phone */
  .stage { touch-action: none; }   /* swipes belong to the carousel, not to browser scroll / pull-to-refresh */
  .counter { bottom: calc(14px + env(safe-area-inset-bottom)); left: 20px; }
  .listbtn { bottom: calc(10px + env(safe-area-inset-bottom)); right: 12px; padding: 10px 8px; }   /* ≥44px tap area */
  .list { --cols: 1fr auto; padding: 110px 20px 90px; }
  .lhead, .lk, .li { display: none; }
  .lface { grid-template-columns: 1fr auto; row-gap: 8px; padding: 18px 0; }
  .ld { grid-column: 1 / -1; grid-row: 2; max-width: none; }
  .lwhite .lt { padding-left: 0; }
}
@media (prefers-reduced-motion: reduce) { .rv { transition: none; } }

/* Faculty Glyphic ships in a single weight (400): never ask for bold, the browser would fake it */
.faculty-glyphic-regular { font-family: 'Faculty Glyphic', sans-serif; font-weight: 400; font-style: normal; }

/* text selection: white fill, text in the page background colour (very light backgrounds: #151413) */
::selection { background: #fff; color: var(--sel-fg, var(--bg)); text-shadow: none; }
.wall--about ::selection { color: #181818; }   /* the About wall is its own black background */

/* "Copied ✓" state of the e-mail link */
.mail .bck, .ab-link .bck { display: inline-block; width: 1em; height: 1em; margin-left: .2em; vertical-align: -.12em; }

/* ---------- mobile base (≤760px) ---------- */
@media (max-width: 760px), (max-width: 1100px) and (orientation: portrait) {
  #tuner, #tuner-tab { display: none !important; }   /* dev panel is desktop-only */
  html { -webkit-text-size-adjust: 100%; }
  body { -webkit-tap-highlight-color: transparent; overscroll-behavior: none; }
}

/* touch: logo.js skips the cube when there is no hover, so the 5 extra faces stay stacked flat over the avatar - hide them */
@media (hover: none), (max-width: 760px) {
  .brand .face:not(:first-child) { display: none; }
}


/* ---------- menu: burger (mobnav.js adds html.nav-burger only when the items do not fit next to the logo) ---------- */
.burger { display: none; }
@media (max-width: 760px), (max-width: 1100px) and (orientation: portrait) {
  .nav a { filter: none !important; }   /* no sticky-hover blur on touch */
  html.nav-burger .top:not(.cs-top) .burger { display: block; position: absolute; right: 10px; top: calc(16px + env(safe-area-inset-top)); width: 44px; height: 40px; z-index: 3; padding: 0; border: 0; background: none; color: #fff; cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .burger i { position: absolute; left: 10px; right: 10px; height: 2px; border-radius: 1px; background: currentColor; transition: transform .4s var(--ease), top .4s var(--ease); }
  .burger i:nth-child(1) { top: 15px; } .burger i:nth-child(2) { top: 23px; }
  body.menu-open .burger i:nth-child(1) { top: 19px; transform: rotate(45deg); }
  body.menu-open .burger i:nth-child(2) { top: 19px; transform: rotate(-45deg); }
  /* the nav becomes a panel that slides down from the top; items centred */
  html.nav-burger .top:not(.cs-top) .nav { left: 0; right: 0; top: 0; height: auto; flex-direction: column; align-items: center; gap: 2px; padding: calc(84px + env(safe-area-inset-top)) 20px 28px; background: var(--bg, #222); box-shadow: 0 14px 36px rgba(0, 0, 0, .28); z-index: 1;
    font-size: var(--fs-m); line-height: var(--lh-m); transform: translateY(-105%); visibility: hidden; transition: transform .45s var(--ease), visibility 0s .45s; }
  html:not(.nav-ready) .top .nav { transition: none !important; }   /* no slide-in while the page is loading */
  html.nav-burger .wall--about .top .nav { background: #181818; }
  html.nav-burger .nav a { padding: 12px 24px; text-align: center; }
  html body.menu-open .top:not(.cs-top) .nav { transform: none; visibility: inherit; transition: transform .45s var(--ease); }
}

/* crawlable text (generated by tools/build-cases.mjs): in the HTML for search engines and screen readers, not painted */
.seo-text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
