/* =========================================================
   ASHWINI PAIGAVAN — Architecture Portfolio
   Design system: editorial / Swiss-grid / material-driven
   Brand accent sampled from the source portfolio: #D2232A
   ========================================================= */

:root{
  --bg:#F4F2EE;
  --bg-alt:#E8E5DE;
  --surface:#FFFFFF;
  --fg:#1A1A1A;
  --fg-muted:#5C5A56;
  --line:rgba(26,26,26,.14);
  --line-strong:rgba(26,26,26,.34);
  --accent:#D2232A;
  --accent-fg:#FFFFFF;
  --grain-opacity:.04;
  --cursor-mix: multiply;

  --font-serif:'Fraunces', 'Iowan Old Style', serif;
  --font-sans:'Space Grotesk', 'Helvetica Neue', Arial, sans-serif;
  --font-mono:'IBM Plex Mono', ui-monospace, monospace;

  --container:min(1400px, 92vw);
  --edge: 4vw;
  --dur-1: .6s;
  --dur-2: 1s;
  --ease: cubic-bezier(.16,.84,.32,1);
}

[data-theme="dark"]{
  --bg:#111110;
  --bg-alt:#1A1A19;
  --surface:#161615;
  --fg:#EDEAE3;
  --fg-muted:#948F86;
  --line:rgba(237,234,227,.13);
  --line-strong:rgba(237,234,227,.32);
  --accent:#F0454C;
  --accent-fg:#111110;
  --grain-opacity:.07;
  --cursor-mix: screen;
}

*,*::before,*::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; overflow-x:hidden; }
::selection{ background:var(--accent); color:var(--accent-fg); }

body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:var(--font-sans);
  font-size:16px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  transition:background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}

img,svg{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
ul,ol{ margin:0; padding:0; list-style:none; }
h1,h2,h3,h4,p{ margin:0; }
button{ font:inherit; background:none; border:0; color:inherit; cursor:pointer; }

.font-serif{ font-family:var(--font-serif); }

/* ---------- texture layer ---------- */
.grain{
  position:fixed; inset:0; z-index:9998; pointer-events:none;
  opacity:var(--grain-opacity); mix-blend-mode:var(--cursor-mix);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:180px 180px;
}

/* ---------- custom cursor ---------- */
.cursor-dot,.cursor-ring{ position:fixed; top:0; left:0; z-index:9999; pointer-events:none; border-radius:50%; transform:translate(-50%,-50%); }
.cursor-dot{ width:6px; height:6px; background:var(--accent); transition:transform .15s var(--ease), opacity .2s; }
.cursor-ring{ width:34px; height:34px; border:1px solid var(--line-strong); transition:transform .18s var(--ease), width .25s, height .25s, opacity .2s, border-color .3s; }
.cursor-ring.is-active{ width:64px; height:64px; border-color:var(--accent); }
body.no-cursor .cursor-dot,body.no-cursor .cursor-ring{ display:none; }

/* ---------- preloader ---------- */
.preloader{
  position:fixed; inset:0; z-index:10000; background:var(--bg);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1.4rem;
  transition:opacity .8s var(--ease), visibility .8s;
}
.preloader.is-done{ opacity:0; visibility:hidden; }
.preloader-line{ width:min(280px,60vw); }
.preloader-line path{ fill:none; stroke:var(--accent); stroke-width:1.5; stroke-dasharray:900; stroke-dashoffset:900; animation:draw 1.6s var(--ease) forwards; }
.preloader-text{ font-family:var(--font-mono); font-size:.72rem; letter-spacing:.35em; text-transform:uppercase; color:var(--fg-muted); }
@keyframes draw{ to{ stroke-dashoffset:0; } }

/* ---------- header ---------- */
.site-header{
  position:fixed; top:0; left:0; right:0; z-index:500;
  border-bottom:1px solid transparent;
  transition:border-color .4s, background .4s, transform .5s var(--ease);
}
.site-header.is-scrolled{ background:color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter:blur(10px); border-color:var(--line); }
.site-header.is-hidden{ transform:translateY(-100%); }
.header-inner{
  max-width:var(--container); margin:0 auto; padding:1.2rem 0;
  display:flex; align-items:center; justify-content:space-between; gap:2rem;
}
.logo{ font-family:var(--font-sans); font-size:.82rem; font-weight:700; letter-spacing:.16em; }
.logo span{ color:var(--accent); }
.main-nav{ display:flex; gap:2.2rem; font-size:.82rem; letter-spacing:.03em; }
.main-nav a{ position:relative; padding-bottom:3px; }
.main-nav a::after{ content:''; position:absolute; left:0; bottom:0; width:0; height:1px; background:var(--accent); transition:width .35s var(--ease); }
.main-nav a:hover::after{ width:100%; }
.header-right{ display:flex; align-items:center; gap:1.4rem; }

.theme-toggle{ display:flex; align-items:center; }
.toggle-track{ position:relative; width:46px; height:24px; border:1px solid var(--line-strong); border-radius:99px; display:block; }
.toggle-thumb{ position:absolute; top:2px; left:2px; width:18px; height:18px; border-radius:50%; background:var(--fg); transition:transform .4s var(--ease), background .4s; }
[data-theme="dark"] .toggle-thumb{ transform:translateX(21px); background:var(--accent); }

.menu-btn{ display:none; font-size:.75rem; letter-spacing:.05em; }
@media (max-width:1000px){
  .menu-btn{ display:inline-flex; align-items:center; border:1px solid var(--line-strong); padding:.5rem .9rem; border-radius:99px; }
}

/* ---------- side nav ---------- */
.side-nav{
  position:fixed; right:2.4rem; top:50%; transform:translateY(-50%); z-index:400;
  display:flex; flex-direction:column; gap:1.1rem;
}
.side-nav a{ display:flex; align-items:center; gap:.6rem; font-family:var(--font-mono); font-size:.62rem; letter-spacing:.1em; text-transform:uppercase; color:var(--fg-muted); opacity:0; transform:translateX(6px); transition:opacity .3s,transform .3s,color .3s; }
.side-nav.is-visible a{ opacity:1; transform:none; }
.side-nav a span{ width:6px; height:6px; border-radius:50%; border:1px solid var(--line-strong); transition:.3s; }
.side-nav a.is-active{ color:var(--fg); }
.side-nav a.is-active span{ background:var(--accent); border-color:var(--accent); transform:scale(1.5); }
@media (max-width:1000px){ .side-nav{ display:none; } }

/* ================= LAYOUT HELPERS ================= */
section{ position:relative; padding:4rem var(--edge); }
.section-heading{ margin-bottom:2rem; max-width:900px; }
.section-index{ display:block; font-family:var(--font-mono); font-size:.72rem; letter-spacing:.15em; text-transform:uppercase; color:var(--accent); margin-bottom:1.1rem; }
.section-heading h2{ font-family:var(--font-serif); font-weight:500; font-size:clamp(2rem,4.2vw,3.4rem); line-height:1.05; }

.reveal{ opacity:0; transform:translateY(34px); transition:opacity 1s var(--ease), transform 1s var(--ease); }
.reveal.is-in{ opacity:1; transform:none; }

/* ================= HERO ================= */
.hero{
  min-height:88svh; display:flex; align-items:stretch; padding:7rem var(--edge) 4rem;
  overflow:hidden;
}
.hero-grid-bg{
  position:absolute; inset:0; z-index:0; opacity:.5;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 100% 6.25%, 8.333% 100%;
  mask-image:linear-gradient(to bottom, black, transparent 92%);
}
.hero-inner{
  position:relative; z-index:2; max-width:var(--container); margin:0 auto; width:100%;
  /* flex-wrap (not a hard display:block media-query swap) so the visual
     drops below the text purely because it no longer fits — driven by the
     container's actual rendered width, not a viewport-width breakpoint that
     some mobile/in-app browsers report incorrectly. That mismatch was
     leaving hero-content squeezed into a sliver with hero-visual overlapping
     it instead of the two properly stacking. */
  display:flex; flex-wrap:wrap; align-items:center; gap:3vw;
}
.hero-content{ position:relative; flex:1 1 320px; min-width:280px; }
.eyebrow{ font-family:var(--font-mono); font-size:.78rem; letter-spacing:.14em; text-transform:uppercase; color:var(--fg-muted); margin-bottom:1.4rem; }
.hero-title{
  font-family:var(--font-serif); font-weight:500; letter-spacing:-.01em;
  font-size:clamp(3rem, 9.5vw, 7.6rem); line-height:.94; margin:0 0 1.6rem;
}
.hero-title em{ font-style:italic; font-weight:300; color:var(--accent); }
.hero-role{ font-size:1.05rem; color:var(--fg-muted); max-width:540px; }
.hero-role span{ color:var(--fg); border-bottom:1px solid var(--accent); }
.hero-tags{ display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1.8rem; }
.hero-tags span{
  font-family:var(--font-mono); font-size:.66rem; letter-spacing:.08em; text-transform:uppercase;
  border:1px solid var(--line-strong); padding:.4rem .8rem; border-radius:99px; color:var(--fg-muted);
}
/* large project render + a second, smaller one overlapping its bottom-left
   corner, with a dot-grid accent tucked behind the bottom-right — mirrors a
   printed collage rather than a single flat portrait. */
.hero-visual{ position:relative; width:min(34vw,420px); flex-shrink:0; align-self:center; }
.hero-visual-main{
  aspect-ratio:4/3.4; overflow:hidden; border-radius:1px;
  box-shadow:0 40px 90px -30px rgba(0,0,0,.5);
}
.hero-visual-main img{ width:100%; height:100%; object-fit:cover; }
.hero-visual-sketch{
  position:absolute; left:-16%; bottom:-15%; z-index:2; width:42%;
  aspect-ratio:1/1; overflow:hidden;
  border:5px solid var(--bg); box-shadow:0 24px 50px -18px rgba(0,0,0,.4);
}
.hero-visual-sketch img{ width:100%; height:100%; object-fit:cover; }
.hero-dots{
  position:absolute; right:-9%; bottom:-11%; z-index:0;
  width:120px; height:120px;
  background-image:radial-gradient(var(--line-strong) 1.4px, transparent 1.4px);
  background-size:13px 13px; opacity:.7;
}

.scroll-cue{
  position:absolute; left:var(--edge); bottom:2rem; z-index:2;
  display:flex; align-items:center; gap:.7rem; font-family:var(--font-mono); font-size:.68rem; letter-spacing:.15em; text-transform:uppercase; color:var(--fg-muted);
}
.scroll-cue span{ display:inline-block; animation:bob 1.8s ease-in-out infinite; }
@keyframes bob{ 0%,100%{ transform:translateY(0);} 50%{ transform:translateY(6px);} }

@media (max-width:860px){
  .hero{ min-height:auto; display:block; padding:6rem var(--edge) 2.5rem; }
  .hero-inner{ display:block; }
  .hero-title{ margin-bottom:1.2rem; }
  .hero-visual{ width:62%; margin:2.6rem auto 2rem; }
  .scroll-cue{ position:relative; left:auto; bottom:auto; margin-top:1.5rem; }
}

/* ================= TICKER ================= */
.ticker-section{ padding:1.6rem 0; border-top:1px solid var(--line); border-bottom:1px solid var(--line); overflow:hidden; background:var(--bg-alt); }
.ticker-track{
  display:flex; white-space:nowrap; width:max-content;
  font-family:var(--font-serif); font-style:italic; font-size:clamp(1.1rem,2.4vw,1.9rem);
  animation:ticker 30s linear infinite;
}
.ticker-track span{ padding:0 2rem; color:var(--fg); display:inline-flex; align-items:center; gap:1.2rem; }
.ticker-track span em{ font-style:normal; color:var(--accent); font-family:var(--font-mono); font-size:.62rem; letter-spacing:.14em; text-transform:uppercase; }
@keyframes ticker{ from{ transform:translateX(0);} to{ transform:translateX(-50%);} }

/* ================= WORKS (index list) ================= */
.work-list{ border-top:1px solid var(--line); }
.work-row{
  position:relative;
  display:grid; grid-template-columns:3.5rem 1fr auto auto auto 2rem;
  align-items:center; gap:2rem;
  padding:1.4rem 0; border-bottom:1px solid var(--line);
  cursor:pointer; transition:padding-left .4s var(--ease), color .4s;
}
.work-row:hover{ padding-left:1.4rem; color:var(--accent); }
.work-row.is-open{ color:var(--accent); }
.work-no{ font-family:var(--font-mono); font-size:.8rem; color:var(--fg-muted); }
.work-name{ font-family:var(--font-serif); font-size:clamp(1.3rem,2.8vw,2.1rem); font-weight:500; }
.work-name i{ font-style:italic; font-weight:300; opacity:.72; font-size:.72em; }
.work-type,.work-loc,.work-year{ font-family:var(--font-mono); font-size:.75rem; text-transform:uppercase; letter-spacing:.06em; color:var(--fg-muted); white-space:nowrap; }
.work-arrow{ font-size:1.2rem; transform:translateX(0); transition:transform .4s var(--ease); justify-self:end; }
.work-row:hover .work-arrow{ transform:translateX(6px); }
.work-row.is-open .work-arrow{ transform:rotate(90deg); }
@media (max-width:900px){
  .work-row{ grid-template-columns:2.4rem 1fr; row-gap:.4rem; }
  .work-type,.work-loc,.work-year{ grid-column:2; }
  .work-arrow{ display:none; }
}

/* project detail panel */
.work-detail{
  max-height:0; overflow:hidden; transition:max-height .7s var(--ease);
  background:var(--bg-alt); margin:0 calc(var(--edge) * -1);
}
.work-detail.is-open{ max-height:6000px; }
.work-detail-inner{ padding:3rem var(--edge) 1.5rem; display:grid; grid-template-columns:1fr 1fr; gap:3rem; align-items:start; }
.work-detail-inner figure{ border:1px solid var(--line); margin:0; background:var(--surface); }
.work-detail-inner figure img{ width:100%; height:auto; }
.work-detail-meta{ display:grid; grid-template-columns:1fr 1fr; gap:1rem; margin-top:1.6rem; }
.work-detail-meta div{ border-top:1px solid var(--line); padding-top:.6rem; font-size:.92rem; }
.work-detail-meta b{ display:block; font-family:var(--font-mono); font-size:.65rem; text-transform:uppercase; letter-spacing:.1em; color:var(--accent); margin-bottom:.35rem; }
.work-detail h3{ font-family:var(--font-serif); font-size:1.7rem; font-weight:500; margin-bottom:.8rem; }
.work-detail p{ color:var(--fg-muted); line-height:1.7; margin-bottom:1rem; }
.work-note{
  border-left:2px solid var(--accent); padding:.6rem 0 .6rem 1rem;
  font-size:.9rem; color:var(--fg-muted); margin-top:1.4rem!important;
}
.view-more-btn{
  display:inline-flex; align-items:center; gap:.5rem; margin-top:1.6rem;
  font-family:var(--font-mono); font-size:.75rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--accent); border-bottom:1px solid var(--accent); padding-bottom:.3rem;
  transition:gap .3s var(--ease), opacity .3s;
}
.view-more-btn:hover{ gap:.9rem; }
.view-more-btn span{ font-size:1rem; }
@media (max-width:900px){ .work-detail-inner{ grid-template-columns:1fr; gap:1.8rem; padding-top:2rem; } }

/* sub-projects (academic collection) */
.sub-projects{ display:flex; flex-direction:column; gap:1.1rem; margin-top:1.4rem; }
.sub-projects li{ border-top:1px solid var(--line); padding-top:.9rem; }
.sub-projects b{ font-family:var(--font-serif); font-size:1.05rem; font-weight:500; display:block; }
.sub-projects span{ font-family:var(--font-mono); font-size:.66rem; letter-spacing:.06em; text-transform:uppercase; color:var(--accent); display:block; margin:.2rem 0 .4rem; }
.sub-projects p{ font-size:.88rem; margin:0; line-height:1.6; }

/* gallery */
.gallery{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(190px,1fr)); gap:1px;
  background:var(--line); border-top:1px solid var(--line);
  margin:0 0 0; padding:0;
}
.gallery img{
  width:100%; aspect-ratio:1/1; object-fit:cover; background:var(--surface);
  cursor:zoom-in; transition:opacity .3s, transform .5s var(--ease);
}
.gallery img:hover{ opacity:.82; }

/* ================= PROFILE =================
   Rebuilt around the content itself (no portrait): a full-width heading row,
   an asymmetric lead/dossier split beneath it, and a full-width skills band —
   rather than a narrow left column with dead space where an image used to sit. */
/* Overrides the base `section` top padding (4rem) — stacked on the previous
   section's own 4rem bottom padding, that doubled up into a large empty gap
   above "02 — Profile" before any content appeared. */
.profile-section{ position:relative; overflow:hidden; padding-top:2rem; }

.profile-grid-bg{
  position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.5;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 100% 7.7%, 6.25% 100%;
  mask-image:radial-gradient(ellipse 85% 75% at 72% 35%, black, transparent 78%);
}
.profile-watermark{
  position:absolute; z-index:0; pointer-events:none; right:1vw; top:-3vh;
  font-family:var(--font-serif); font-weight:600; letter-spacing:-.04em; line-height:1;
  font-size:clamp(13rem,30vw,25rem); color:var(--fg); opacity:.04;
}

.profile-head{ position:relative; z-index:1; max-width:1100px; margin-bottom:3.2rem; }
.profile-head h2{ font-size:clamp(2.4rem,6vw,5rem); font-weight:500; line-height:1.02; margin-top:.5rem; }

.profile-body{
  position:relative; z-index:1;
  display:grid; grid-template-columns:1.35fr 1fr; align-items:start;
  gap:clamp(2.5rem,6vw,7rem);
}
.profile-lead{ padding-top:.3rem; }
.lead-line{
  font-family:var(--font-serif); font-style:italic; font-weight:400; color:var(--fg);
  font-size:clamp(1.35rem,2.3vw,1.85rem); line-height:1.4; margin-bottom:1.6rem;
}
.profile-lead p:not(.lead-line){ color:var(--fg-muted); line-height:1.85; font-size:1.05rem; max-width:640px; }

.profile-dossier{ border-left:1px solid var(--line); padding-left:clamp(1.5rem,3vw,3rem); }
.capability-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:1px; background:var(--line); margin:0 0 2.2rem; border:1px solid var(--line); }
.capability-grid div{ background:var(--bg); padding:1.1rem 1.3rem; font-size:.9rem; }
.capability-grid b{ display:block; font-family:var(--font-mono); font-size:.62rem; color:var(--accent); text-transform:uppercase; letter-spacing:.1em; margin-bottom:.4rem; }
.mini-head{
  font-family:var(--font-mono); font-size:.7rem; letter-spacing:.15em; text-transform:uppercase;
  color:var(--accent); margin:2rem 0 .8rem;
}
.profile-dossier .mini-head:first-of-type{ margin-top:0; }
.timeline{ display:flex; flex-direction:column; }
.timeline li{ display:grid; grid-template-columns:5rem 1fr; gap:.8rem; padding:.9rem 0; border-top:1px solid var(--line); font-size:.88rem; }
.timeline li:last-child{ border-bottom:1px solid var(--line); }
.timeline b{ font-family:var(--font-mono); color:var(--fg-muted); font-weight:400; font-size:.76rem; }
.timeline strong{ font-weight:500; }
.timeline span{ color:var(--fg-muted); line-height:1.6; }

.profile-skills{ position:relative; z-index:1; margin-top:4rem; padding-top:2.4rem; border-top:1px solid var(--line); }
.skill-tags{ display:flex; flex-wrap:wrap; gap:.6rem; }
.skill-tags span{
  font-family:var(--font-mono); font-size:.7rem; letter-spacing:.05em;
  border:1px solid var(--line-strong); padding:.45rem .85rem; border-radius:99px;
}
.skill-tags.soft{ margin-top:.8rem; }
.skill-tags.soft span{ border-style:dashed; color:var(--fg-muted); }

@media (max-width:900px){
  .profile-body{ grid-template-columns:1fr; gap:3rem; }
  .profile-dossier{ border-left:none; padding-left:0; border-top:1px solid var(--line); padding-top:2rem; }
  .profile-watermark{ display:none; }
}

/* ================= BOOK SHELF (one project book at a time) ================= */
.book-section{ text-align:center; background:var(--bg-alt); }
.book-section .section-heading{ margin-left:auto; margin-right:auto; }
.book-section .section-heading p{ color:var(--fg-muted); margin-top:1rem; font-size:1rem; }

.book-stage{
  position:relative; margin-top:2rem;
  min-height:clamp(640px, 88vh, 920px);
  display:flex; align-items:center; justify-content:center;
  perspective:2400px; /* static, so the cover's 3D rotation stays consistent
                          while .book-opener itself is being transformed */
}

/* ---- shelf view ---- */
.shelf-view{ animation:fadeIn .4s var(--ease); transition:opacity .35s ease; width:100%; }
.shelf-view.is-suppressed{ opacity:0; pointer-events:none; }
.shelf{ display:flex; align-items:center; justify-content:center; gap:2rem; }
.shelf-frame{ position:relative; display:flex; align-items:center; justify-content:center; }
/* Portrait, like a real closed book — it then opens into the wider landscape
   spread (targetRect() in script.js), which is physically what a book does. */
.shelf-viewport{ position:relative; z-index:2; width:min(400px, 62vw); overflow:hidden; perspective:1600px; }
.shelf-track{ display:flex; transition:transform .55s var(--ease); }
.shelf-track .book-card{ flex:0 0 100%; }

/* the incoming card swivels into place (as if pivoting to face you) rather
   than just sliding flat — reads as a physical object turning, not a slide */
.book-card.is-entering-next .book-cover{ transform:rotateY(26deg) scale(.9) !important; transition:none !important; }
.book-card.is-entering-prev .book-cover{ transform:rotateY(-26deg) scale(.9) !important; transition:none !important; }

/* the outgoing card tilts away in the same rotational direction as it's
   carried off by the track's slide — uses the normal (not !important,
   not transition:none) rule below so it animates smoothly rather than
   snapping, since it's already resting at rotateY(0) when this is added */
.book-card.is-leaving-next .book-cover{ transform:rotateY(-24deg) scale(.9); }
.book-card.is-leaving-prev .book-cover{ transform:rotateY(24deg) scale(.9); }

/* soft silhouettes of the adjacent books, peeking from behind the current
   one — communicates where the shelf came from / is going without competing
   with the active cover for attention */
.shelf-ghost{
  position:relative; z-index:1; flex:0 0 auto;
  width:min(230px, 32vw); aspect-ratio:3/4;
  border-radius:2px 5px 5px 2px; overflow:hidden; background:var(--surface);
  opacity:.34; filter:blur(1.4px) saturate(.5);
  transform:scale(.9);
  box-shadow:0 24px 44px -22px rgba(0,0,0,.55);
  transition:opacity .45s var(--ease), transform .45s var(--ease);
}
.shelf-ghost img{ width:100%; height:100%; object-fit:cover; }
.shelf-ghost::after{ /* matching spine, so the ghosts read as books too */
  content:''; position:absolute; left:0; top:0; bottom:0; width:12px;
  background:linear-gradient(to right, rgba(0,0,0,.5), rgba(0,0,0,.12) 60%, transparent);
}
.shelf-ghost-prev{ margin-right:-90px; }
.shelf-ghost-next{ margin-left:-90px; }
.shelf-ghost.is-empty{ opacity:0; }
@media (max-width:640px){
  .shelf-ghost{ width:min(150px, 26vw); }
  .shelf-ghost-prev{ margin-right:-60px; }
  .shelf-ghost-next{ margin-left:-60px; }
}

/* A physical hardback: portrait proportions, a stacked contact→ambient
   shadow (rather than a flat offset block), a shaded spine down the left
   and a sliver of page edges on the fore-edge. */
.book-card{ cursor:pointer; outline:none; }
.book-cover{
  position:relative; aspect-ratio:3/4; /* testing a taller cover per reference */
  border-radius:2px 6px 6px 2px;
  overflow:hidden; background:var(--surface); transform-style:preserve-3d;
  box-shadow:
    0 1px 2px rgba(0,0,0,.22),
    0 10px 20px -8px rgba(0,0,0,.34),
    0 34px 54px -24px rgba(0,0,0,.5);
  transition:transform .55s cubic-bezier(.22,.9,.32,1), box-shadow .45s var(--ease);
}
.book-card:hover .book-cover, .book-card:focus-visible .book-cover{
  transform:translateY(-8px) rotateY(-3deg);
  box-shadow:
    0 2px 4px rgba(0,0,0,.24),
    0 18px 32px -10px rgba(0,0,0,.4),
    0 54px 74px -28px rgba(0,0,0,.58);
}
/* contain, not cover — the source pages are square while the cover is a
   taller portrait box, and cover was cropping the top/sides off; contain
   shows the whole page, with the surface colour filling the small letterbox
   margin instead of losing content */
.book-cover img{ width:100%; height:100%; object-fit:contain; background:var(--surface); }

/* spine shading — the hinge the cover rotates around when it opens */
.book-spine{
  position:absolute; left:0; top:0; bottom:0; width:18px; z-index:2;
  background:linear-gradient(to right,
    rgba(0,0,0,.58) 0%,
    rgba(0,0,0,.26) 42%,
    rgba(255,255,255,.10) 66%,
    rgba(0,0,0,.14) 100%);
}
/* fore-edge: hint of stacked page edges opposite the spine */
.book-cover::after{
  content:''; position:absolute; right:0; top:1.5%; bottom:1.5%; width:5px; z-index:2;
  background:repeating-linear-gradient(to right, rgba(255,255,255,.5) 0 1px, rgba(0,0,0,.12) 1px 2px);
  opacity:.55;
}
/* accent band along the foot of the jacket */
.book-cover::before{
  content:''; position:absolute; left:0; right:0; bottom:0; height:9px; z-index:3;
  background:var(--accent);
}
.book-open{
  position:absolute; left:0; right:0; bottom:11%; z-index:4; text-align:center;
  font-family:var(--font-mono); font-size:.7rem; letter-spacing:.18em; text-transform:uppercase;
  color:#fff; text-shadow:0 2px 10px rgba(0,0,0,.8);
  opacity:.92; transition:opacity .3s var(--ease);
}
.book-open::after{
  content:''; display:block; width:52px; height:2px; background:var(--accent);
  margin:.5rem auto 0;
}
.book-card:hover .book-open, .book-card:focus-visible .book-open{ opacity:1; }

.book-label{ margin-top:1.3rem; }
.book-label b{ display:block; font-family:var(--font-serif); font-size:1.7rem; font-weight:500; }
.book-label i{ display:block; font-style:italic; color:var(--fg-muted); font-size:1rem; margin-top:.15rem; }
.book-label span{ display:block; font-family:var(--font-mono); font-size:.68rem; letter-spacing:.06em; text-transform:uppercase; color:var(--accent); margin-top:.5rem; }

.shelf-arrow{
  width:46px; height:46px; flex:0 0 auto; border:1px solid var(--line-strong); border-radius:50%;
  display:flex; align-items:center; justify-content:center; transition:.3s;
}
.shelf-arrow:hover:not(:disabled){ background:var(--accent); color:var(--accent-fg); border-color:var(--accent); }
.shelf-arrow:disabled{ opacity:.3; cursor:default; }

/* A second, closer pair of prev/next controls right under the book's title —
   the existing .shelf-arrow buttons flank the whole shelf row, which on
   mobile ends up far from the book and easy to miss when a swipe doesn't
   register; this row sits directly under the title instead. */
.shelf-nav-row{ display:flex; align-items:center; justify-content:center; gap:1.4rem; margin-top:1.8rem; }
.shelf-nav-btn{
  width:34px; height:34px; flex:0 0 auto; border:1px solid var(--line-strong); border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-size:.85rem; transition:.3s;
}
.shelf-nav-btn:hover:not(:disabled){ background:var(--accent); color:var(--accent-fg); border-color:var(--accent); }
.shelf-nav-btn:disabled{ opacity:.3; cursor:default; }

.shelf-dots{ display:flex; justify-content:center; gap:.5rem; }
.shelf-dot{ width:7px; height:7px; border-radius:50%; border:1px solid var(--line-strong); padding:0; transition:.3s; }
.shelf-dot.is-active{ background:var(--accent); border-color:var(--accent); transform:scale(1.3); }

@media (max-width:640px){
  .shelf{ gap:.8rem; }
  /* was capped at 300px, which plateaus well before the 640px breakpoint
     boundary (~405px viewport width) and leaves unused space either side
     on larger phones or a zoomed-out view — let it keep growing with the
     viewport instead. */
  .shelf-viewport{ width:min(420px, 74vw); }
}

@keyframes fadeIn{ from{ opacity:0; transform:translateY(8px);} to{ opacity:1; transform:none;} }

/* ================= BOOK OPENER =================
   The clicked cover animates open in place (a real FLIP: its start rect is
   set to exactly match the shelf card it was clicked from, then transitions
   to a centered "open" rect), while the cover face rotates away in 3D and
   the reader content fades in beneath it. See openBook()/closeBook() in
   script.js for the rect math and class choreography. */
.book-opener{
  /* JS sets left/top/width/height ONCE, to the final "open" rect — the box's
     real layout size never changes, so PageFlip's one-time size measurement
     is always correct regardless of animation timing. The FLIP illusion
     (starting small, at the clicked cover's position) is done purely with a
     transform, which JS animates from a computed start offset back to none. */
  position:absolute; z-index:5;
  visibility:hidden; pointer-events:none;
  transform-origin:top left;
  transition:transform .95s cubic-bezier(.22,.9,.32,1);
  /* StPageFlip's own container restricts touch to pan-y, but that only
     covers #flipbook itself — a second touch point landing anywhere else in
     this wrapper (the title bar, controls, the page margins) was still free
     to start a native pinch/double-tap zoom on mobile, which is what was
     zooming the whole page out while flipping. Extending the same pan-y
     restriction to the full opener closes that gap. */
  touch-action:pan-y;
}
.book-opener.is-active{ visibility:visible; pointer-events:auto; }

/* Deliberately blank — no cover image here. An image face on a rotating 3D
   plane is exactly what was rendering broken (bleeding outside its box at
   extreme rotation angles); a plain panel has nothing that can misrender. */
.opener-cover{
  position:absolute; inset:0; z-index:2;
  transform-style:preserve-3d; transform-origin:0% 50%; transform:rotateY(0deg);
  backface-visibility:hidden;
  border:1px solid var(--line-strong);
  background:
    linear-gradient(155deg, color-mix(in srgb, var(--surface) 90%, var(--fg) 10%), var(--surface) 55%);
  box-shadow:14px 18px 0 -2px var(--line), 0 40px 70px -35px rgba(0,0,0,.4);
  overflow:hidden;
  transition:
    transform .95s cubic-bezier(.22,.9,.32,1),
    box-shadow .95s cubic-bezier(.22,.9,.32,1),
    opacity .3s ease .55s;
}
.book-opener.is-opening .opener-cover,
.book-opener.is-open .opener-cover{
  transform:rotateY(-100deg);
  box-shadow:55px 26px 80px -30px rgba(0,0,0,.55);
}
.book-opener.is-open .opener-cover{ opacity:0; pointer-events:none; }
.opener-spine{ position:absolute; left:0; top:0; bottom:0; width:9px; background:linear-gradient(to right, rgba(0,0,0,.4), transparent); }

/* ---- reader (the pages) — occupies the same box as the cover, underneath it ---- */
.reader-view{
  position:absolute; inset:0; z-index:1;
  display:flex; flex-direction:column; align-items:center; gap:1.2rem; padding-top:.4rem;
  opacity:0; transform:scale(.96);
  transition:opacity .55s ease .3s, transform .7s cubic-bezier(.22,.9,.32,1) .3s;
}
.book-opener.is-opening .reader-view,
.book-opener.is-open .reader-view{ opacity:1; transform:none; }

/* .bm-bar/.bm-stage must fill .book-opener's actual box, not size themselves
   independently against the viewport — that mismatch was why the open book
   rendered at an uncontrolled size instead of the one actually set by JS. */
/* grid (not flex) so the title block centers under the bar's full width —
   an empty 1fr column balances the back-button column on the other side —
   rather than sitting left-aligned right next to the back button. */
.bm-bar{ width:100%; display:grid; grid-template-columns:1fr auto 1fr; align-items:baseline; gap:1.6rem; }
.bm-back{
  font-family:var(--font-mono); font-size:.72rem; letter-spacing:.06em; text-transform:uppercase;
  color:var(--fg-muted); border-bottom:1px solid transparent; transition:.25s; flex-shrink:0;
  justify-self:start;
}
.bm-back:hover{ color:var(--accent); border-color:var(--accent); }
.bm-titles{ text-align:center; }
.bm-titles b{ font-family:var(--font-serif); font-size:1.3rem; font-weight:500; margin-right:.7rem; }
.bm-titles span{ font-family:var(--font-mono); font-size:.72rem; color:var(--fg-muted); letter-spacing:.04em; }
.bm-stage{ width:100%; flex:1; min-height:0; display:flex; align-items:center; justify-content:center; }

@media (max-width:640px){
  /* The 3-column grid (1fr auto 1fr) squeezed "Back to shelf" and the title
     into narrow columns on phone widths, wrapping each word onto its own
     line. Stack them instead — plenty of width for both on their own row. */
  .bm-bar{ display:flex; flex-direction:column; align-items:center; gap:.5rem; text-align:center; }
  .bm-back{ justify-self:auto; white-space:nowrap; }
  .bm-titles{ display:flex; flex-direction:column; gap:.2rem; }
  .bm-titles b{ margin-right:0; }
}

#flipbook{ margin:0 auto; max-width:100%; box-shadow:0 30px 70px -30px rgba(0,0,0,.4); }
#flipbook .page{ background:var(--surface); overflow:hidden; }
#flipbook .page img{
  width:100%; height:100%; object-fit:contain; background:#fff;
  image-rendering:-webkit-optimize-contrast; /* keeps fine linework crisp */
}

.book-controls{ display:flex; align-items:center; gap:1.6rem; }
.book-controls button{ width:44px; height:44px; border:1px solid var(--line-strong); border-radius:50%; display:flex; align-items:center; justify-content:center; transition:.3s; }
.book-controls button:hover{ background:var(--accent); color:var(--accent-fg); border-color:var(--accent); }
#pageIndicator{ font-family:var(--font-mono); font-size:.75rem; letter-spacing:.08em; color:var(--fg-muted); min-width:64px; text-align:center; }
.book-hint{ font-family:var(--font-mono); font-size:.68rem; color:var(--fg-muted); letter-spacing:.05em; }

/* ================= CREDENTIALS ================= */
.recognition{ padding-top:4rem; padding-bottom:4rem; }
.press-list{ display:grid; grid-template-columns:repeat(3,1fr); border-top:1px solid var(--line); border-left:1px solid var(--line); margin-bottom:2.5rem; }
.press-list li{ border-right:1px solid var(--line); border-bottom:1px solid var(--line); padding:1.6rem; }
.press-list b{ display:block; font-family:var(--font-serif); font-size:1.1rem; margin-bottom:.4rem; }
.press-list span{ font-family:var(--font-mono); font-size:.7rem; color:var(--accent); text-transform:uppercase; letter-spacing:.06em; }
.course-list{ display:grid; grid-template-columns:repeat(2,1fr); gap:0 3rem; }
.course-list li{ display:flex; justify-content:space-between; align-items:baseline; gap:1.5rem; padding:.75rem 0; border-bottom:1px solid var(--line); }
.course-list b{ font-weight:500; font-size:.95rem; }
.course-list span{ font-family:var(--font-mono); font-size:.68rem; color:var(--fg-muted); text-align:right; white-space:nowrap; }
@media (max-width:900px){
  .press-list{ grid-template-columns:1fr; }
  .course-list{ grid-template-columns:1fr; gap:0; }
  .course-list li{ flex-direction:column; gap:.2rem; }
  .course-list span{ text-align:left; }
}

/* ================= CONTACT ================= */
/* was min-height:60vh + justify-content:center, which vertically centered
   a short block of content inside a tall box — on most viewports that put
   a large empty gap above "05 — Contact" before anything appeared. */
.contact{ display:flex; flex-direction:column; justify-content:flex-start; }
.contact h2{ font-family:var(--font-serif); font-weight:500; font-size:clamp(2.2rem,6vw,4.6rem); line-height:1.04; margin:1rem 0 2.4rem; }
.big-link{ display:inline-block; width:fit-content; font-family:var(--font-mono); font-size:clamp(1rem,2.2vw,1.5rem); border-bottom:1px solid var(--accent); padding-bottom:.4rem; color:var(--fg); }
.contact-meta{ display:flex; gap:4rem; margin-top:3.5rem; flex-wrap:wrap; }
.contact-meta > div{ border-top:1px solid var(--line); padding-top:1rem; }
.contact-meta b{ display:block; font-family:var(--font-mono); font-size:.65rem; text-transform:uppercase; letter-spacing:.1em; color:var(--accent); margin-bottom:.6rem; }
.contact-meta p{ color:var(--fg-muted); line-height:1.6; }

/* ================= FOOTER ================= */
.site-footer{
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1rem;
  padding:1.8rem var(--edge); border-top:1px solid var(--line);
  font-family:var(--font-mono); font-size:.7rem; letter-spacing:.05em; color:var(--fg-muted); text-transform:uppercase;
}
.site-footer a:hover{ color:var(--accent); }

/* ================= LIGHTBOX ================= */
.lightbox{
  position:fixed; inset:0; z-index:9000; display:none;
  align-items:center; justify-content:center;
  background:rgba(10,10,10,.94); padding:3vh 6vw;
}
.lightbox.is-open{ display:flex; }
.lightbox img{ max-width:100%; max-height:94vh; object-fit:contain; box-shadow:0 30px 80px rgba(0,0,0,.5); }
.lightbox button{
  position:absolute; color:#fff; font-size:1.4rem; width:52px; height:52px;
  border:1px solid rgba(255,255,255,.3); border-radius:50%;
  display:flex; align-items:center; justify-content:center; transition:.25s;
}
.lightbox button:hover{ background:var(--accent); border-color:var(--accent); }
.lb-close{ top:2vh; right:2vw; }
.lb-prev{ left:1.5vw; top:50%; transform:translateY(-50%); }
.lb-next{ right:1.5vw; top:50%; transform:translateY(-50%); }
@media (max-width:700px){
  .lightbox{ padding:2vh 2vw; }
  .lb-prev{ left:.5rem; } .lb-next{ right:.5rem; }
  .lightbox button{ width:42px; height:42px; font-size:1.1rem; }
}

@media (max-width:1000px){
  .main-nav{ display:none; }
  section{ padding:3.5rem var(--edge); }
}
