/* ==========================================================================
   SUSAN — portfolio. Editorial and quiet: big type, thin rules, one accent
   used sparingly. Same background engine as the bio page on `main`.
   ========================================================================== */

:root {
  --accent: #22d3ee;
  --text:   #e9eef4;
  --muted:  #7d8b9c;
  --bg:     #0a0d11;
  --line:   rgba(150, 190, 215, .12);
  --font:   "Satoshi", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* System stack — no extra font request just for a few numerals. */
  --mono:   ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --wrap:   820px;                 /* wider, so the businesses have room to talk */
}

*, *::before, *::after { box-sizing: border-box; }

/* The UA's [hidden] rule loses to any ID selector below, which would leave
   empty widgets rendering. */
[hidden] { display: none !important; }

html { background: var(--bg); }

body {
  margin: 0;
  min-height: 100%;
  font-family: var(--font);
  color: var(--text);
  background: transparent;         /* block backgrounds paint after negative
                                      z-index layers — opaque would bury them */
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--accent); color: #04252c; }
a { color: inherit; }

/* ---------- background stack --------------------------------------------- */

#bg-color { position: fixed; inset: 0; background: var(--bg); z-index: -5; }

#bg-media { position: fixed; inset: 0; z-index: -4; overflow: hidden; }
#bg-media > img, #bg-media > video {
  width: 100%; height: 100%;
  object-fit: cover; object-position: var(--bg-position, center);
  display: block;
  filter: blur(var(--bg-blur, 0px)) brightness(var(--bg-brightness, 1))
          grayscale(var(--bk-gray, 0));
  transform: scale(var(--bg-scale, 1.04))
             translate3d(var(--par-x, 0px), var(--par-y, 0px), 0);
  transition: transform .45s cubic-bezier(.2, .8, .2, 1);
  will-change: transform;
}
#bg-media::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse at center,
              transparent 42%, rgba(0, 0, 0, var(--vignette, .55)) 100%);
}

#bg-overlay {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: -2; pointer-events: none;
  background: var(--overlay-color, rgba(7, 10, 14, .5));
  -webkit-mask-image: var(--spot-mask, none);
          mask-image: var(--spot-mask, none);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}

#lens-fx {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: -1; pointer-events: none;
}

/* The aurora sits UNDER the tint now (-3, below #bg-overlay at -2), so the
   overlay and vignette dim it exactly as they dim the photo. It also fades out
   across the middle, keeping the bands in the margins and off the reading
   column — the content is a 680px centre channel. */
#bg-fx {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: -3; pointer-events: none;
  /* Stops are in px off the centre line, not percentages — the reading column
     is a fixed 680px, so a percentage band drifts across it as the window
     resizes. 390px clears the column (340 half-width + margin); it fades back
     in by 500px. */
  --fx-clear: 390px;
  --fx-fade: 500px;
  -webkit-mask-image: linear-gradient(90deg,
      #000 0,
      #000 calc(50% - var(--fx-fade)),
      transparent calc(50% - var(--fx-clear)),
      transparent calc(50% + var(--fx-clear)),
      #000 calc(50% + var(--fx-fade)),
      #000 100%);
          mask-image: linear-gradient(90deg,
      #000 0,
      #000 calc(50% - var(--fx-fade)),
      transparent calc(50% - var(--fx-clear)),
      transparent calc(50% + var(--fx-clear)),
      #000 calc(50% + var(--fx-fade)),
      #000 100%);
}

/* Narrow screens have no margins for it to live in, so drop the mask and let
   the tint carry it instead. */
@media (max-width: 900px) {
  #bg-fx {
    -webkit-mask-image: none; mask-image: none;
    opacity: .45;
  }
}
#cursor-fx {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: 90; pointer-events: none;
}

/* ---------- scroll progress hairline ---------------------------------------- */

#progress {
  position: fixed; top: 0; left: 0;
  height: 1px; width: 0;
  background: var(--accent);
  box-shadow: 0 0 8px -1px var(--accent);
  z-index: 80;
  opacity: .8;
}

/* ---------- layout --------------------------------------------------------- */

#page { opacity: 0; transition: opacity .7s ease .1s; }
#page.visible { opacity: 1; }

.fold {
  width: 100%; max-width: var(--wrap);
  margin: 0 auto;
  /* Side padding scales with the viewport so the column never runs up against
     the edge on a laptop, and stays comfortable on a phone. */
  padding: clamp(72px, 12vh, 128px) clamp(24px, 5vw, 56px);
}

.fold--hero {
  min-height: 100vh;
  display: flex; flex-direction: column; justify-content: center;
  position: relative;
  padding-top: 0; padding-bottom: 0;
}

.fold h2 {
  margin: 0 0 34px;
  font-size: 13px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 0 18px rgba(34, 211, 238, .35);
}

/* A soft scrim behind the copy so text stays readable whatever photo sits
   behind it — cheaper and less fussy than boxing every paragraph. */
.fold--intro, #about, .prose, #about-more-inner { position: relative; }
#intro, .prose p, #about-more-inner p, .more-bits li, .lead, #facts {
  text-shadow: 0 1px 14px rgba(0, 0, 0, .75);
}

/* ---------- hero ------------------------------------------------------------ */

/* ---------- hero: contact toggle ------------------------------------------- */

#contact-toggle {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 9px;
  /* Generous, because line-height:.92 on the name swallows roughly 18px of
     this before anything shows. Set against the visible gap, not the margin. */
  margin: 0 0 clamp(38px, 5vw, 58px); padding: 8px 14px 8px 15px;
  font-family: inherit;
  font-size: 12px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--accent);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  position: relative; overflow: hidden;
  transition: border-color .35s ease, color .35s ease, padding .35s cubic-bezier(.2,.8,.2,1);
}
/* Accent wash that wipes across on hover, behind the label. */
#contact-toggle::before {
  content: ""; position: absolute; inset: 0;
  background: var(--accent); opacity: .08;
  transform: scaleX(0); transform-origin: left;
  transition: transform .45s cubic-bezier(.16,1,.3,1);
}
#contact-toggle:hover { border-color: var(--accent); }
#contact-toggle:hover::before { transform: scaleX(1); }
#contact-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
#contact-toggle > * { position: relative; }        /* above the wash */

#contact-toggle .dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent);
  transition: transform .45s cubic-bezier(.16,1,.3,1), box-shadow .35s ease;
}
#contact-toggle:hover .dot { box-shadow: 0 0 9px var(--accent); }
/* Open state: the dot stretches into a short bar — a close affordance without
   swapping in a different glyph. */
#contact-toggle[aria-expanded="true"] .dot {
  transform: scaleX(2.6);
  border-radius: 3px;
}

/* ---------- hero: the swap ------------------------------------------------- */

/* Both panels occupy the same cell, so the container keeps the height of the
   taller one and nothing below it moves during the transition. */
#hero-stack { display: grid; }
#hero-stack > * { grid-area: 1 / 1; align-self: start; }

#hero-main > *, #hero-contact > * {
  transition:
    opacity .55s cubic-bezier(.16, 1, .3, 1),
    transform .55s cubic-bezier(.16, 1, .3, 1),
    filter .55s cubic-bezier(.16, 1, .3, 1);
  transition-delay: calc(var(--i, 0) * 55ms);
}

/* contact hidden by default */
#hero-contact { pointer-events: none; }
#hero-contact > * { opacity: 0; transform: translateY(16px); filter: blur(7px); }

/* open: main leaves upward, contact arrives from below */
#hero-stack.showing #hero-main { pointer-events: none; }
#hero-stack.showing #hero-main > * {
  opacity: 0; transform: translateY(-14px); filter: blur(7px);
  /* Leaving is quicker than arriving, so the two don't visually collide. */
  transition-delay: calc(var(--i, 0) * 35ms);
}
#hero-stack.showing #hero-contact { pointer-events: auto; }
#hero-stack.showing #hero-contact > * {
  opacity: 1; transform: none; filter: none;
  transition-delay: calc(120ms + var(--i, 0) * 65ms);
}
/* ---------- quote ----------------------------------------------------------- */

#quote {
  /* Tighter now: the contact button follows it, and that carries its own
     larger gap before the name. */
  margin: 0 0 clamp(22px, 2.8vw, 32px);
  padding: clamp(18px, 2.2vw, 26px) clamp(20px, 2.6vw, 30px);
  max-width: 62ch;
  border-left: 2px solid var(--accent);
  border-radius: 0 8px 8px 0;
  background: linear-gradient(90deg, rgba(20, 33, 42, .66), rgba(13, 19, 26, .5));
}
/* Banner. A square source drops into a wide box, so object-fit:cover shows only
   the middle band — the crop lives here, not in the file. */
#quote-banner {
  position: relative;
  margin: -2px -2px 20px;          /* sit flush with the quote's padding */
  aspect-ratio: var(--banner-ratio, 4 / 1);
  overflow: hidden;
  border-radius: 6px;
}
#quote-banner img {
  width: 100%; height: 100%;
  object-fit: cover;               /* symmetric by default via object-position */
  display: block;
}

/* Line art on a white ground: inverting turns the white to black, screen makes
   that black drop out, and hue-rotate puts the colours back where they were —
   so the drawing reads light on the dark page with no white box around it. */
#quote-banner.blend-screen img {
  filter: invert(1) hue-rotate(180deg);
  mix-blend-mode: screen;
}

/* Feather every edge so the strip melts into the panel instead of reading as a
   pasted-in slab. Masking the image itself (rather than laying a gradient over
   it) keeps it working whatever sits behind. */
#quote-banner img {
  -webkit-mask-image:
      linear-gradient(90deg, transparent 0%, #000 9%, #000 91%, transparent 100%),
      linear-gradient(180deg, transparent 0%, #000 14%, #000 86%, transparent 100%);
          mask-image:
      linear-gradient(90deg, transparent 0%, #000 9%, #000 91%, transparent 100%),
      linear-gradient(180deg, transparent 0%, #000 14%, #000 86%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}

#quote-text {
  margin: 0;
  font-size: clamp(15px, 1.7vw, 17.5px);
  line-height: 1.65;
  font-style: italic;
  color: var(--text); opacity: .9;
  text-shadow: 0 1px 14px rgba(0, 0, 0, .8);
  text-wrap: pretty;
}
#quote-source {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11.5px; letter-spacing: .06em;
  color: var(--muted);
}
#quote-source::before { content: "— "; color: var(--accent); }

/* Circle sits beside the name and scales with it, so the pairing holds from
   mobile up to a wide desktop. */
#hero-id {
  display: flex; align-items: center;
  gap: clamp(18px, 2.4vw, 30px);
}

#pfp {
  flex: none;
  position: relative;
  width:  clamp(64px, 11vw, 104px);
  height: clamp(64px, 11vw, 104px);
  border-radius: 50%;
  overflow: hidden;
  display: grid; place-items: center;
  border: 1px solid rgba(150, 190, 215, .22);
  background: rgba(20, 30, 40, .5);
  box-shadow: 0 0 0 4px rgba(34, 211, 238, .07), 0 14px 40px -18px rgba(0, 0, 0, .9);
  transition: border-color .3s ease, box-shadow .3s ease, transform .3s cubic-bezier(.2,.8,.2,1);
}
#pfp:hover {
  transform: translateY(-2px);
  border-color: rgba(34, 211, 238, .5);
  box-shadow: 0 0 0 4px rgba(34, 211, 238, .12), 0 18px 44px -18px rgba(34, 211, 238, .4);
}
#pfp img { width: 100%; height: 100%; object-fit: cover; display: block; }
#pfp.has-image { background: none; }

/* Shown until there's a picture — an initial, not a broken frame. */
#pfp-fallback {
  font-size: clamp(24px, 4vw, 40px);
  font-weight: 900; letter-spacing: -.03em;
  color: var(--muted); opacity: .55;
}

@media (max-width: 620px) {
  #hero-id { gap: 14px; }
}

#name {
  margin: 0;
  font-size: clamp(56px, 13vw, 108px);
  font-weight: 900; line-height: .92; letter-spacing: -.045em;
  /* Glow, like the bio page. Sits on the text rather than a box behind it. */
  text-shadow: 0 0 38px rgba(34, 211, 238, .32), 0 2px 30px rgba(0, 0, 0, .6);
}
/* Scales with the heading rather than sitting at a fixed px, so the name keeps
   the same breathing room from mobile up to a wide desktop. */
#tagline {
  margin: clamp(40px, 5.6vw, 64px) 0 0;
  font-size: clamp(18px, 2.6vw, 23px);
  line-height: 1.5; color: var(--text); max-width: 22ch;
}
#facts {
  margin: clamp(26px, 3vw, 38px) 0 0;
  font-size: 14px; color: var(--muted);
}
#facts span + span::before {
  content: "·"; margin: 0 10px; color: rgba(150, 190, 215, .35);
}

/* ---------- hero: contact panel -------------------------------------------- */

/* Availability as a source comment rather than a status dot — same
   information, without the dashboard cliché. */
#hc-availability {
  margin: 0 0 20px;
  font-family: var(--mono);
  font-size: 12.5px; letter-spacing: .02em; color: var(--muted);
  opacity: .75;
}
#hc-availability::before {
  content: "// ";
  color: var(--accent);
  opacity: .8;
}

/* A button now, not a link — clicking copies rather than navigates. */
#hc-handle {
  display: inline-flex; align-items: center; gap: 12px;
  margin: 0; padding: 0;
  background: none; border: 0;
  font-family: inherit;
  font-size: clamp(24px, 4.6vw, 40px);
  font-weight: 800; letter-spacing: -.035em;
  text-align: left;
  color: var(--text);
  cursor: pointer;
  transition: color .3s ease;
  max-width: 100%;
}
#hc-handle:hover { color: var(--accent); }
#hc-handle:active { transform: translateY(1px); }
#hc-handle:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; border-radius: 3px; }

/* Discord glyph + an @ prefix: together they stop "susanier.cc" reading as a
   website, which the .cc otherwise invites. */
#hc-handle-icon {
  display: inline-flex; flex: none;
  color: var(--muted);
  transition: color .3s ease, transform .3s cubic-bezier(.2, .8, .2, 1);
}
#hc-handle-icon svg { width: .82em; height: .82em; display: block; }
#hc-handle:hover #hc-handle-icon { color: #5865F2; transform: translateY(-2px); }

#hc-handle-text {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1px; background-repeat: no-repeat; background-position: 0 100%;
  transition: background-size .45s cubic-bezier(.16, 1, .3, 1);
  overflow-wrap: anywhere;
}
#hc-handle-text::before {
  content: "@";
  color: var(--muted);
  font-weight: 600;
  margin-right: .04em;
}
#hc-handle:hover #hc-handle-text { background-size: 100% 1px; }
#hc-handle:hover #hc-handle-text::before { color: var(--accent); }

/* Secondary contact, quiet underneath the handle. */
#hc-email {
  display: inline-block; margin-top: 12px;
  font-family: var(--mono);
  font-size: 13px; color: var(--muted);
  text-decoration: none;
  transition: color .25s ease;
}
#hc-email:hover { color: var(--accent); }

#hc-copy {
  flex: none;
  font-family: var(--mono);
  font-size: 11px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
  padding: 4px 9px; border: 1px solid var(--line); border-radius: 7px;
  cursor: pointer;
  transition: color .25s ease, border-color .25s ease, background .25s ease;
}
#hc-copy:hover { color: var(--accent); border-color: var(--accent); }
#hc-copy.done { color: #4ade80; border-color: rgba(74, 222, 128, .5); }
#hc-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

#hc-note { margin: 20px 0 0; font-size: 16px; color: var(--muted); max-width: 34ch; }

#hc-socials { display: flex; gap: 18px; margin-top: 26px; }
#hc-socials a {
  color: var(--muted); display: inline-flex;
  transition: transform .2s cubic-bezier(.2,.8,.2,1), color .2s ease;
}
#hc-socials svg { width: 20px; height: 20px; display: block; }
#hc-socials a:hover { color: var(--accent); transform: translateY(-3px); }

#cue {
  position: absolute; left: 24px; bottom: 40px;
  width: 1px; height: 54px;
  background: linear-gradient(180deg, transparent, var(--accent));
  opacity: .5;
  animation: drop 2.4s ease-in-out infinite;
  transform-origin: top;
}
@keyframes drop {
  0%, 100% { transform: scaleY(.35); opacity: .25 }
  50%      { transform: scaleY(1);   opacity: .6 }
}

/* ---------- intro ------------------------------------------------------------ */

#intro {
  margin: 0;
  font-size: clamp(19px, 2.4vw, 24px);
  line-height: 1.6; color: var(--text);
  text-wrap: pretty;
}

/* ---------- work -------------------------------------------------------------- */

/* Glass cards rather than hairline rows — they need to hold their own against
   a photograph behind them. */
.work { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.work li {
  /* One set of numbers drives the row padding, the index column and the indent
     of the expanded panel, so the note and the detail text line up under the
     title instead of drifting apart. */
  --card-pad: 28px;
  --index-w: 20px;
  --col-gap: 18px;
  --text-indent: calc(var(--card-pad) + var(--index-w) + var(--col-gap));

  border: 1px solid var(--line);
  border-radius: 12px;
  /* No backdrop-filter here on purpose. Each blurred surface is its own
     composited layer with a blur pass every frame, and with one per card the
     scroll got noticeably heavy. Over a dark background a slightly stronger
     translucent fill is indistinguishable and costs nothing. */
  background: linear-gradient(160deg, rgba(22, 32, 42, .62), rgba(14, 20, 27, .48));
  transition: border-color .3s ease, transform .3s cubic-bezier(.2,.8,.2,1),
              box-shadow .3s ease;
}
.work li:hover {
  border-color: rgba(34, 211, 238, .4);
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -24px rgba(34, 211, 238, .55);
}

.work .row {
  display: grid;
  grid-template-columns: var(--index-w) 1fr auto;
  gap: 6px var(--col-gap);
  padding: 26px var(--card-pad);
  text-decoration: none;
  transition: color .25s ease;
}
.row.is-expandable { cursor: pointer; }
.work li:hover .work-name { color: var(--accent); }
li.open .work-name { color: var(--accent); }

/* Visit link on an expandable row — sits beside the toggle. */
.work-link {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex: none;
  font-size: 14px; line-height: 1;
  color: var(--muted); text-decoration: none;
  border: 1px solid transparent; border-radius: 6px;
  transition: color .22s ease, border-color .22s ease,
              background .22s ease, transform .22s cubic-bezier(.2,.8,.2,1);
}
.work-link:hover {
  color: var(--accent);
  border-color: rgba(34, 211, 238, .4);
  background: rgba(34, 211, 238, .08);
  transform: translateY(-1px);
}
.work-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The +, rotating into an × rather than swapping glyph. */
.work-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none;
  font-family: var(--mono); font-size: 17px; line-height: 1;
  color: var(--muted);
  transition: transform .35s cubic-bezier(.16, 1, .3, 1), color .25s ease;
}
.work li:hover .work-toggle { color: var(--accent); }
li.open .work-toggle { transform: rotate(45deg); color: var(--accent); }

/* 0fr → 1fr animates cleanly; height:auto cannot. */
.work-detail {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .45s cubic-bezier(.16, 1, .3, 1);
}
li.open .work-detail { grid-template-rows: 1fr; }
.work-detail-inner { overflow: hidden; opacity: 0; transition: opacity .3s ease; }
li.open .work-detail-inner { opacity: 1; transition-delay: .12s; }

/* Indented to the title's own column, not to the card edge. */
.work-detail-inner > * {
  margin-left: var(--text-indent);
  margin-right: var(--card-pad);
  max-width: 60ch;
}
.work-detail-inner > *:last-child { margin-bottom: 28px; }
/* margin-block, not the `margin` shorthand — the shorthand would reset the
   margin-left above and drop everything back to the card edge. */
.work-detail-inner p {
  margin-block: 0 16px; font-size: 15.5px; line-height: 1.7; color: var(--muted);
}
.work-results {
  list-style: none; padding: 0;
  margin-block: 0 16px;
  display: grid; gap: 8px;
}
.work-results li {
  position: relative; padding-left: 18px;
  font-family: var(--mono); font-size: 13.5px; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.work-results li::before { content: "—"; position: absolute; left: 0; color: var(--accent); }
.work-stack {
  font-family: var(--mono);
  font-size: 12.5px; letter-spacing: .04em;
  color: var(--muted); opacity: .75;
}
.work-visit {
  display: inline-block; margin-top: 6px;
  font-family: var(--mono); font-size: 12px;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent); text-decoration: none;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1px; background-repeat: no-repeat; background-position: 0 100%;
  transition: background-size .35s cubic-bezier(.16, 1, .3, 1);
}
.work-visit:hover { background-size: 100% 1px; }

@media (max-width: 620px) {
  .work li { --card-pad: 18px; --index-w: 18px; --col-gap: 12px; }
}

/* Monospace index — the sort of detail that reads as "built by hand". */
.work-index {
  font-family: var(--mono);
  font-size: 12px; color: var(--muted);
  opacity: .5; padding-top: 11px;
  font-variant-numeric: tabular-nums;
  transition: color .25s ease, opacity .25s ease;
}
a.row:hover .work-index { color: var(--accent); opacity: 1; }
a.row:hover .work-name { color: var(--accent); }
a.row:hover .arrow { opacity: 1; transform: none; }

.work-name {
  font-size: clamp(23px, 3.4vw, 31px);
  font-weight: 700; letter-spacing: -.028em;
  transition: color .25s ease;
}
.work-meta {
  display: flex; align-items: center; gap: 14px;
  align-self: center;
}
.work-year {
  font-family: var(--mono);
  font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.work-note {
  grid-column: 2 / -1;
  margin: 4px 0 0; font-size: 16px; line-height: 1.6; color: var(--muted);
  max-width: 62ch;                 /* was 46ch — room to actually say something */
}
.work-niche { color: var(--muted); font-weight: 500; }
.work-niche::before { content: " — "; }

.arrow {
  align-self: center;
  opacity: 0; transform: translateX(-6px);
  transition: opacity .25s ease, transform .25s ease;
  color: var(--accent);
}

/* ---------- about ----------------------------------------------------------------- */

.prose p {
  margin: 0 0 18px;
  font-size: 17px; line-height: 1.75; color: var(--muted);
  text-wrap: pretty;
}
.prose p:last-child { margin-bottom: 0; }

/* ---------- about: "even more" ------------------------------------------------------
   Deliberately quiet. Someone reading professionally should be able to skip
   the whole thing without feeling they missed anything.                            */

#more-toggle {
  display: inline-flex; align-items: center; gap: 9px;
  margin-top: 26px; padding: 0;
  background: none; border: 0;
  font-family: var(--mono);
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  transition: color .25s ease;
}
#more-toggle:hover { color: var(--accent); }
#more-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
#more-toggle::before {
  content: ""; width: 18px; height: 1px; background: currentColor; opacity: .5;
  transition: width .35s cubic-bezier(.16, 1, .3, 1);
}
#more-toggle:hover::before { width: 28px; }

.more-plus {
  font-size: 14px; line-height: 1;
  transition: transform .35s cubic-bezier(.16, 1, .3, 1);
}
#more-toggle[aria-expanded="true"] .more-plus { transform: rotate(45deg); }
#more-toggle[aria-expanded="true"] { color: var(--accent); }

/* Same 0fr → 1fr mechanic as the work rows. */
#about-more {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .45s cubic-bezier(.16, 1, .3, 1);
}
#about-more.open { grid-template-rows: 1fr; }
#about-more-inner { overflow: hidden; opacity: 0; transition: opacity .3s ease; }
#about-more.open #about-more-inner { opacity: 1; transition-delay: .12s; }

#more-hint {
  /* Tight to the toggle so the two mono lines read as one pair (~19px
     baseline-to-baseline at this size), then a wider gap before the prose.
     The contrast is what groups them. */
  margin: 6px 0 22px;
  font-family: var(--mono);
  font-size: 11.5px; letter-spacing: .06em;
  color: var(--muted); opacity: .6;
}
#more-hint::before { content: "// "; color: var(--accent); opacity: .8; }

/* :not() keeps this off the hint — otherwise `#about-more-inner p` (1-0-1)
   outranks `#more-hint` (1-0-0) and silently wins the margin. */
#about-more-inner p:not(#more-hint) {
  margin: 0 0 16px; font-size: 16px; line-height: 1.75; color: var(--muted);
}
.more-bits {
  list-style: none; margin: 4px 0 26px; padding: 0;
  display: grid; gap: 8px;
}
.more-bits li {
  position: relative; padding-left: 18px;
  font-family: var(--mono); font-size: 13px; color: var(--muted);
}
.more-bits li::before {
  content: "·"; position: absolute; left: 4px; color: var(--accent);
}

/* ---------- "i was here" ---------------------------------------------------------- */

#here-wrap {
  max-width: var(--wrap); margin: 0 auto;
  padding: 0 24px clamp(56px, 9vh, 96px);
  display: flex; justify-content: center;
}

/* A rectangular two-cell control: label on the left, count on the right,
   split by a rule. Physical rather than decorative — the whole thing sits on a
   2px bottom edge and presses down into it, like a key. */
#here {
  display: inline-flex; align-items: stretch;
  padding: 0;
  font-family: var(--mono);
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 3px;
  cursor: pointer;
  overflow: hidden;
  transition: border-color .2s ease, color .2s ease,
              transform .08s ease, border-bottom-width .08s ease;
}
#here:hover { color: var(--text); border-color: rgba(34, 211, 238, .55); }

/* Press: sink into the bottom edge instead of scaling. */
#here:active:not([disabled]) {
  transform: translateY(1px);
  border-bottom-width: 1px;
}
#here:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

#here-label {
  position: relative;
  padding: 12px 18px;
  overflow: hidden;
}
/* Fill sweeps in from the left on hover. */
#here-label::before {
  content: ""; position: absolute; inset: 0;
  background: var(--accent); opacity: .1;
  transform: scaleX(0); transform-origin: left;
  transition: transform .38s cubic-bezier(.16, 1, .3, 1);
}
#here:hover:not([disabled]) #here-label::before { transform: scaleX(1); }
#here-label > span, #here-label { position: relative; }

#here-count {
  display: flex; align-items: center; justify-content: center;
  min-width: 66px;
  padding: 12px 14px;
  border-left: 1px solid var(--line);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: background .25s ease, color .25s ease, border-color .25s ease;
}

/* Marked: the label cell fills solid. A definite state change, no indicator. */
#here.marked { border-color: rgba(34, 211, 238, .4); color: var(--muted); }
#here.marked #here-label {
  background: var(--accent);
  color: #04252c;
  font-weight: 700;
}
#here.marked #here-label::before { transform: scaleX(1); opacity: 0; }
#here.marked #here-count { color: var(--accent); border-left-color: rgba(34, 211, 238, .3); }

#here[disabled] { cursor: default; }

/* The count cell blinks once as the number lands. */
#here.bumped #here-count { animation: bump .45s ease-out; }
@keyframes bump {
  0%   { background: rgba(34, 211, 238, .22) }
  100% { background: transparent }
}

/* ---------- footer ------------------------------------------------------------------
   The page ends here. Contact lives behind the hero button, so this stays a
   single quiet line rather than another full section.                                */

#footer {
  max-width: var(--wrap); margin: 0 auto;
  padding: 24px 24px 34px;
  border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  font-family: var(--mono);
  font-size: 12px; color: var(--muted);
}
.foot-left, .foot-right { display: flex; align-items: center; gap: 14px; }
.foot-left  { justify-content: flex-start; }
.foot-right { justify-content: flex-end; }
#updated::before { content: "·"; margin-right: 14px; opacity: .5; }

/* Fixed bottom-right, mirroring the audio player on the left. Collapsed to
   just the key; the label slides out on hover, same pattern as the volume
   control. It was in the footer at 98% down the page, which made a
   discoverability hint the least discoverable thing on the site. */
#keys-open {
  position: fixed; right: 20px; bottom: 20px; z-index: 61;
  display: inline-flex; align-items: center; gap: 0;
  height: 34px; padding: 0 8px;
  background: rgba(12, 17, 22, .7);
  border: 1px solid var(--line);
  border-radius: 4px;
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  font-family: var(--mono);
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); cursor: pointer;
  overflow: hidden;
  transition: gap .25s ease, padding .25s ease, color .2s ease, border-color .2s ease;
}
#keys-open:hover { color: var(--text); border-color: rgba(34, 211, 238, .5); }
#keys-open:hover kbd { border-color: var(--accent); color: var(--accent); }
#keys-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

#keys-open-label {
  max-width: 0; opacity: 0; white-space: nowrap;
  transition: max-width .28s cubic-bezier(.16, 1, .3, 1), opacity .2s ease;
}
#keys-open:hover { gap: 9px; padding-right: 13px; }
#keys-open:hover #keys-open-label { max-width: 90px; opacity: 1; }

@media (max-width: 640px) {
  #keys-open { display: none; }     /* no physical keyboard to speak of */
}

/* Physical-key treatment, same 2px bottom edge as the "i was here" control. */
kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 20px; padding: 0 6px;
  font-family: var(--mono); font-size: 11px; line-height: 1;
  color: var(--muted);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 3px;
  transition: color .2s ease, border-color .2s ease;
}

#footer #socials { display: flex; gap: 16px; margin: 0; }
#footer #socials a {
  color: var(--muted); display: inline-flex;
  transition: transform .2s cubic-bezier(.2,.8,.2,1), color .2s ease;
}
#footer #socials svg { width: 17px; height: 17px; display: block; }
#footer #socials a:hover { color: var(--accent); transform: translateY(-2px); }
#views { font-variant-numeric: tabular-nums; }

/* ---------- shortcuts dialog ---------------------------------------------------------- */

#keys {
  position: fixed; inset: 0; z-index: 95;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(6, 9, 13, .72);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .28s ease;
}
#keys.open { opacity: 1; }
/* The overlay is focused on open (for screen readers) and spans the viewport,
   so the UA focus ring frames the whole screen. Drop it — Esc is bound to
   document, so keyboard handling is unaffected. */
#keys:focus,
#keys:focus-visible { outline: none; }

#keys-panel {
  width: 100%; max-width: 340px;
  padding: 22px 24px 24px;
  background: rgba(14, 20, 26, .96);
  border: 1px solid var(--line);
  border-radius: 5px;
  transform: translateY(10px) scale(.985);
  transition: transform .32s cubic-bezier(.16, 1, .3, 1);
}
#keys.open #keys-panel { transform: none; }

#keys-panel h3 {
  margin: 0 0 18px;
  font-family: var(--mono);
  font-size: 11px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--accent);
}
#keys-list { margin: 0; }
.key-row {
  display: flex; align-items: center; gap: 14px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
}
.key-row:first-child { border-top: 0; }
.key-row dt { flex: none; }
.key-row dd {
  margin: 0; font-size: 13.5px; color: var(--muted);
}

/* ---------- audio -------------------------------------------------------------------- */

#player {
  position: fixed; left: 20px; bottom: 20px; z-index: 61;
  display: flex; align-items: center; gap: 10px;
  width: min(290px, calc(100% - 40px));
  padding: 8px 11px; border-radius: 13px;
  background: rgba(12, 17, 22, .7);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
#player-main { display: flex; flex-direction: column; min-width: 0; flex: 1; gap: 4px; }
#player-title { font-size: 12.5px; font-weight: 600; overflow: hidden;
                text-overflow: ellipsis; white-space: nowrap; }
#player-bar { height: 2px; border-radius: 99px; background: rgba(255,255,255,.14);
              overflow: hidden; cursor: pointer; }
#player-progress { height: 100%; width: 0; background: var(--accent); }
#player-toggle, #player-next {
  flex: none; width: 29px; height: 29px;
  display: grid; place-items: center; border-radius: 50%;
  border: 1px solid var(--line); background: rgba(255,255,255,.05);
  color: var(--text); cursor: pointer;
  transition: background .2s ease, transform .2s ease;
}
#player-toggle:hover, #player-next:hover { background: rgba(34,211,238,.14); transform: scale(1.07); }

#volume {
  position: fixed; top: 20px; right: 20px; z-index: 61;
  display: flex; align-items: center;
  height: 36px; padding: 0 10px; border-radius: 18px;
  background: rgba(12, 17, 22, .7);
  border: 1px solid var(--line);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  color: var(--text); cursor: pointer; overflow: hidden;
  transition: gap .25s ease, padding .25s ease;
}
#volume-slider {
  width: 0; opacity: 0; accent-color: var(--accent); cursor: pointer;
  transition: width .25s ease, opacity .25s ease;
}
#volume:hover { gap: 10px; padding-right: 13px; }
#volume:hover #volume-slider { width: 70px; opacity: 1; }

#equalizer {
  position: fixed; left: 0; right: 0; bottom: 0;
  width: 100%; height: 70px; z-index: -1; pointer-events: none;
}

/* ---------- reveal --------------------------------------------------------------------- */

.reveal, .work li {
  opacity: 0; transform: translateY(16px);
  transition: opacity .8s cubic-bezier(.16,1,.3,1), transform .8s cubic-bezier(.16,1,.3,1);
}
.reveal.in, .work li.in { opacity: 1; transform: none; }

/* ---------- edit mode -------------------------------------------------------------------
   Only present when the page is opened with ?edit and the server allows it.   */

body.editing { padding-bottom: 64px; }

[contenteditable].is-editable {
  outline: 1px dashed rgba(34, 211, 238, .35);
  outline-offset: 4px;
  border-radius: 2px;
  transition: outline-color .2s ease, background .2s ease;
  min-width: 1ch;                    /* empty fields stay clickable */
  min-height: 1em;
}
[contenteditable].is-editable:hover { outline-color: rgba(34, 211, 238, .7); }
[contenteditable].is-editable:focus {
  outline: 1px solid var(--accent);
  background: rgba(34, 211, 238, .06);
}

#editbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 200;
  display: flex; align-items: center; gap: 14px;
  padding: 12px 18px;
  background: rgba(10, 15, 20, .94);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  font-family: var(--mono);
  font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
}
#editbar .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted); flex: none;
}
#editbar.dirty .dot { background: #fbbf24; }
#editbar-title { color: var(--text); }
#editbar-status { margin-left: auto; text-transform: none; letter-spacing: .04em; }
#editbar-status.bad { color: #f87171; }

#editbar button {
  font-family: inherit; font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 7px 14px;
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 3px;
  background: transparent; color: var(--muted);
  cursor: pointer;
  transition: color .2s ease, border-color .2s ease, transform .08s ease;
}
#editbar button:hover { color: var(--text); border-color: rgba(34,211,238,.55); }
#editbar button:active { transform: translateY(1px); border-bottom-width: 1px; }
#editbar-save { color: var(--accent) !important; border-color: rgba(34,211,238,.45) !important; }

/* ==========================================================================
   BANKAI
   Everything here is inert until bankai.js adds .bankai-live. The whole layer
   is built on first press, so a visitor who never touches the button never
   pays for any of it.
   ========================================================================== */

#bankai {
  position: fixed; inset: 0;
  z-index: 9000;
  pointer-events: none;
  contain: layout paint style;     /* nothing in here can reflow the page */
}
#bankai.live { pointer-events: auto; cursor: pointer; }

#bankai-fx { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Two flat layers doing opposite jobs. `back` is the surface the corridor is
   drawn against and sits under the canvas; `plate` is a hard cut and covers
   everything. Both are DOM: a full-viewport flat colour is one composited
   layer, where filling the canvas costs a screen-sized overdraw per frame. */
#bankai-back, #bankai-plate {
  position: absolute; inset: 0;
  opacity: 0;
  will-change: opacity;
}

html.bankai-live #page {
  filter: grayscale(var(--bk-gray, 0));
  transform: translate3d(var(--bk-x, 0px), var(--bk-y, 0px), 0)
             scale(var(--bk-scale, 1));
  will-change: transform, filter;
}
html.bankai-live #bg-media {
  transform: translate3d(calc(var(--bk-x, 0px) * 1.6),
                         calc(var(--bk-y, 0px) * 1.6), 0);
}
/* No scroll-chasing while it plays — the shot is composed for this viewport.
   The padding replaces the classic scrollbar's width so locking it doesn't
   jolt the layout sideways on platforms that reserve space for one. */
html.bankai-live { overflow: hidden; padding-right: var(--bk-sbw, 0px); }
html.bankai-live #progress,
html.bankai-live #keys-open,
html.bankai-live #player,
html.bankai-live #volume { opacity: 0; transition: opacity .25s ease; }

/* ---- the call ----------------------------------------------------------
   Condensed to the point of distortion and larger than the viewport, so the
   letters crop top and bottom exactly as they do in the source edit. */
#bankai-word {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  opacity: 0;
  filter: invert(var(--w-invert, 0));
}
#bankai-word span {
  grid-area: 1 / 1;
  font-family: var(--font);
  font-weight: 900;
  font-size: clamp(96px, 23vw, 340px);
  letter-spacing: -.035em;
  line-height: .8;
  white-space: nowrap;
  transform: scale(var(--w-scale, 1)) scaleY(1.42) scaleX(.9);
  will-change: transform;
}
#bankai-word-main  { color: #f2f3f5; }
#bankai-word-echo {
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(255, 255, 255, .34);
  translate: -.055em .06em;
}

/* ---- letterbox --------------------------------------------------------- */
#bankai-bars { position: absolute; inset: 0; }
#bankai-bars::before, #bankai-bars::after {
  content: ""; position: absolute; left: 0; right: 0;
  height: 8vh; background: #000;
  transform: scaleY(0);
  transition: transform .9s cubic-bezier(.16, 1, .3, 1);
}
#bankai-bars::before { top: 0;    transform-origin: top; }
#bankai-bars::after  { bottom: 0; transform-origin: bottom; }
#bankai.framed #bankai-bars::before,
#bankai.framed #bankai-bars::after { transform: scaleY(1); }

/* ---- what you just watched --------------------------------------------- */
#bankai-credit {
  position: absolute; left: clamp(20px, 5vw, 54px); bottom: calc(8vh + 26px);
  display: flex; flex-direction: column; gap: 3px;
  padding-left: 14px;
  border-left: 1px solid rgba(244, 122, 178, .5);
  /* It lands wherever the page happens to have scrolled to, so it carries its
     own separation rather than relying on what's behind it. */
  text-shadow: 0 1px 16px rgba(0, 0, 0, .95), 0 0 3px rgba(0, 0, 0, .8);
  opacity: 0; transform: translateY(8px);
  transition: opacity .5s ease, transform .5s cubic-bezier(.16, 1, .3, 1);
}
#bankai-credit.on { opacity: 1; transform: none; }
#bankai-credit .bk-kanji {
  font-size: 26px; letter-spacing: .12em; color: #fff;
  text-shadow: 0 0 18px rgba(244, 122, 178, .75);
}
#bankai-credit .bk-name {
  font-family: var(--mono); font-size: 11px; letter-spacing: .22em;
  text-transform: uppercase; color: #f47ab2;
}
#bankai-credit .bk-who {
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  color: rgba(255, 255, 255, .45);
}

#bankai-skip {
  position: absolute; right: clamp(20px, 5vw, 54px); bottom: calc(8vh + 26px);
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: rgba(255, 255, 255, .28);
  opacity: 0; transition: opacity .6s ease 1.4s;
}
#bankai.framed #bankai-skip { opacity: 1; }

/* ---- the cut ------------------------------------------------------------
   Stand-ins for real text while it's in two pieces. Positioned in viewport
   coordinates because the page underneath is locked for the duration.

   The layer is the first child of #bankai, so the backdrop dims it and the
   letterbox covers it exactly as they do the real page. It carries the page's
   grayscale too — a clone in full colour over a drained page reads as text
   being revealed rather than text being cut. */
#bankai-cuts {
  position: absolute; inset: 0;
  filter: grayscale(var(--bk-gray, 0));
}
.bankai-cut {
  position: absolute;
  pointer-events: none;
}
.bankai-cut > * { will-change: transform, filter; }

/* ---------- responsive ------------------------------------------------------------------ */

@media (max-width: 620px) {
  #cue { display: none; }
  .work .row { padding: 18px 2px; }
  a.row:hover { padding-left: 6px; }
  #player { width: calc(100% - 40px); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .reveal, .work li { opacity: 1; transform: none; }
}
