/* ============================================================
   Gracefully — design system
   Tokens first, then base, then components, then motion.
   Full documentation: STYLE-GUIDE.md
   ============================================================ */

/* --- 1. Tokens ------------------------------------------- */

:root {
  /* Colour — light is the default and the canonical palette */
  --paper:       #fbf7ef;
  --paper-warm:  #f5eee0;
  --paper-sunk:  #f1e9d9;
  --ink:         #241f1a;
  --ink-muted:   #6f6558;
  --ink-faint:   #a09585;
  --rule:        #ddd2bd;
  --rule-strong: #c6b99f;
  --accent:      #2b7d58;
  --accent-wash: rgba(43, 125, 88, 0.10);

  /* Texture */
  --grain:  0.05;
  --blotch: rgba(198, 176, 132, 0.16);

  /* Type */
  --font-display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --font-text:    "Newsreader", "Iowan Old Style", Georgia, serif;
  --font-hand:    "Caveat", "Bradley Hand", "Segoe Script", cursive;

  --size-display: clamp(3.25rem, 11vw, 6rem);
  --size-lede:    clamp(1.1875rem, 2.4vw, 1.4375rem);
  --size-entry:   1.375rem;
  --size-body:    1.0625rem;
  --size-hand:    1.375rem;
  --size-hand-sm: 1.1875rem;

  --leading-tight: 1.06;
  --leading-snug:  1.4;
  --leading-loose: 1.7;

  /* Space — named by role, not by size */
  --space-2xs: 0.375rem;
  --space-xs:  0.75rem;
  --space-sm:  1.25rem;
  --space-md:  2rem;
  --space-lg:  3.25rem;
  --space-xl:  5rem;

  --measure: 34rem;   /* reading column */
  --page:    42rem;   /* page column    */

  /* Bubble radii — deliberately uneven, so nothing looks stamped out */
  --radius-blob: 18px 22px 16px 24px;
  --radius-soft: 14px;

  /* Motion */
  --ease:        cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-expo:   cubic-bezier(0.16, 1, 0.3, 1);
  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-pen:    cubic-bezier(0.5, 0.02, 0.35, 1);
  --dur-fast:    180ms;
  --dur:         340ms;
  --dur-slow:    760ms;
  --dur-write:   1700ms;

  /* The hand-drawn hairline, used as a mask so it takes --rule's colour */
  --wave-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='40'%20height='6'%20viewBox='0%200%2040%206'%3E%3Cpath%20d='M0%203%20Q%205%201.2%2010%203%20T%2020%203%20T%2030%203%20T%2040%203'%20fill='none'%20stroke='%23000'%20stroke-width='1.3'%20stroke-linecap='round'/%3E%3C/svg%3E");
}

:root[data-theme="dark"] {
  --paper:       #17150f;
  --paper-warm:  #1f1c14;
  --paper-sunk:  #241f16;
  --ink:         #f2ece0;
  --ink-muted:   #a49a89;
  --ink-faint:   #746a5c;
  --rule:        #3a3327;
  --rule-strong: #524936;
  --accent:      #86d0a4;
  --accent-wash: rgba(134, 208, 164, 0.11);

  --grain:  0.07;
  --blotch: rgba(120, 100, 62, 0.18);
}

/* --- 2. Base --------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--size-body);
  font-weight: 380;
  line-height: var(--leading-loose);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

/* Texture layer 1 — paper grain */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Texture layer 2 — uneven paper tone, so the page is never a flat fill */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(58% 44% at 14% 16%, var(--blotch) 0%, transparent 72%),
    radial-gradient(48% 38% at 86% 28%, var(--blotch) 0%, transparent 72%),
    radial-gradient(66% 48% at 42% 90%, var(--blotch) 0%, transparent 74%);
}

body > * { position: relative; z-index: 1; }

::selection { background: var(--accent-wash); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 6px;
}

em { font-style: italic; }

/* --- 3. Layout ------------------------------------------- */

.page {
  flex: 1;
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(3.5rem, 14vh, 8rem) var(--space-sm) var(--space-lg);
}

/* --- 4. Hand-drawn hairlines ----------------------------- */

/* Every rule on the site is this wobbly line, masked so it takes --rule's
   colour and themes correctly. Never use a plain 1px border. */
.masthead__meta::after,
.section-label::after,
.entry::after,
.empty::after,
.colophon::before,
.rule-wave {
  content: "";
  display: block;
  height: 6px;
  background: var(--rule);
  -webkit-mask-image: var(--wave-mask);
  mask-image: var(--wave-mask);
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  -webkit-mask-size: 40px 6px;
  mask-size: 40px 6px;
  -webkit-mask-position: center;
  mask-position: center;
}

/* --- 5. Masthead ----------------------------------------- */

.masthead { margin-bottom: var(--space-lg); }

.masthead__meta {
  font-family: var(--font-hand);
  font-size: var(--size-hand);
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin-bottom: var(--space-sm);
}

.masthead__meta::after { flex: 1; }

.wordmark {
  font-family: var(--font-display);
  font-size: var(--size-display);
  font-weight: 500;
  font-optical-sizing: auto;
  font-variation-settings: "SOFT" 100, "WONK" 1;
  line-height: var(--leading-tight);
  letter-spacing: -0.012em;
}

.wordmark__mark {
  color: var(--accent);
  display: inline-block;
}

.lede {
  margin-top: var(--space-xs);
  max-width: var(--measure);
  font-size: var(--size-lede);
  line-height: var(--leading-snug);
  color: var(--ink-muted);
}

.lede em {
  color: var(--ink);
  font-style: italic;
}

/* --- 6. Section label ------------------------------------ */

/* Sentence case, handwritten. Never uppercase — see STYLE-GUIDE.md §3. */
.section-label {
  font-family: var(--font-hand);
  font-size: var(--size-hand);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin-bottom: var(--space-2xs);
}

.section-label::after { flex: 1; }

/* --- 7. The pen ------------------------------------------ */

/* A fountain pen that draws an ink stroke, then lifts off the page.
   The ink path carries pathLength="1", so the dash animation needs no JS. */

.penstroke {
  position: relative;
  width: 100%;
  max-width: 26rem;
  margin-top: calc(-1 * var(--space-xs));
  pointer-events: none;
}

.penstroke__svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.penstroke__ink {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-opacity: 0.85;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.penstroke__pen { opacity: 0; }

.penstroke__nib   { fill: var(--ink); }
.penstroke__slit  { stroke: var(--paper); stroke-width: 1.1; fill: none; }
.penstroke__hole  { fill: var(--paper); }
.penstroke__collar { fill: var(--accent); }
.penstroke__grip  { fill: var(--ink); opacity: 0.86; }

.penstroke.is-in .penstroke__ink {
  animation: ink-draw var(--dur-write) var(--ease-pen) 500ms forwards;
}

.penstroke.is-in .penstroke__pen {
  animation:
    pen-travel var(--dur-write) var(--ease-pen) 500ms forwards,
    pen-lift   calc(var(--dur-write) + 400ms) linear 500ms forwards;
}

@keyframes ink-draw  { to { stroke-dashoffset: 0; } }
@keyframes pen-travel { to { offset-distance: 100%; } }
@keyframes pen-lift {
  0%   { opacity: 0; }
  4%   { opacity: 1; }
  82%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Path variants. The `d` on the ink path and the `path()` here must match
   exactly, or the nib will drift off its own line. */
.penstroke--swash .penstroke__pen {
  offset-path: path("M10 30 C 74 8 132 40 198 26 C 258 13 312 34 366 22 C 384 18 398 22 410 32");
  offset-rotate: 0deg;
  offset-distance: 0%;
}

.penstroke--squiggle {
  max-width: 15rem;
}

.penstroke--squiggle .penstroke__pen {
  offset-path: path("M8 26 C 48 6 88 40 128 22 C 158 9 186 30 214 18");
  offset-rotate: 0deg;
  offset-distance: 0%;
}

/* Browsers without CSS motion path get the ink, never a parked pen. */
.no-motionpath .penstroke__pen { display: none; }

/* --- 8. Index (the app list) ----------------------------- */

.entries { list-style: none; }

.entry { position: relative; }

.entry::after {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
}

.entry__link {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  align-items: baseline;
  column-gap: var(--space-xs);
  row-gap: var(--space-2xs);
  padding: var(--space-sm) var(--space-2xs);
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: padding-left var(--dur) var(--ease-bounce);
}

/* Hover wash — a soft blob, not a rectangle */
.entry__link::before {
  content: "";
  position: absolute;
  top: 2px;
  bottom: 2px;
  left: calc(-1 * var(--space-xs));
  right: calc(-1 * var(--space-xs));
  background: var(--accent-wash);
  border-radius: var(--radius-blob);
  opacity: 0;
  transform: scale(0.97);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease-bounce);
  pointer-events: none;
}

.entry__link:hover::before,
.entry__link:focus-visible::before { opacity: 1; transform: scale(1); }

.entry__link:hover,
.entry__link:focus-visible { padding-left: var(--space-sm); }

.entry__num {
  font-family: var(--font-hand);
  font-size: var(--size-hand-sm);
  color: var(--ink-faint);
  transition: color var(--dur) var(--ease);
}

.entry__link:hover .entry__num,
.entry__link:focus-visible .entry__num { color: var(--accent); }

.entry__name {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-variation-settings: "SOFT" 100, "WONK" 1;
  font-size: var(--size-entry);
  font-weight: 450;
  line-height: var(--leading-snug);
  /* Grid blockifies children, so shrink-wrap the item — otherwise the hover
     underline draws across the whole column instead of under the word. */
  justify-self: start;
  position: relative;
  transition: color var(--dur) var(--ease);
}

/* The underline is the same wobbly line, drawn on rather than faded in */
.entry__name::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.32em;
  height: 6px;
  background: var(--accent);
  -webkit-mask-image: var(--wave-mask);
  mask-image: var(--wave-mask);
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  -webkit-mask-size: 40px 6px;
  mask-size: 40px 6px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease-expo);
}

.entry__link:hover .entry__name,
.entry__link:focus-visible .entry__name { color: var(--accent); }

.entry__link:hover .entry__name::after,
.entry__link:focus-visible .entry__name::after { transform: scaleX(1); }

.entry__desc {
  grid-column: 2 / 3;
  font-size: var(--size-body);
  font-style: italic;
  line-height: var(--leading-snug);
  color: var(--ink-muted);
  max-width: var(--measure);
}

.entry__arrow {
  font-family: var(--font-text);
  color: var(--ink-faint);
  transition: transform var(--dur) var(--ease-bounce), color var(--dur) var(--ease);
}

.entry__link:hover .entry__arrow,
.entry__link:focus-visible .entry__arrow {
  transform: translateX(5px);
  color: var(--accent);
}

/* --- 9. Empty state -------------------------------------- */

.empty {
  position: relative;
  padding: var(--space-md) var(--space-2xs);
  color: var(--ink-muted);
  font-style: italic;
}

.empty::after {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
}

/* The closing rule spans the full column, so the measure is capped on the
   text itself rather than on the box that carries the rule. */
.empty > span { display: inline-block; max-width: var(--measure); }

/* --- 10. Colophon ---------------------------------------- */

.colophon {
  position: relative;
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--space-md) var(--space-sm) var(--space-lg);
  font-family: var(--font-hand);
  font-size: var(--size-hand-sm);
  line-height: 1.3;
  color: var(--ink-muted);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.colophon::before {
  position: absolute;
  top: 0;
  left: var(--space-sm);
  right: var(--space-sm);
}

.colophon a {
  color: var(--ink-muted);
  text-decoration: none;
  position: relative;
  transition: color var(--dur) var(--ease);
}

.colophon a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.28em;
  height: 6px;
  background: var(--accent);
  -webkit-mask-image: var(--wave-mask);
  mask-image: var(--wave-mask);
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  -webkit-mask-size: 40px 6px;
  mask-size: 40px 6px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease-expo);
}

.colophon a:hover,
.colophon a:focus-visible { color: var(--accent); }

.colophon a:hover::after,
.colophon a:focus-visible::after { transform: scaleX(1); }

/* --- 11. Theme toggle ------------------------------------ */

.theme-toggle {
  position: fixed;
  top: var(--space-sm);
  right: var(--space-sm);
  z-index: 10;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--rule);
  border-radius: 46% 54% 52% 48%;
  background: var(--paper);
  color: var(--ink-muted);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease), transform var(--dur) var(--ease-bounce),
              border-radius var(--dur) var(--ease);
}

.theme-toggle:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: rotate(-14deg) scale(1.08);
  border-radius: 54% 46% 48% 52%;
}

.theme-toggle svg { width: 1.0625rem; height: 1.0625rem; display: block; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun  { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }

/* --- 12. Motion: entrance -------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--dur-slow) var(--ease-expo),
              transform var(--dur-slow) var(--ease-expo);
  transition-delay: calc(var(--i, 0) * 90ms);
}

.reveal.is-in {
  opacity: 1;
  transform: none;
}

/* The wordmark gets a softer, slower arrival than everything else */
.reveal--display {
  filter: blur(8px);
  transform: translateY(20px);
  transition: opacity 1s var(--ease-expo), transform 1s var(--ease-expo),
              filter 1s var(--ease-expo);
}

.reveal--display.is-in { filter: blur(0); }

/* Rules draw in from the left */
.reveal--rule::after {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-expo);
  transition-delay: calc(var(--i, 0) * 90ms + 160ms);
}

.reveal--rule.is-in::after { transform: scaleX(1); }

/* --- 13. Reduced motion ---------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }

  .reveal, .reveal--display {
    opacity: 1;
    transform: none;
    filter: none;
  }

  .reveal--rule::after { transform: scaleX(1); }
  .entry__link:hover, .entry__link:focus-visible { padding-left: var(--space-2xs); }
  .entry__link::before { transform: none; }
  .theme-toggle:hover { transform: none; }

  /* The pen does not write; the finished stroke is simply there. */
  .penstroke__ink { stroke-dashoffset: 0; }
  .penstroke__pen { display: none; }
}

/* --- 14. Narrow viewports -------------------------------- */

@media (max-width: 30rem) {
  .entry__link { grid-template-columns: 1.875rem 1fr auto; }
  .theme-toggle { top: var(--space-xs); right: var(--space-xs); }
  .penstroke { max-width: 100%; }
}
