/* ============================================================
   Abhyas — light revamp
   Warm paper background, friendly type, one distinct material
   per resource kind so you can spot a type before you read it.
   Standalone: nothing here is loaded by index.html yet.
   ============================================================ */

:root {
  /* --- ground ---
   The whole palette is tuned a few hundred K warm, the way a screen looks
   under macOS Night Shift, and the four resource hues carry ~20% more
   saturation. Night Shift is a display filter, so it never reaches a
   visitor's screen; this bakes the same feel into the design itself.
   Verified: no text pair lost contrast, four pairs gained. --- */
  --paper: #FFF8E6;          /* warm cream page */
  --surface: #FFFDF5;
  --ink: #282129;
  --ink-soft: #61545E;
  --muted: #928287;
  --hair: #EBE0CA;
  /* --- washes ---
     Soft surfaces are ink at low alpha, not opaque greys. A wash picks up
     whatever sits behind it, so a chip on the cream sheet and the same chip
     inside a white panel stay related instead of looking like two greys. --- */
  --wash:        rgba(40, 33, 41, .045);
  --wash-strong: rgba(40, 33, 41, .09);

  /* --- brand --- */
  --brand: #6A57E0;
  --brand-soft: #EEEAF8;
  --pink: #FF6B9D;

  /* --- one colour family per resource kind ---
     All four are pulled toward the warm cream ground and the amber CTA:
     amber is the anchor, the rest are its warm neighbours (terracotta,
     olive, clay-mauve) rather than four unrelated primaries. --- */
  --papers: #F28700;         /* quizzes & past papers — the CTA amber itself */
  --papers-tint: #FEE7C0;
  --papers-ink: #8B5000;

  --notes: #698B39;          /* notes & slides — warm olive */
  --notes-tint: #ECF0D1;
  --notes-ink: #495A23;

  --assignment: #D04724;     /* assignments — terracotta */
  --assignment-tint: #FDDFCC;
  --assignment-ink: #8D2D14;

  --reference: #8C6597;      /* reference books — clay mauve */
  --reference-tint: #F0E6F0;
  --reference-ink: #5B3C60;

  --font-display: "Bricolage Grotesque", "Plus Jakarta Sans", sans-serif;
  --font-body: "Plus Jakarta Sans", -apple-system, sans-serif;
  --font-mono: "DM Mono", ui-monospace, monospace;
  /* course names — the one thing people scan, so it gets its own face */
  --font-course: "Archivo", "Bricolage Grotesque", sans-serif;

  /* one vertical rhythm for content blocks — sections should not each
     invent their own padding */
  --section-y: 80px;

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;

  /* --- optical tracking ---
     Letter-spacing scales with size: display type needs to be pulled tight,
     body type needs none. Pick the band by rendered px, not by eye. Archivo
     runs one band looser than these — its counters close up faster than
     Bricolage's. --- */
  --track-hero: -.045em;   /* 48px+   */
  --track-xl:   -.036em;   /* 30–48px */
  --track-lg:   -.030em;   /* 24–30px */
  --track-md:   -.024em;   /* 19–24px */
  --track-sm:   -.014em;   /* 16–19px */
  --track-xs:   0;         /* <16px   */

  --ease: cubic-bezier(.2, .9, .3, 1);
  --pop: cubic-bezier(.34, 1.56, .64, 1);
  /* --- motion ---
     One curve for arrivals, heavily decelerated, and deliberately long:
     a slow front-loaded ease is most of what reads as "premium". Hovers
     stay short — a slow hover feels broken, not luxurious. --- */
  --ease-out-expo: cubic-bezier(.16, 1, .3, 1);
  --dur-arrive: .9s;
  --dur-hover: .28s;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 28px; }

/* ------------------------------------------------------------
   Page shell — the whole site sits on a tinted frame as a
   rounded sheet of paper.
   ------------------------------------------------------------ */
body { background: #EADCC2; padding: 14px; }
.shell {
  background: var(--paper);
  border-radius: 30px;
  min-height: calc(100vh - 28px);
  box-shadow: 0 30px 60px -30px rgba(70, 50, 20, .25);
  /* clip, not hidden: `overflow: hidden` makes this a scroll container, which
     makes view() timelines resolve against .shell instead of the document and
     leaves every card stuck in its finished state. `clip` crops identically
     to the radius without creating one. */
  overflow: clip;
}

/* ------------------------------------------------------------
   Header — few links, one action, nothing else
   ------------------------------------------------------------ */
.top { padding-top: 8px; position: relative; z-index: 2; }
.top-in { display: flex; align-items: center; height: 76px; }
.logo {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-display); font-weight: 800;
  font-size: 1.1rem; letter-spacing: var(--track-sm);
  text-decoration: none; color: var(--ink);
}
/* the mark carries its own ink and amber, so it needs no badge behind it */
.logo img {
  width: 34px; height: 34px; flex-shrink: 0;
  display: block; object-fit: contain;
  transition: transform .4s var(--pop);
}
.logo:hover img { transform: rotate(-10deg) scale(1.08); }

.top nav {
  position: absolute; left: 50%; transform: translateX(-50%);
  display: flex; gap: 4px; padding: 5px;
  background: var(--wash); border-radius: 999px;
}
.top nav a {
  text-decoration: none; color: var(--ink-soft);
  font-size: .88rem; font-weight: 600;
  padding: 8px 17px; border-radius: 999px;
  transition: background .25s var(--ease), color .25s var(--ease);
}
.top nav a:hover { color: var(--ink); }
.top nav a.on { background: var(--surface); color: var(--ink); box-shadow: 0 2px 6px rgba(70,50,20,.09); }

.btn-add {
  margin-left: auto; border: 0; cursor: pointer; font-family: inherit;
  background: var(--ink); color: #fff; font-weight: 600; font-size: .86rem;
  padding: 12px 20px; border-radius: 999px;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
  box-shadow: 0 5px 14px -4px rgba(38,33,46,.5);
}
.btn-add:hover { transform: translateY(-2px); box-shadow: 0 10px 20px -6px rgba(38,33,46,.55); }
.btn-add:active { transform: translateY(1px); }

/* ------------------------------------------------------------
   Hero — pill, two-tone headline, one line, two buttons
   ------------------------------------------------------------ */
.hero { padding: 52px 0 20px; text-align: center; }
.badge {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: .82rem; font-weight: 600; color: var(--ink-soft);
  background: var(--surface); border: 1px solid var(--hair);
  padding: 8px 17px; border-radius: 999px; margin-bottom: 26px;
  box-shadow: 0 2px 8px rgba(70,50,20,.06);
}
.badge i { width: 7px; height: 7px; border-radius: 50%; background: var(--papers); animation: blip 2.4s infinite; }
.badge b { font-weight: 800; color: var(--ink); }
@keyframes blip { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.hero h1 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.35rem, 7.4vw, 5.4rem);
  line-height: .96; letter-spacing: var(--track-hero);
  margin: 0 0 22px;
}
.hero h1 span { display: block; text-wrap: balance; }
/* The hero is clamp()ed from 37.6px to 86.4px, so its tracking has to move
   with it: below ~650px it drops out of the 48px+ band and needs one step
   looser, or it reads cramped on a phone. */
@media (max-width: 650px) {
  .hero h1 { letter-spacing: var(--track-xl); }
}
.h-muted { color: #b9b2ab; }
.h-solid { color: var(--ink); }

.hero-sub { font-size: 1.08rem; color: var(--ink-soft); margin: 0 auto 30px; max-width: 52ch; line-height: 1.5; }

.cta-row { display: flex; gap: 14px; justify-content: center; align-items: center; flex-wrap: wrap; }
.cta-solid {
  display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  background: linear-gradient(180deg, #FA9A0A 0%, #F28700 100%);
  color: #fff; font-weight: 700; font-size: 1rem;
  padding: 16px 30px; border-radius: 999px;
  box-shadow: 0 10px 22px -6px rgba(242, 135, 0, .55), inset 0 1px 0 rgba(255,255,255,.4);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
.cta-solid:hover { transform: translateY(-3px); box-shadow: 0 16px 30px -8px rgba(242, 135, 0, .6), inset 0 1px 0 rgba(255,255,255,.4); }
.cta-solid:active { transform: translateY(1px); }
.cta-ghost {
  display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  color: var(--ink); font-weight: 700; font-size: 1rem;
  padding: 16px 26px; border-radius: 999px;
  background: var(--surface); border: 1.5px solid var(--hair);
  transition: transform .18s var(--ease), border-color .2s;
}
.cta-ghost:hover { transform: translateY(-3px); border-color: var(--ink); }
.cta-ghost svg, .cta-solid svg { transition: transform .3s var(--pop); }
.cta-ghost:hover svg { transform: translateX(4px); }

/* ------------------------------------------------------------
   Hero stage — one big folder, two cards floating over it
   ------------------------------------------------------------ */
.stage { position: relative; margin-top: 52px; padding-bottom: 40px; min-height: 330px; }

/* the hero folder and floating cards were replaced by the fan (see below) */
/* ------------------------------------------------------------
   Filters — same segment-track as the hero nav, centred.
   One track, one raised chip, so the whole site speaks once.
   ------------------------------------------------------------ */
.controls { padding: 26px 0 30px; text-align: center; }

/* the search field borrows the hero badge's shape and shadow */
.search {
  display: flex; align-items: center; gap: 12px;
  max-width: 560px; margin: 0 auto 20px;
  background: var(--surface); border: 1px solid var(--hair);
  border-radius: 999px; padding: 14px 20px 14px 24px;
  box-shadow: 0 2px 8px rgba(70, 50, 20, .06);
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease), transform .22s var(--ease);
}
.search:focus-within {
  border-color: var(--ink);
  transform: translateY(-1px);
  box-shadow: 0 8px 24px -6px rgba(70, 50, 20, .22), 0 0 0 3px var(--wash);
}
.search input { flex: 1; border: 0; outline: 0; font: 500 1rem var(--font-body); color: var(--ink); background: transparent; }
.search input::placeholder { color: var(--muted); }
.search svg { color: var(--muted); flex-shrink: 0; }
.search-kbd {
  display: flex; align-items: center; gap: 3px;
  margin-left: auto; pointer-events: none; flex-shrink: 0;
}
.search-kbd kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 5px;
  font-family: var(--font-mono); font-size: .74rem; font-weight: 500;
  color: var(--muted); background: var(--wash);
  border: 1px solid var(--wash-strong); border-radius: 6px;
}

/* the track — identical construction to .top nav */
.pills {
  display: inline-flex; gap: 4px; padding: 5px;
  background: var(--wash);
  border-radius: 999px;
  max-width: 100%; overflow-x: auto;
  scrollbar-width: none;
}
.pills::-webkit-scrollbar { display: none; }

.pill {
  cursor: pointer; font-family: inherit; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 8px;
  font-size: .88rem; font-weight: 600;
  padding: 8px 17px; border-radius: 999px;
  background: transparent; border: 0; color: var(--ink-soft);
  transition: background .25s var(--ease), color .25s var(--ease), box-shadow .25s var(--ease);
}
.pill i { width: 8px; height: 8px; border-radius: 50%; background: currentColor; transition: transform .3s var(--pop); }
.pill:hover { color: var(--ink); }
/* the raised chip — the same white lift the nav uses */
.pill.on {
  background: var(--surface);
  box-shadow: 0 2px 6px rgba(70, 50, 20, .09);
  font-weight: 700;
}
.pill.on i { transform: scale(1.25); }
.pill[data-kind="all"].on        { color: var(--ink); }
.pill[data-kind="papers"].on     { color: var(--papers-ink); }
.pill[data-kind="notes"].on      { color: var(--notes-ink); }
.pill[data-kind="assignment"].on { color: var(--assignment-ink); }
.pill[data-kind="reference"].on  { color: var(--reference-ink); }

/* only speaks when a filter returns nothing — otherwise it takes no space */
.count { font: 500 .82rem var(--font-mono); color: var(--muted); margin: 18px 0 0; }
.count:empty { display: none; }

/* ------------------------------------------------------------
   Folder cards
   Three real layers: .fc-back (the folder), the sheets in the
   middle, .fc-front (the pocket flap) on top. On hover the sheets
   spring out and the flap sinks — opposing motion is what sells it.
   Each resource kind gets its own way of opening.
   ------------------------------------------------------------ */
/* Fixed-width tiles, left-aligned, and the last row is allowed to end
   ragged. A `1fr` track would stretch the cards to fill the row, which
   makes a card a different size at every viewport width and pads a short
   last row out to nothing. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 30px 26px;
  padding: 22px 0 var(--section-y);
}

.fcard {
  position: relative;
  height: 220px;
  cursor: pointer;
  user-select: none;
  border-radius: 28px 48px 28px 28px;
  will-change: transform, opacity, filter;
  transition: transform .38s cubic-bezier(0.16, 1, 0.3, 1), box-shadow .38s cubic-bezier(0.16, 1, 0.3, 1);
}
.fcard.reveal-card {
  opacity: 0;
  transform: scale(0.92) translateY(24px);
  filter: blur(4px);
  transition: transform var(--dur-arrive) var(--ease-out-expo),
              opacity var(--dur-arrive) var(--ease-out-expo),
              filter var(--dur-arrive) var(--ease-out-expo),
              box-shadow .38s var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}
.fcard.reveal-card.in {
  opacity: 1;
  transform: scale(1) translateY(0);
  filter: blur(0px);
}
.fcard:hover, .fcard:focus-visible {
  transform: translateY(-6px) scale(1.018);
  box-shadow: 0 20px 38px -12px rgba(50, 35, 10, .22), 0 4px 10px rgba(0, 0, 0, .04);
}

/* layer 1 — the folder itself */
.fc-back {
  position: absolute; inset: 0; z-index: 1;
  border-radius: 28px 48px 28px 28px;
  background: var(--back);
}

/* layer 2 — the paper inside; these carry the real file names */
.fc-sheet {
  position: absolute; z-index: 2;
  background: #fff;
  border-radius: 14px;
  padding: 9px 14px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .08);
  transition: transform .38s cubic-bezier(.34, 1.56, .64, 1);
}
.fc-sheet b {
  display: block; font-size: .84rem; font-weight: 700; color: var(--ink);
  line-height: 1.25; letter-spacing: var(--track-xs); margin-bottom: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* marker and year share one row, which buys the room the ruled lines need */
.sh-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.fc-sheet small { font: 500 .68rem var(--font-mono); color: var(--muted); }
.fc-sheet i {
  display: block; width: 22px; height: 4px; border-radius: 2px;
  background: var(--dot); flex-shrink: 0;
}

/* the page should read as written-on, not blank: ruled lines standing in for
   body text. Two show at rest; the rest arrive as the sheets spring out. */
.fc-rule { display: flex; flex-direction: column; gap: 4px; }
.fc-rule span { height: 3.5px; border-radius: 2px; background: rgba(38, 33, 46, .13); }
.fc-rule span:nth-child(2) { width: 92%; }
.fc-rule span:nth-child(3) { width: 74%; }
.fc-rule span:nth-child(4) { width: 88%; }
.fc-rule span:nth-child(5) { width: 56%; }

/* layer 3 — the pocket flap; it carries the card's name */
.fc-front {
  position: absolute; bottom: 0; left: 0; right: 0; z-index: 3;
  height: 132px;
  border-radius: 28px;
  padding: 22px;
  display: flex; justify-content: space-between; align-items: flex-end;
  color: #fff;
  background: var(--front);
  box-shadow: 0 12px 24px -6px var(--glow);
  transition: transform .35s ease;
}
.fcard:hover .fc-front { transform: translateY(4px); }

/* identity on the left of the flap, count on the right — the two children
   .fc-front was always laid out for. */
.fc-id { min-width: 0; }
.fc-meta {
  font: 500 .7rem var(--font-mono);
  opacity: .85; margin-bottom: 5px; letter-spacing: .06em;
}
.fc-title {
  font-family: var(--font-course); font-size: 16.5px; font-weight: 700;
  line-height: 1.22; letter-spacing: var(--track-sm);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.fc-stat { font-size: 26px; font-weight: 800; line-height: 1; flex-shrink: 0; text-align: right; padding-left: 12px; }
.fc-stat span { display: block; font-size: 10px; font-weight: 600; opacity: .8; letter-spacing: .05em; text-transform: uppercase; margin-top: 3px; }
.fc-open {
  margin-top: 9px; font-size: 10px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; opacity: .82;
}
.fc-open span { display: inline-block; transition: transform .3s var(--pop); }
.fcard:hover .fc-open span { transform: translateX(3px); }

/* the file count rides the card as a little stuck-on note */
.sticky {
  position: absolute; top: 12px; right: 12px; z-index: 5;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 42px; padding: 7px 9px 6px;
  border-radius: 4px 4px 6px 6px;
  background: linear-gradient(158deg, #ffe873 0%, #ffd43b 62%, #f5c518 100%);
  box-shadow: 0 5px 12px -4px rgba(80, 60, 0, .45);
  transform: rotate(-4deg);
  transition: transform .35s var(--pop);
}
.sticky b { font-size: 1.24rem; font-weight: 800; color: #4d3a00; line-height: 1; }
.sticky span { margin-top: 2px; font-size: .5rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: #8a6a10; }
/* the strip of tape across the top */
.sticky::before {
  content: ""; position: absolute; top: -5px; left: 50%; transform: translateX(-50%);
  width: 22px; height: 10px; border-radius: 2px;
  background: rgba(255, 255, 255, .55);
}
/* the turned-up bottom corner */
.sticky::after {
  content: ""; position: absolute; right: 0; bottom: 0;
  width: 10px; height: 10px;
  background: linear-gradient(135deg, rgba(0, 0, 0, .14), transparent 60%);
  border-radius: 0 0 6px 0;
}
.fcard:hover .sticky { transform: rotate(3deg) scale(1.06); }
.grid .fcard:hover .sticky { transform: scale(1.07); }

.grid .sticky {
  top: 10px; right: 10px;
  flex-direction: row; align-items: baseline; gap: 4px;
  min-width: 0; padding: 5px 9px;
  transform: none;
}
.grid .sticky b { font-size: .82rem; }
.grid .sticky span { margin-top: 0; font-size: .48rem; letter-spacing: .07em; }
.grid .sticky::before { width: 18px; height: 8px; top: -4px; }
.grid .sticky::after { width: 8px; height: 8px; }


/* =========================================================
   PAST PAPERS — the lift.
   One stack of sheets rises straight out of the pocket.
   ========================================================= */
.t-papers {
  --back: #DC7A00;
  --front: linear-gradient(180deg, #FA9A0A 0%, #F28700 100%);
  --glow: rgba(242, 135, 0, .4);
  --dot: #F28700;
}
.t-papers .fc-sheet { top: 22px; left: 20px; right: 20px; height: 132px; }
.t-papers .s2 { top: 16px; left: 27px; right: 27px; z-index: 1; opacity: .72; }
.t-papers .s3 { top: 10px; left: 34px; right: 34px; z-index: 0; opacity: .5; }
.t-papers.one .fc-sheet { top: 26px; }
.t-papers:hover .s1 { transform: translateY(-38px); }
.t-papers:hover .s2 { transform: translateY(-52px); }
.t-papers:hover .s3 { transform: translateY(-64px); }

/* =========================================================
   NOTES & SLIDES — the angular cutout (Folder 4).
   The front panel is clipped with a diagonal notch at the
   top right; the pages sit in that notch and slide out
   diagonally on hover.
   ========================================================= */
.t-notes {
  /* The back must be clearly darker than the front: the notch in .fc-front
     cuts a hole, and what shows through it IS the inside of the folder. Same
     lightness on both layers and the card reads as a flat rectangle. */
  --back: linear-gradient(135deg, #435E1F 0%, #2F4315 100%);
  --front: linear-gradient(180deg, #7A9C3D 0%, #597C2B 100%);
  --glow: rgba(89, 124, 43, .42);
  --dot: #698B39;
}
.t-notes .fc-mid { display: none; }
.t-notes .fc-back { border-radius: 28px; }

/* the pages, tucked into the notch */
.t-notes .fc-sheet {
  left: auto; height: 108px; width: 52%;
  border-radius: 13px; padding: 11px 12px 11px 14px;
  background: #fff;
  box-shadow: 0 5px 13px -6px rgba(58, 68, 30, .45);
  transition: transform .42s cubic-bezier(.34, 1.5, .64, 1);
}
.t-notes .fc-sheet i { display: none; }
.t-notes .s1 { top: 13px; right: 13px; z-index: 3; }
.t-notes .s2 { top: 23px; right: 27px; width: 49%; z-index: 2; opacity: .8; }
.t-notes .s3 { display: none; }
.t-notes:hover .s1 { transform: translate(7px, -31px) rotate(4.5deg); }
.t-notes:hover .s2 { transform: translate(-11px, -39px) rotate(-6.5deg); }
.t-notes.one .s1 { top: 16px; right: 18px; }

/* the clipped front */
.t-notes .fc-front {
  top: 0; height: auto; z-index: 4;
  border-radius: 28px;
  clip-path: polygon(0 0, 33% 0, 46% 38%, 100% 38%, 100% 100%, 0 100%);
  box-shadow: 0 14px 26px -10px var(--glow);
  transition: transform .35s ease;
}
.t-notes:hover .fc-front { transform: translateY(3px); }

/* =========================================================
   ASSIGNMENTS — the frosted reveal.
   The flap is glass; the paper blurs through it before it rises.
   ========================================================= */
.t-assignment {
  --back: linear-gradient(135deg, #E16331 0%, #BB310D 100%);
  --front: rgba(255, 255, 255, .22);
  --glow: rgba(187, 49, 13, .32);
  --dot: #D04724;
}
.t-assignment .fc-front {
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, .35);
  transition: transform .35s ease, background .3s ease;
}
.t-assignment:hover .fc-front { background: rgba(255, 255, 255, .3); }
.t-assignment .fc-sheet { top: 24px; left: 26px; right: 26px; height: 124px; }
.t-assignment .s2 { top: 17px; left: 34px; right: 34px; z-index: 1; opacity: .7; }
.t-assignment .s3 { display: none; }
.t-assignment .fc-sheet { transition: transform .35s cubic-bezier(.34, 1.45, .64, 1); }
.t-assignment:hover .s1 { transform: translateY(-40px); }
.t-assignment:hover .s2 { transform: translateY(-54px); }

/* =========================================================
   REFERENCE BOOKS — the stepped stack.
   Tiers rise by different amounts, like books pulled off a shelf.
   ========================================================= */
.t-reference {
  --back: transparent;
  --front: #492E55;
  --glow: rgba(73, 46, 85, .45);
  --dot: #8C6597;
}
.t-reference .fc-back { display: none; }
.fc-tier {
  position: absolute; z-index: 2;
  border-radius: 24px 24px 0 0;
  transition: transform .35s cubic-bezier(.34, 1.4, .64, 1);
  padding: 13px 20px 0;
  color: #fff;
  font-size: .78rem; font-weight: 700;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.fc-tier small { display: block; font: 500 .64rem var(--font-mono); opacity: .78; margin-top: 2px; }
.t3 { top: 0;  height: 86px; width: 80%;  left: 10%; background: #cdb8d6; color: #492E55; }
.t2 { top: 12px; height: 86px; width: 90%; left: 5%;  background: #a585b5; }
.t1 { top: 24px; height: 86px; width: 100%; left: 0;  background: #6e4f80; }
.t-reference:hover .t3 { transform: translateY(-26px); }
.t-reference:hover .t2 { transform: translateY(-15px); }
.t-reference:hover .t1 { transform: translateY(-6px); }
.t-reference .fc-front { height: 140px; border-radius: 26px; }
/* ------------------------------------------------------------
   List view — the same folders, same order, no preview. One row
   each, aligned on a shared column grid so the eye can run down
   any single field.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   Small screens
   ------------------------------------------------------------ */
@media (max-width: 620px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
}

@media (max-width: 720px) {
  .wrap { padding: 0 18px; }
  .top nav { display: none; }
  .top-in { gap: 12px; }
  .logo { margin-right: auto; }
  .btn-add { white-space: nowrap; padding: 10px 15px; font-size: .82rem; }
  .hero { padding: 48px 0 30px; }
  .hero h1 { max-width: none; }
  .hero p { font-size: .98rem; }
  .hero-stats { gap: 24px; }
  .confetti { display: none; }
  .pills { gap: 3px; padding: 4px; }
  .pill { font-size: .8rem; padding: 8px 13px; }
  .search { padding: 13px 18px; }
  body { padding: 8px; }
  .shell { border-radius: 22px; }
  .top-in { height: 64px; }
  .hero { padding: 34px 0 16px; }
  .stage { margin-top: 36px; min-height: 0; }
  .cta-row { flex-direction: column; align-items: stretch; }
  .cta-solid, .cta-ghost { justify-content: center; }
}

/* ------------------------------------------------------------
   The reference shelf — books stand up, you pull one out.
   ------------------------------------------------------------ */
.library { background: #f6efe2; border-radius: 30px; margin: 8px 0 0; padding: 46px 0 8px; }
.lib-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 30px; }
.lib-head h2 { font-family: var(--font-display); font-size: 1.9rem; font-weight: 800; letter-spacing: var(--track-xl); line-height: 1.02; margin: 0 0 5px; }
.lib-head p { margin: 0; color: var(--ink-soft); font-size: .92rem; }
.lib-hint { font: 500 .74rem var(--font-mono); color: var(--muted); white-space: nowrap; }

.shelf { position: relative; padding-bottom: 44px; }
.shelf-row {
  display: flex; gap: 30px; align-items: flex-end;
  overflow-x: auto; padding: 26px 4px 0;   /* no bottom pad — the books rest on the plank */
  scrollbar-width: none;
}
.shelf-row::-webkit-scrollbar { display: none; }
/* the plank: its top edge is exactly where the books end */
.shelf::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 39px; height: 5px;
  border-radius: 99px; background: #e2d5bd;
  box-shadow: 0 10px 22px -8px rgba(90, 66, 24, .45);
}

.book {
  position: relative; display: block; flex: 0 0 auto;
  width: 132px; aspect-ratio: 2 / 3;
  border: 0; padding: 0; cursor: pointer; font-family: inherit; text-align: left;
  border-radius: 3px 9px 9px 3px;
  background: linear-gradient(135deg, var(--c1), var(--c2));
  color: var(--c-ink);
  box-shadow: 6px 10px 16px -12px rgba(50, 35, 10, .75);
  transition: transform .42s cubic-bezier(.34, 1.5, .64, 1), box-shadow .42s var(--ease);
  transform-origin: bottom center;
}
/* pulled straight off the shelf towards the reader — no tilt */
.book:hover, .book:focus-visible {
  transform: translateY(-16px) scale(1.045);
  box-shadow: 8px 26px 32px -18px rgba(50, 35, 10, .6);
  outline: none;
}
.book:hover .pages, .book:focus-visible .pages { right: -5px; }
.book:focus-visible { box-shadow: 0 32px 42px -16px rgba(50,35,10,.5), 0 0 0 3px var(--ink); }

/* spine on the left, page block on the right */
.book .spine {
  position: absolute; left: 0; top: 0; bottom: 0; width: 11px;
  background: linear-gradient(90deg, rgba(0,0,0,.3), rgba(0,0,0,.04));
  border-radius: 3px 0 0 3px;
}
.book .pages {
  position: absolute; right: -3px; transition: right .42s var(--ease); top: 5px; bottom: 5px; width: 5px;
  border-radius: 0 3px 3px 0;
  background: repeating-linear-gradient(180deg, #fdfaf3 0 2px, #ded7c8 2px 3px);
}
.book .cover-in { position: absolute; inset: 0; padding: 20px 15px 16px 21px; display: flex; flex-direction: column; }
.book .b-title { font-family: var(--font-course); font-size: .92rem; font-weight: 800; line-height: 1.18; letter-spacing: var(--track-xs); }
.book .b-author { margin-top: auto; font-size: .62rem; font-weight: 700; opacity: .8; letter-spacing: .04em; text-transform: uppercase; }
.book .b-rule { width: 26px; height: 3px; border-radius: 2px; background: currentColor; opacity: .55; margin: 9px 0 0; }

/* cover palettes */
.c-ink     { --c1: #3b3446; --c2: #221d2b; --c-ink: #fff; }
.c-amber   { --c1: #FA9A0A; --c2: #E27D00; --c-ink: #412100; }
.c-crimson { --c1: #E16331; --c2: #b04327; --c-ink: #fff; }
.c-mint    { --c1: #8ca860; --c2: #526e35; --c-ink: #fff; }
.c-violet  { --c1: #a585b5; --c2: #6b4c7d; --c-ink: #fff; }
.c-sky     { --c1: #8aa8b8; --c2: #4c6b7d; --c-ink: #fff; }

/* ------------------------------------------------------------
   Book detail — the cover flies from the shelf into the panel
   ------------------------------------------------------------ */
.modal { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 24px; overflow-y: auto; }
.modal[hidden] { display: none; }
.modal-back {
  position: absolute; inset: 0;
  background: rgba(38, 33, 46, .48); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  opacity: 0; transition: opacity .35s var(--ease);
}
.modal.open .modal-back { opacity: 1; }

/* Course Folder Modal */
.folder-modal-card {
  position: relative; width: min(720px, 100%);
  background: var(--surface); border-radius: 28px;
  padding: 34px 32px 26px;
  box-shadow: 0 40px 90px -25px rgba(50, 35, 10, .5);
  max-height: calc(100vh - 56px);
  display: flex; flex-direction: column;
  opacity: 0; transform: translateY(22px) scale(.96);
  transition: opacity .32s var(--ease), transform .42s var(--pop);
}
.modal.open .folder-modal-card { opacity: 1; transform: none; }
.fm-header { margin-bottom: 20px; }
.fm-meta-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.fm-badge-dept {
  font: 500 .74rem var(--font-mono); text-transform: uppercase; letter-spacing: .06em;
  padding: 5px 12px; border-radius: 999px; background: var(--brand-soft); color: var(--brand);
}
.fm-badge-code {
  font: 500 .74rem var(--font-mono); color: var(--ink-soft); background: var(--wash);
  letter-spacing: .06em;
  padding: 5px 12px; border-radius: 999px;
}
.fm-title {
  font-family: var(--font-course); font-size: 1.72rem; font-weight: 700; letter-spacing: var(--track-md);
  line-height: 1.05; margin: 0 0 6px;
}
.fm-sub { color: var(--ink-soft); font-size: .92rem; margin: 0 0 18px; }
.fm-tabs {
  display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none;
  padding-bottom: 6px; border-bottom: 1px solid var(--hair);
}
.fm-tabs::-webkit-scrollbar { display: none; }
.fm-tab {
  border: 0; background: transparent; cursor: pointer; font-family: inherit;
  font-size: .84rem; font-weight: 600; color: var(--ink-soft);
  padding: 8px 15px; border-radius: 999px;
  transition: background .2s, color .2s; white-space: nowrap;
}
.fm-tab:hover { color: var(--ink); background: var(--wash); }
.fm-tab.on { background: var(--ink); color: #fff; }

.fm-body {
  overflow-y: auto; max-height: 380px; padding-right: 4px; margin: 16px 0;
  display: flex; flex-direction: column; gap: 10px;
}
.fm-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px 18px; border-radius: 18px; background: var(--wash); border: 1px solid var(--hair);
  transition: transform .18s var(--ease), border-color .2s, background .2s, box-shadow .2s;
}
.fm-row:hover {
  background: #fff; border-color: rgba(38, 33, 46, .18);
  transform: translateY(-2px); box-shadow: 0 6px 16px -4px rgba(70, 50, 20, .08);
}
.fm-row-left { display: flex; align-items: center; gap: 14px; min-width: 0; }
.fm-type-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.fm-info { min-width: 0; }
.fm-info b { display: block; font-size: .94rem; font-weight: 700; color: var(--ink); text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }
.fm-info span { font-size: .8rem; color: var(--ink-soft); display: flex; gap: 8px; align-items: center; margin-top: 2px; }
.fm-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.btn-dl {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--ink); color: #fff;
  text-decoration: none; font-size: .82rem; font-weight: 700;
  padding: 8px 14px; border-radius: 999px; border: 0; cursor: pointer;
  transition: transform .18s var(--ease), background .2s;
}
.btn-dl:hover { transform: translateY(-1px); background: #3d3549; }
.btn-icon {
  width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid var(--hair); background: var(--surface);
  cursor: pointer; display: grid; place-items: center; color: var(--ink-soft);
  transition: transform .18s var(--ease), color .2s, border-color .2s;
}
.btn-icon:hover { color: var(--ink); border-color: var(--ink); transform: scale(1.08); }
.fm-empty { text-align: center; color: var(--muted); padding: 32px 0; font-size: .92rem; }

.fm-footer {
  padding-top: 14px; border-top: 1px solid var(--hair);
  display: flex; justify-content: flex-end;
}
.btn-share-course {
  display: inline-flex; align-items: center; gap: 8px;
  background: transparent; border: 1.5px dashed var(--hair);
  color: var(--ink-soft); font-family: inherit; font-size: .84rem; font-weight: 600;
  padding: 10px 18px; border-radius: 999px; cursor: pointer;
  transition: border-color .2s, color .2s, background .2s;
}
.btn-share-course:hover { border-color: var(--ink); color: var(--ink); background: var(--wash); }

/* Share Resource Modal */
.share-modal-card {
  position: relative; width: min(560px, 100%);
  background: var(--surface); border-radius: 28px;
  padding: 34px 32px; box-shadow: 0 40px 90px -25px rgba(50, 35, 10, .5);
  opacity: 0; transform: translateY(22px) scale(.96);
  transition: opacity .32s var(--ease), transform .42s var(--pop);
}
.modal.open .share-modal-card { opacity: 1; transform: none; }
.sm-icon {
  width: 50px; height: 50px; border-radius: 16px;
  background: var(--brand-soft); color: var(--brand);
  display: grid; place-items: center; margin-bottom: 16px;
}
.sm-title { font-family: var(--font-display); font-size: 1.6rem; font-weight: 800; letter-spacing: var(--track-lg); line-height: 1.05; margin: 0 0 6px; }
.sm-sub { color: var(--ink-soft); font-size: .92rem; margin: 0 0 20px; }
.sm-dropzone {
  border: 2px dashed rgba(38, 33, 46, .18); border-radius: 20px;
  padding: 26px 20px; text-align: center; background: var(--wash);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  margin-bottom: 20px; transition: border-color .2s, background .2s; cursor: pointer;
}
.sm-dropzone.dragover, .sm-dropzone:hover { border-color: var(--brand); background: var(--brand-soft); }
.sm-dropzone svg { color: var(--brand); margin-bottom: 4px; }
.sm-dropzone b { font-size: .95rem; color: var(--ink); }
.sm-dropzone span { font-size: .8rem; color: var(--muted); margin-bottom: 10px; }
.sm-choose-btn { font-size: .84rem; padding: 10px 22px; cursor: pointer; }

.sm-form { display: flex; flex-direction: column; gap: 14px; }
.sm-field { display: flex; flex-direction: column; gap: 6px; }
.sm-field label { font-size: .78rem; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em; }
.sm-field input, .sm-field select {
  font: 500 .92rem var(--font-body); color: var(--ink); background: var(--wash);
  border: 1px solid var(--hair); border-radius: 12px; padding: 12px 14px; outline: none;
  transition: border-color .2s, box-shadow .2s;
}
.sm-field input:focus, .sm-field select:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(108, 92, 231, .15); background: #fff; }
.sm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.sm-submit-btn { width: 100%; justify-content: center; margin-top: 6px; cursor: pointer; border: 0; font-family: inherit; }

/* Toast Notification */
.toast {
  position: fixed; bottom: 28px; left: 50%;
  transform: translateX(-50%) translateY(24px) scale(0.95);
  background: var(--ink); color: #fff; font-size: .88rem; font-weight: 600;
  padding: 12px 24px; border-radius: 999px;
  box-shadow: 0 14px 34px -8px rgba(38, 33, 46, .45);
  z-index: 400; opacity: 0; pointer-events: none;
  transition: opacity .3s var(--ease), transform .35s var(--pop);
  display: flex; align-items: center; gap: 8px;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }

.modal-card {
  position: relative; width: min(760px, 100%);
  background: var(--surface); border-radius: 28px;
  padding: 32px; display: grid; grid-template-columns: 180px 1fr; gap: 30px;
  perspective: 3000px; perspective-origin: 28% 50%;
  box-shadow: 0 40px 80px -30px rgba(50, 35, 10, .55);
  max-height: calc(100vh - 48px); overflow-y: auto;
  opacity: 0; transform: translateY(22px) scale(.97);
  transition: opacity .34s var(--ease), transform .44s var(--pop);
}
.modal.open .modal-card { opacity: 1; transform: none; }

/* the cover animates independently — FLIP from the shelf position */
.modal-cover { width: 180px; aspect-ratio: 2 / 3; align-self: start; transform-origin: top left; }
.modal-cover .book { width: 100%; cursor: default; }
.modal-cover .book:hover { transform: none; box-shadow: 0 12px 22px -10px rgba(50, 35, 10, .55); }

.modal-close {
  position: absolute; top: 18px; right: 18px;
  width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--hair);
  background: var(--surface); cursor: pointer; color: var(--ink-soft);
  display: grid; place-items: center; font-size: 1.1rem; line-height: 1;
  transition: transform .25s var(--pop), background .2s, color .2s;
}
.modal-close:hover { transform: rotate(90deg); background: var(--ink); color: #fff; }

.m-kind { font: 500 .68rem var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--reference); }
.m-title { font-family: var(--font-course); font-size: 1.72rem; font-weight: 700; letter-spacing: var(--track-md); line-height: 1.05; margin: 9px 0 6px; }
.m-author { font-size: .95rem; font-weight: 600; color: var(--ink-soft); margin: 0 0 20px; }
.m-gist { font-size: .95rem; line-height: 1.6; color: var(--ink-soft); margin: 0 0 22px; }
.m-facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 24px; }
.m-facts div { background: #f7f1e6; border-radius: 14px; padding: 12px 14px; }
.m-facts b { display: block; font-size: .95rem; font-weight: 800; letter-spacing: var(--track-xs); }
.m-facts span { font: 500 .64rem var(--font-mono); color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.m-cta { display: flex; gap: 10px; flex-wrap: wrap; }

@media (max-width: 620px) {
  .modal-card { grid-template-columns: 1fr; padding: 24px; gap: 20px; }
  .modal-cover { width: 132px; }
  .m-facts { grid-template-columns: 1fr 1fr; }
  .lib-head { display: block; }
  .lib-hint { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .book, .modal-card, .modal-back, .modal-cover { transition-duration: .01ms !important; }
}

/* ------------------------------------------------------------
   The panel opens like a book.
   The flap is a second copy of the cover lying over the detail
   page. It hinges on the spine and swings left; the page behind
   it lifts in as it goes.
   ------------------------------------------------------------ */
.modal-card { transform-style: preserve-3d; }

.modal-page { position: relative; }
.flap {
  position: absolute; z-index: 5;
  inset: 0;
  border-radius: 2px 12px 12px 2px;
  transform-origin: left center;
  transform: rotateY(0deg);
  transform-style: preserve-3d;
  /* a leaf of paper, not a second cover — the cover is already
     standing on the left, so this is the page that turns */
  background: linear-gradient(96deg, #f0e7d7 0%, #fdfaf3 14%, #fffdf8 100%);
  box-shadow: -10px 0 26px -14px rgba(40, 28, 8, .55), inset 9px 0 14px -12px rgba(70, 50, 18, .5);
  transition: transform .82s cubic-bezier(.58, .04, .18, 1), opacity .26s ease .5s;
  pointer-events: none;
  backface-visibility: hidden;
}
/* the reverse of the leaf, seen once it turns past edge-on */
.flap::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 2px 12px 12px 2px;
  background: linear-gradient(96deg, #fffdf8, #f2ead9);
  box-shadow: inset -9px 0 14px -12px rgba(70, 50, 18, .45);
  transform: rotateY(180deg);
  backface-visibility: hidden;
}
/* faint ruled body, so the leaf reads as a printed page in motion */
.flap::before {
  content: ""; position: absolute; inset: 30px 26px auto 26px; height: 62%;
  background: repeating-linear-gradient(180deg, rgba(70, 50, 18, .09) 0 1px, transparent 1px 15px);
}
.modal.opened .flap { transform: rotateY(-124deg); opacity: 0; }

/* the detail page rises in behind the turning cover */
#modalBody { opacity: 0; transform: translateY(14px); transition: opacity .5s ease .3s, transform .6s var(--ease) .3s; }
.modal.opened #modalBody { opacity: 1; transform: none; }
/* the spine edge of the right-hand page */
#modalBody::before {
  content: ""; position: absolute; left: -20px; top: 0; bottom: 0; width: 14px;
  border-radius: 8px;
  background: linear-gradient(90deg, rgba(60, 42, 14, .12), transparent);
  pointer-events: none;
}

@media (max-width: 620px) {
  #modalBody::before { display: none; }
}

/* reference folders open the book, so say so */
.t-reference { cursor: pointer; }

/* ------------------------------------------------------------
   The library page
   ------------------------------------------------------------ */
.lib-hero { padding-bottom: 10px; }
.lib-hero .search { margin-top: 34px; }
.lib-hero .pills { margin-top: 4px; }

.shelf-block { margin-bottom: 44px; animation: rise .55s var(--ease) both; animation-delay: var(--d, 0ms); }
.shelf-label { display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px; }
.shelf-label h2 { font-family: var(--font-course); font-size: 1.2rem; font-weight: 700; letter-spacing: var(--track-sm); margin: 0; }
.shelf-label span { font: 500 .72rem var(--font-mono); color: var(--muted); }
.lib-empty { text-align: center; color: var(--muted); padding: 60px 0 90px; font-size: .95rem; }
main > #shelves { padding-top: 34px; padding-bottom: var(--section-y); }

.lib-all { text-decoration: none; color: var(--ink); border-bottom: 2px solid var(--papers); padding-bottom: 2px; transition: color .2s, border-color .2s; }
.lib-all:hover { color: var(--papers-ink); border-color: var(--ink); }

/* ------------------------------------------------------------
   Scroll polish — sections settle in as they come into view.
   IntersectionObserver adds .in; the sections start slightly
   low and blurred and land on a long, soft curve.
   ------------------------------------------------------------ */
.reveal {
  opacity: 0;
  transform: translateY(34px);
  filter: blur(6px);
  transition:
    opacity .9s cubic-bezier(.22, .61, .36, 1),
    transform 1.05s cubic-bezier(.22, .61, .36, 1),
    filter .9s cubic-bezier(.22, .61, .36, 1);
  transition-delay: var(--rd, 0ms);
  will-change: opacity, transform;
}
.reveal.in { opacity: 1; transform: none; filter: none; }

/* children of a revealed block come in one after another */
.reveal-group > * { opacity: 0; transform: translateY(22px); transition: opacity .7s var(--ease), transform .8s cubic-bezier(.22,.61,.36,1); }
.reveal-group.in > * { opacity: 1; transform: none; }
.reveal-group.in > *:nth-child(1) { transition-delay: .04s; }
.reveal-group.in > *:nth-child(2) { transition-delay: .10s; }
.reveal-group.in > *:nth-child(3) { transition-delay: .16s; }
.reveal-group.in > *:nth-child(4) { transition-delay: .22s; }
.reveal-group.in > *:nth-child(5) { transition-delay: .28s; }
.reveal-group.in > *:nth-child(6) { transition-delay: .34s; }

/* Native scroll-linked polish where the browser supports it.
   The (animation-range: entry) test is required: some engines ship
   animation-timeline without ranges, and would run this wrong. */
@supports ((animation-timeline: view()) and (animation-range: entry)) {
  @media (prefers-reduced-motion: no-preference) {
    .book {
      animation: bookArrive linear both;
      animation-timeline: view(inline);
      animation-range: entry 0% entry 40%;
    }
    @keyframes bookArrive { from { opacity: 0; transform: translateY(26px); } }
  }
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal-group > * { opacity: 1 !important; transform: none !important; filter: none !important; }
  html { scroll-behavior: auto; }
}


@keyframes fanDeal {
  /* no `to` — it interpolates to the slot's own resting transform, which is
     what lets the hover transition take over cleanly once the deal is done */
  from { opacity: 0; transform: translate(0, 62px) rotate(0deg) scale(.82); }
}


/* a page marker tucked into the top corner */


/* the coloured foot, with a wave where it meets the paper */
/* No overlay here. The wave is a separate SVG filled with the same flat
   colour, and any gradient on the foot alone shows up as a hard seam where
   the two meet. Flat colour is what makes them read as one shape. */

/* the card at the front of the fan is the one in full colour */





/* ------------------------------------------------------------
   Footer — the sign-off.
   Menus and fine print sit on a hairline grid; the wordmark
   below is set as large as the sheet allows and dissolves into
   the paper, cropped by the shell's own rounded corner.
   ------------------------------------------------------------ */
/* No rule above the footer. Supaste can drop its divider because the ground
   changes colour; here the sheet is continuous, so the separation is carried
   by space instead — which is why the gap above is large. */
.foot { margin-top: 130px; padding-top: 0; padding-bottom: 6px; }

.foot-top {
  display: grid;
  /* link columns size to their content, so the gutters between them are
     equal instead of the columns being equal and the gutters ragged. */
  grid-template-columns: minmax(0, 1fr) repeat(3, max-content);
  gap: 40px 56px;
  align-items: start;
}

/* --- the brand column --- */
.foot-brand { max-width: 36ch; }
.foot-mark {
  display: inline-flex; align-items: center; gap: 12px;
  font-family: var(--font-display); font-weight: 800;
  font-size: 1.32rem; letter-spacing: var(--track-md);
  text-decoration: none; color: var(--ink);
}
.foot-mark img { width: 42px; height: 42px; display: block; object-fit: contain; }
.foot-blurb { color: var(--ink-soft); font-size: .88rem; line-height: 1.55; margin: 16px 0 0; }

/* --- the link columns --- */
.foot-col h3 {
  font: 500 .66rem var(--font-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); margin: 4px 0 16px;
}
.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.foot-col a {
  text-decoration: none; color: var(--ink-soft);
  font-size: .89rem; font-weight: 600;
  display: inline-block;
  transition: color .2s var(--ease), transform .2s var(--ease);
}
.foot-col a:hover { color: var(--ink); transform: translateX(3px); }

/* --- the fine print --- */
/* byline + copyright now live under the blurb, closing the gap the
   brand column used to leave. */
.foot-fine {
  display: grid; gap: 11px; justify-items: start;
  margin-top: 24px;
  font: 400 .82rem var(--font-body); color: var(--muted);
}
.foot-fine b { font-weight: 600; color: var(--ink); }
.foot-heart { font-size: .86em; line-height: 1; }

/* the byline — a face makes it read as a person, not a credit line */
.foot-by { display: inline-flex; align-items: center; gap: 8px; }
.foot-person {
  display: inline-flex; align-items: center; gap: 7px;
  text-decoration: none; color: var(--ink-soft);
}
.foot-person img {
  width: 22px; height: 22px; border-radius: 50%; object-fit: cover;
  display: block; border: 1px solid var(--hair); background: var(--surface);
}
.foot-person b {
  font-weight: 500; color: var(--ink);
  border-bottom: 1px solid transparent; transition: border-color .2s var(--ease);
}
.foot-person:hover b { border-bottom-color: var(--ink); }

/* --- the oversized wordmark --- */
.foot-word-wrap { container-type: inline-size; }
.foot-word {
  margin: 124px 0 0;
  font-family: var(--font-display); font-weight: 800;
  /* "Abhyas" in Bricolage 800 at -.055em measures 3.064em wide, so
     100/3.064 = 32.6cqi sets the word to exactly fill the content
     column — it stays locked to .wrap at every viewport. */
  font-size: min(28.4vw, 22rem);   /* fallback: no container units */
  line-height: .8; letter-spacing: -.055em;   /* below --track-hero: the wordmark is set larger than any real heading */
  /* Bricolage carries an optical-size axis, and `font-optical-sizing: auto`
     picks a WIDER cut at smaller sizes — which breaks the fixed advance
     ratio the cqi sizing depends on. Pin the display cut at every size. */
  font-optical-sizing: none;
  font-variation-settings: "opsz" 96, "wght" 800;
  text-align: center; user-select: none;
  /* decorative only: at this size the glyph inline box overflows its line
     box by ~73px and was intercepting clicks on the byline above it. */
  pointer-events: none;
  background: linear-gradient(180deg, #DCCCB0 0%, #EFE4D2 58%, rgba(253, 248, 239, 0) 95%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  /* pull the baseline toward the sheet edge without clipping the y */
  margin-bottom: -.035em;
}

@supports (font-size: 1cqi) {
  /* 32.6cqi fills the column exactly, but then curved terminals (the final
     "s" especially) overshoot the background-clip box and get sliced.
     31.4cqi leaves ~2% of slack each side so every letter closes cleanly. */
  .foot-word { font-size: 31.4cqi; }
}

@media (max-width: 900px) {
  .foot-top { grid-template-columns: 1fr 1fr; gap: 36px 28px; }
  .foot-brand { grid-column: 1 / -1; max-width: none; }
}
@media (max-width: 560px) {
  .foot { margin-top: 84px; }
  .foot-word { margin-top: 76px; }
  .foot-top { grid-template-columns: 1fr; gap: 30px; }
  /* tracking stays at -.055em here: the cqi sizing is derived from that
     exact advance width, so loosening it overflows the column. */
}

/* ============================================================
   MOTION — scroll-linked arrival.

   Two paths, never both:
   · Chrome / Edge / Safari get a real scroll-driven animation, so a
     card's arrival is tied to scroll position and reverses if you
     scroll back up. This runs off the compositor.
   · Firefox has no scroll-driven animation support, so it keeps the
     IntersectionObserver one-shot defined further up. app.js skips
     the observer entirely when the native path is available.

   Only opacity and transform are animated — both compositor-friendly.
   ============================================================ */
@supports ((animation-timeline: view()) and (animation-range: entry)) {
  @media (prefers-reduced-motion: no-preference) {

    /* hand control to the scroll timeline: clear the observer's base state */
    .fcard.reveal-card,
    .rel-track {
      opacity: 1;
      transform: none;
      filter: none;
      transition: none;
    }

    @keyframes arrive {
      from { opacity: 0; transform: translateY(30px) scale(.965); }
      to   { opacity: 1; transform: translateY(0)   scale(1); }
    }

    .fcard.reveal-card {
      animation: arrive linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 26%;
      will-change: opacity, transform;
    }

    /* a light cascade across each row, so a row lands as a wave
       rather than four cards snapping together */
    .grid > .fcard:nth-child(4n + 2) { animation-range: entry 4% cover 29%; }
    .grid > .fcard:nth-child(4n + 3) { animation-range: entry 8% cover 32%; }
    .grid > .fcard:nth-child(4n + 4) { animation-range: entry 12% cover 35%; }

    .rel-track {
      animation: arrive linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 24%;
      will-change: opacity, transform;
    }

    /* The rail draws itself across the whole time the timeline is on
       screen. `cover` is used rather than `contain`: the track is often
       shorter than the viewport, and `contain` collapses to a degenerate
       range in that case and never runs. */
    /* The rail is driven from releases.js, not a view() timeline. Its
       subject is position:absolute, and an absolutely-positioned subject
       whose containing block is not the scroll container leaves the
       ViewTimeline inactive — currentTime stays null even with the element
       fully on screen. A short rAF-throttled scroll handler is exact and
       costs one element. Everything else on the site stays CSS-driven. */

  }
}

/* ------------------------------------------------------------
   Releases — three folders, one per status.

   Same construction as the archive cards: a coloured folder body
   with the site's asymmetric corner, white sheets sitting inside,
   and the sheets lifting on hover the way the resource sheets do.
   ------------------------------------------------------------ */
.s-building {
  /* --col-* dress the release folders; --k-* dress the version timeline.
     Both map to the same four brand families. */
  --k: var(--papers);    --k-tint: var(--papers-tint);    --k-ink: var(--papers-ink);

  --col-back:  linear-gradient(150deg, #F09A22 0%, #DC7A00 100%);
  --col-glow:  rgba(242, 135, 0, .40);
  --col-dot:   #FFE0B0;
  --sheet-tag-bg: #FEE7C0; --sheet-tag-ink: #8B5000;
}
.s-shipped {
  --k: var(--notes);     --k-tint: var(--notes-tint);     --k-ink: var(--notes-ink);

  --col-back:  linear-gradient(150deg, #7A9C3D 0%, #435E1F 100%);
  --col-glow:  rgba(89, 124, 43, .42);
  --col-dot:   #DCEBBB;
  --sheet-tag-bg: #ECF0D1; --sheet-tag-ink: #495A23;
}
.s-next {
  --k: var(--reference); --k-tint: var(--reference-tint); --k-ink: var(--reference-ink);

  --col-back:  linear-gradient(150deg, #8C6597 0%, #492E55 100%);
  --col-glow:  rgba(73, 46, 85, .40);
  --col-dot:   #E7D6EC;
  --sheet-tag-bg: #F0E6F0; --sheet-tag-ink: #5B3C60;
}

.rel-board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 26px;
  align-items: start;
  padding: 10px 0 var(--section-y);
}


/* The header sits above the folder now, so the rail behind it is visible
   for its whole length instead of only in the 26px gaps. */
.rel-track { position: relative; }

.rel-head {
  position: relative; z-index: 2;
  display: flex; align-items: center; gap: 10px;
  padding: 0 4px 14px;
}
.rel-node {
  width: 13px; height: 13px; border-radius: 50%; flex-shrink: 0;
  background: var(--k);
  box-shadow: 0 0 0 4px var(--paper), 0 2px 6px rgba(40, 33, 41, .18);
}
.rel-label {
  font: 500 .7rem var(--font-mono); letter-spacing: .12em;
  text-transform: uppercase; color: var(--k-ink);
}
.rel-n {
  margin-left: auto;
  min-width: 24px; height: 24px; padding: 0 8px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 500 .72rem var(--font-mono);
  color: var(--k-ink); background: var(--k-tint); border-radius: 999px;
}

/* the rail: one unbroken line through every node */
.rel-board::before {
  content: "";
  position: absolute;
  z-index: 0;
  /* 10px board padding + 12px to the centre of the 24px header row */
  top: 21px;
  left: 10px;
  right: 10px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    var(--papers) 0%, var(--notes) 50%, var(--reference) 100%);
  opacity: .55;
}

.rel-col {
  position: relative;
  border-radius: 28px 48px 28px 28px;   /* the folder corner, site-wide */
  background: var(--col-back);
  padding: 18px;
  box-shadow: 0 16px 34px -14px var(--col-glow);
}


.rel-sheets { display: grid; gap: 12px; }

.rel-sheet {
  background: var(--surface);
  border-radius: 14px;                   /* the sheet radius from .fc-sheet */
  padding: 15px 16px 16px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .08);
  transition: transform var(--dur-hover) var(--pop),
              box-shadow var(--dur-hover) var(--ease-out-expo);
}
.rel-sheet:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 26px -8px rgba(70, 50, 20, .32);
}

.rel-sheet-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 9px; }
.rel-tag {
  font: 500 .62rem var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--sheet-tag-ink); background: var(--sheet-tag-bg);
  border-radius: 999px; padding: 5px 10px;
}
.rel-date { font: 500 .66rem var(--font-mono); color: var(--muted); }
.rel-title {
  font-family: var(--font-course); font-size: 1.02rem; font-weight: 700;
  letter-spacing: var(--track-sm); line-height: 1.2; margin: 0 0 6px;
}
.rel-text { color: var(--ink-soft); font-size: .84rem; line-height: 1.55; margin: 0; }
.rel-items { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.rel-items li {
  font-size: .72rem; font-weight: 600; color: var(--ink-soft);
  background: var(--wash); border-radius: 999px; padding: 5px 10px;
}

.rel-empty {
  border: 1px dashed rgba(255, 255, 255, .38); border-radius: 14px;
  padding: 20px 16px; text-align: center;
  font: 500 .74rem var(--font-mono); color: rgba(255, 255, 255, .78);
}

@media (max-width: 900px) {
  .rel-board { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
  .rel-board::before { display: none; }
}
@media (max-width: 620px) {
  .rel-board { grid-template-columns: 1fr; gap: 18px; padding-bottom: 70px; }
  .rel-col { border-radius: 24px 38px 24px 24px; }
}

/* branch accent on the library shelves — decorative, so it is only ever a
   dot, never a fill; the fills stay reserved for resource kind. */
.shelf-label h2 { display: inline-flex; align-items: center; gap: 10px; }
.shelf-dot {
  width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 8%, transparent);
}

/* 15 branch codes have to sit on one line, so this row runs tighter than
   the browse-page kind pills: less gap, less padding, a smaller dot. */
#libPills { gap: 1px; padding: 4px; overflow-x: auto; }
#libPills .pill {
  gap: 6px;
  font-size: .82rem;
  letter-spacing: .03em;
  padding: 7px 11px;
}
#libPills .pill i { width: 6px; height: 6px; }

/* The course code is the primary key here: a student arrives knowing
   "CS2110", not the book's title. So it leads the cover and the panel. */
.book .b-code {
  font: 500 .56rem var(--font-mono);
  letter-spacing: .12em; text-transform: uppercase;
  opacity: .72; margin-bottom: 7px; display: block;
}
/* branch pills are codes now — short enough that they all sit on one row */
#libPills .pill { letter-spacing: .04em; }

/* A branch with no books yet still gets a pill, so students can see their
   own branch is accounted for — but it is inert, not a dead link. */
#libPills .pill.is-empty {
  opacity: .38;
  cursor: default;
  pointer-events: none;
}

/* ------------------------------------------------------------
   Version timeline — the numbered releases, below the board.

   A rail down the left with a node per release. The rail draws itself
   as the section scrolls past (scroll-driven, so it tracks position
   rather than firing once) and each card arrives on its own.
   ------------------------------------------------------------ */
/* Capped and centred: at full wrap width a bullet ran past 1000px, about
   130 characters, and every short line left a wide empty gutter beside it.
   The board above stays full width, so this reads as a deliberate step in. */
.vt { padding: 8px 0 var(--section-y); max-width: 840px; margin-inline: auto; }
.vt-intro { margin-bottom: 30px; }
.vt-intro h2 {
  font-family: var(--font-display); font-size: 1.9rem; font-weight: 800;
  letter-spacing: var(--track-xl); line-height: 1.02; margin: 0 0 5px;
}
.vt-intro p { color: var(--ink-soft); font-size: .92rem; margin: 0; }

.vt-track { position: relative; padding-left: 54px; }

/* the rail */
.vt-line {
  position: absolute; left: 17px; top: 6px; bottom: 6px; width: 2px;
  border-radius: 2px;
  /* The rail paints its own progress: the grey groove is the background
     colour, the gradient is a background-image whose height is animated.
     Animating a child's scaleY instead would collapse that child to zero,
     and a view() timeline cannot track a subject it has just collapsed. */
  background-color: var(--hair);
  background-image: linear-gradient(180deg, var(--papers) 0%, var(--reference) 100%);
  background-repeat: no-repeat;
  background-size: 100% 0%;
}

.vt-item { position: relative; margin-bottom: 22px; }
.vt-item:last-child { margin-bottom: 0; }

/* the node — an icon badge sitting on the rail */
.vt-node {
  position: absolute; left: -54px; top: 14px;
  width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--k); color: #fff;
  box-shadow: 0 0 0 5px var(--paper), 0 6px 14px -5px var(--k);
}

.vt-card {
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: 18px 22px 20px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .05);
  transition: transform var(--dur-hover) var(--pop),
              box-shadow var(--dur-hover) var(--ease-out-expo);
}
.vt-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 26px -10px rgba(70, 50, 20, .3);
}

.vt-head {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding-bottom: 12px; margin-bottom: 14px;
  border-bottom: 1px solid var(--hair);
}
.vt-version {
  font-family: var(--font-course); font-size: 1.14rem; font-weight: 700;
  letter-spacing: var(--track-sm); margin: 0;
}
.vt-date {
  font: 500 .68rem var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--k-ink); background: var(--k-tint);
  border-radius: 999px; padding: 5px 11px;
}

.vt-group + .vt-group { margin-top: 14px; }
.vt-group-label {
  font: 500 .64rem var(--font-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 7px;
}
.vt-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.vt-list li {
  position: relative; padding-left: 17px;
  color: var(--ink-soft); font-size: .87rem; line-height: 1.5;
}
.vt-list li::before {
  content: ""; position: absolute; left: 0; top: .58em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--k);
  opacity: .55;
}

@media (max-width: 620px) {
  .vt { padding-bottom: 64px; }
  .vt-track { padding-left: 42px; }
  .vt-line { left: 13px; }
  .vt-node { left: -42px; width: 28px; height: 28px; }
  .vt-node svg { width: 13px; height: 13px; }
  .vt-card { padding: 15px 16px 17px; }
}

/* The timeline cards use an IntersectionObserver on every browser, not a
   view() timeline. Measured: .vt-item's ViewTimeline reports currentTime
   null even with the card fully on screen, and `fill: both` then pins the
   card at its `from` state — permanently invisible. The observer is
   deterministic here and the cost is one observer. */
@media (prefers-reduced-motion: no-preference) {
  .vt-item {
    opacity: 0; transform: translateY(18px);
    transition: opacity var(--dur-arrive) var(--ease-out-expo),
                transform var(--dur-arrive) var(--ease-out-expo);
    transition-delay: var(--d, 0ms);
  }
  .vt-item.in { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .vt-line { background-size: 100% 100%; }
}


/* ------------------------------------------------------------
   Releases preview.

   This is intentionally scoped to .preview-page so the experimental page
   can be reviewed without changing the live Releases layout.
   ------------------------------------------------------------ */
.preview-page .preview-hero { padding-bottom: 18px; }
.preview-kicker {
  display: block;
  font: 500 .68rem var(--font-mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted);
}
.preview-page .hero-sub { max-width: 38ch; }
.preview-journey, .preview-history { padding: 48px 0 var(--section-y); }
.preview-section-head { margin-bottom: 30px; }
.preview-section-head h2 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.9rem, 3.5vw, 2.8rem);
  letter-spacing: var(--track-lg); line-height: 1.02; margin: 8px 0 0;
}
.preview-stages { position: relative; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px; }
.preview-rail {
  position: relative; height: 3px; margin: 0 calc(16.66% + 13px) -10px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--notes) 0 31%, var(--papers) 44% 58%, var(--reference) 70% 100%);
  box-shadow: 0 4px 12px -7px rgba(40, 33, 41, .48);
  transform: translateY(10px);
}
.preview-rail::before, .preview-rail::after { content: ""; position: absolute; top: 50%; width: 8px; height: 8px; border: 2px solid var(--paper); border-radius: 50%; transform: translateY(-50%); }
.preview-rail::before { left: 30%; background: var(--notes); }
.preview-rail::after { right: 30%; background: var(--reference); }
.preview-stage { --preview-col: var(--notes); --preview-tint: var(--notes-tint); --preview-ink: var(--notes-ink); position: relative; padding-top: 14px; }
.preview-stage-now { --preview-col: var(--papers); --preview-tint: var(--papers-tint); --preview-ink: var(--papers-ink); }
.preview-stage-next { --preview-col: var(--reference); --preview-tint: var(--reference-tint); --preview-ink: var(--reference-ink); }
.preview-stage-label {
  display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
  font: 500 .68rem var(--font-mono); letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}
.preview-stage-label i { width: 7px; height: 7px; border-radius: 50%; background: var(--preview-col); }
.preview-stage-label { color: var(--preview-ink); }
.preview-stage-label span { margin-left: auto; color: var(--papers-ink); }
.preview-stage-card {
  position: relative; overflow: hidden; min-height: 255px; padding: 24px 22px 22px;
  background: var(--surface); border: 1px solid var(--hair);
  border-radius: 22px 38px 22px 22px;
  box-shadow: 0 12px 28px -22px rgba(70, 50, 20, .45);
}
.preview-stage-card::before { content: ""; position: absolute; inset: 0 0 auto; height: 5px; background: var(--preview-col); }
.preview-stage-card::after { content: ""; position: absolute; right: -34px; bottom: -48px; width: 150px; height: 150px; border-radius: 50%; background: var(--preview-tint); opacity: .75; }
.preview-stage-now .preview-stage-card { border-color: #f3c37e; box-shadow: 0 18px 34px -20px rgba(242, 135, 0, .5); }
.preview-card-corner { position: absolute; z-index: 1; right: 20px; top: 18px; width: 26px; height: 26px; border: 2px solid var(--preview-col); border-left: 0; border-bottom: 0; border-radius: 0 12px 0 0; opacity: .58; }
.preview-stage-meta { position: relative; z-index: 1; font: 500 .66rem var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--preview-ink); }
.preview-stage-card h3, .preview-stage-card p, .preview-chip-list { position: relative; z-index: 1; }
.preview-stage-card h3 { font-family: var(--font-course); font-size: 1.35rem; line-height: 1.12; letter-spacing: var(--track-md); margin: 15px 0 10px; }
.preview-stage-card p { color: var(--ink-soft); font-size: .9rem; line-height: 1.58; margin: 0; }
.preview-chip-list { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 20px 0 0; padding: 0; }
.preview-chip-list li { padding: 6px 9px; border-radius: 999px; background: var(--preview-tint); color: var(--preview-ink); font-size: .7rem; font-weight: 600; }
.preview-stage-past .preview-stage-card {
  border-radius: 16px 30px 16px 16px;
  background: linear-gradient(145deg, #fffef8 0%, var(--notes-tint) 180%);
}
.preview-stage-past .preview-stage-card::after {
  right: 18px; bottom: 17px; width: 84px; height: 46px; border: 1px solid rgba(73, 90, 35, .26);
  border-radius: 8px; background: repeating-linear-gradient(180deg, transparent 0 10px, rgba(73, 90, 35, .14) 10px 11px);
}
.preview-stage-past .preview-chip-list li { background: var(--surface); border: 1px solid rgba(73, 90, 35, .16); }
.preview-stage-now { z-index: 1; }
.preview-stage-now .preview-stage-card {
  min-height: 272px; margin-top: -8px;
  background: linear-gradient(145deg, #fffefa 0%, var(--papers-tint) 185%);
}
.preview-stage-next .preview-stage-card {
  border-style: dashed; border-radius: 12px 34px 12px 12px;
  box-shadow: 8px 8px 0 var(--reference-tint), 0 12px 28px -22px rgba(70, 50, 20, .45);
}
.preview-stage-next .preview-stage-card::after {
  right: 17px; bottom: 18px; width: 72px; height: 72px;
  border: 1px dashed rgba(91, 60, 96, .3); border-radius: 50%; background: transparent;
}
.preview-stage-next .preview-chip-list li { border: 1px dashed rgba(91, 60, 96, .25); }
.preview-history { border-top: 1px solid var(--hair); }
.preview-history-list { position: relative; display: grid; gap: 16px; max-width: 860px; margin: 0 auto; }
.preview-history-list::before { content: ""; position: absolute; top: 22px; bottom: 22px; left: 47px; width: 2px; background: linear-gradient(var(--reference), var(--notes)); }
.preview-release { position: relative; display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 22px; align-items: start; }
.preview-release-mark { position: relative; z-index: 1; display: grid; place-items: center; width: 96px; height: 46px; border: 5px solid var(--paper); border-radius: 999px; background: var(--reference-tint); color: var(--reference-ink); font: 500 .8rem var(--font-mono); }
.preview-release-shipped .preview-release-mark { background: var(--notes-tint); color: var(--notes-ink); }
.preview-release-main { padding: 20px 24px; border: 1px solid var(--hair); border-left: 4px solid var(--reference); border-radius: 18px; background: var(--surface); }
.preview-release-shipped .preview-release-main { border-left-color: var(--notes); }
.preview-release-top { display: flex; justify-content: space-between; gap: 16px; font: 500 .66rem var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.preview-release-top span { color: var(--reference-ink); }
.preview-release-shipped .preview-release-top span { color: var(--notes-ink); }
.preview-release-main h3 { font-family: var(--font-course); font-size: 1.22rem; letter-spacing: var(--track-sm); margin: 12px 0 12px; }
.preview-release-main ul { display: grid; gap: 7px; margin: 0; padding: 0; list-style: none; color: var(--ink-soft); font-size: .86rem; line-height: 1.45; }
.preview-release-main li::before { content: "↗"; display: inline-block; width: 20px; color: var(--muted); }
.preview-note { position: relative; display: flex; align-items: center; gap: 20px; overflow: hidden; margin: 0 auto var(--section-y); padding: 22px 26px; max-width: 860px; border: 1px solid var(--hair); border-radius: 20px; background: var(--surface); }
.preview-note::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 7px; background: linear-gradient(var(--notes), var(--papers), var(--reference)); }
.preview-note-mark { position: relative; z-index: 1; display: grid; place-items: center; flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%; background: var(--papers-tint); color: var(--papers-ink); font-size: 1.5rem; }
.preview-note > div, .preview-note > a { position: relative; z-index: 1; }
.preview-note h2 { font-family: var(--font-display); font-size: 1.25rem; letter-spacing: var(--track-md); margin: 5px 0 4px; }
.preview-note p { color: var(--ink-soft); font-size: .86rem; line-height: 1.5; margin: 0; }
.preview-note .cta-solid { margin-left: auto; flex-shrink: 0; padding: 13px 20px; font-size: .86rem; }

@media (prefers-reduced-motion: no-preference) {
  .preview-page .preview-stage-card, .preview-page .preview-release-main { transition: transform var(--dur-hover) var(--pop), box-shadow var(--dur-hover) var(--ease-out-expo); }
  .preview-page .preview-stage-card:hover, .preview-page .preview-release-main:hover { transform: translateY(-4px); box-shadow: 0 18px 32px -20px rgba(70, 50, 20, .38); }
}
@media (max-width: 900px) {
  .preview-stages { grid-template-columns: 1fr; gap: 18px; }
  .preview-rail { display: none; }
  .preview-stage { padding-top: 0; }
  .preview-stage-card { min-height: 0; }
  .preview-stage-now .preview-stage-card { margin-top: 0; min-height: 0; }
}
@media (max-width: 620px) {
  .preview-section-head { margin-bottom: 28px; }
  .preview-journey, .preview-history { padding: 38px 0 64px; }
  .preview-release { grid-template-columns: 1fr; gap: 0; padding-left: 34px; }
  .preview-history-list::before { left: 13px; }
  .preview-release-mark { position: absolute; left: -1px; top: 18px; width: 28px; height: 28px; border-width: 4px; font-size: .56rem; }
  .preview-release-main { padding: 17px 18px; }
  .preview-note { align-items: flex-start; flex-wrap: wrap; padding: 20px; }
  .preview-note > div { flex: 1 1 190px; }
  .preview-note .cta-solid { width: 100%; justify-content: center; margin-left: 60px; }
}



/* 4 rich semantic folder colorways */








/* Bottom banner for accuracy and reporting */



@media (max-width: 820px) {
}

@media (max-width: 620px) {
}

@supports (animation-timeline: view()) and (animation-range: entry) {
  @media (prefers-reduced-motion: no-preference) {
  }
}


/* ------------------------------------------------------------
   Terms.

   Four statements, not an essay. Deliberately monochrome: colour on
   this site means resource kind, and these are not resources. Giving
   the four rows the four kind colours would invent a third meaning
   for the palette. The only colour is the amber CTA, which is the
   only action on the page.
   ------------------------------------------------------------ */
.doc-hero { padding-bottom: 4px; }
.doc-hero h1 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.4rem, 5.2vw, 3.6rem);
  line-height: 1; letter-spacing: var(--track-xl);
  margin: 0 0 16px;
}



/* ---------- B: one sheet ---------- */
.ts-sheet {
  margin: 34px auto var(--section-y);   /* auto: the hero above is centred */
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: 28px;
  padding: 10px 40px 38px;
  box-shadow: 0 18px 40px -26px rgba(70, 50, 20, .4);
  max-width: 860px;
}
.ts-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; padding: 24px 0 4px;
}
.ts-kicker {
  font-family: var(--font-display); font-weight: 800;
  font-size: 1.05rem; letter-spacing: var(--track-sm);
}
.ts-meta { font: 500 .68rem var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }

.ts { list-style: none; margin: 0; padding: 0; }
.ts-row {
  display: grid; grid-template-columns: 52px minmax(0, 1fr);
  gap: 22px;
  padding: 26px 0;
  border-top: 1px solid var(--hair);
}
.ts-n {
  font: 500 .74rem var(--font-mono); letter-spacing: .1em;
  color: var(--muted); padding-top: 6px;
}
.ts-body h2 {
  font-family: var(--font-display); font-size: 1.3rem; font-weight: 800;
  letter-spacing: var(--track-md); line-height: 1.18; margin: 0 0 8px;
}
.ts-body p {
  color: var(--ink-soft); font-size: .97rem; line-height: 1.6;
  max-width: 56ch; margin: 0;
}
.ts-contact {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
}
.ts-contact p { flex: 1; }
.ts-mail { flex-shrink: 0; }

@media (max-width: 620px) {
  .ts-row { grid-template-columns: 1fr; gap: 8px; }
  .ts-n { padding-top: 0; }
  .ts-sheet { padding: 6px 22px 28px; border-radius: 22px; }
  .ts-contact { align-items: stretch; flex-direction: column; gap: 16px; }
  .ts-mail { width: 100%; justify-content: center; }
}

/* ------------------------------------------------------------
   FAQ accordion.

   The panel animates `grid-template-rows: 0fr -> 1fr` rather than
   max-height, so it eases to the answer's real height whatever its
   length. max-height animates to a guessed value: too small clips a
   long answer, too large spends the tail of the transition easing
   through empty space, which is what makes most accordions feel cheap.
   ------------------------------------------------------------ */
/* Narrower than the sheet above it: a question list reads badly when the
   row is far wider than it is tall. Rows are also taller than the default
   button padding would give, so each one is a block rather than a slot. */
.faq { padding: 66px 0 var(--section-y); max-width: 700px; margin-inline: auto; }

.faq-intro { margin-bottom: 30px; text-align: center; }
.faq-intro h2 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.8rem, 3.4vw, 2.4rem);
  letter-spacing: var(--track-lg); line-height: 1.05; margin: 0;
}

.faq-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }

.faq-item {
  border-radius: 26px;
  background: var(--wash);
  overflow: hidden;
  transition: background-color var(--dur-hover) var(--ease);
}
.faq-item:hover { background: var(--wash-strong); }

.faq-q {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  width: 100%; padding: 24px 20px 24px 26px;
  border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-size: 1.02rem; font-weight: 500;
  color: var(--ink); text-align: left;
}
.faq-icon {
  display: grid; place-items: center; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: 999px;
  background: var(--surface); color: var(--ink-soft);
  transition: transform .4s var(--ease-out-expo), color .25s var(--ease);
}
.faq-item.is-open .faq-icon { transform: rotate(180deg); color: var(--ink); }

.faq-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .5s var(--ease-out-expo);
}
.faq-item.is-open .faq-panel { grid-template-rows: 1fr; }
.faq-panel-in { overflow: hidden; }      /* the row that actually collapses */
.faq-panel p {
  color: var(--ink-soft); font-size: .95rem; line-height: 1.62;
  margin: 0; padding: 0 24px 22px; max-width: 58ch;
}
.faq-panel p b { font-weight: 700; color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .faq-panel, .faq-icon { transition: none; }
}
@media (max-width: 620px) {
  .faq { padding-top: 40px; }
  .faq-q { padding: 17px 14px 17px 18px; font-size: .95rem; }
  .faq-panel p { padding: 0 18px 20px; }
}
