/* writer.css — laugh.so/writer.
   A copy of evaluator.css with the result screen swapped: the evaluator shows
   a number, the writer shows the jokes. Kept as its own file, like the
   evaluator's, so a change to one page cannot reflow the other. Everything
   above the result section is byte-for-byte the evaluator's, on purpose: the
   two pages are meant to read as one product. */
/* Light-only. Dark mode was unshipped 2026-08-12; do not re-add a prefers-color-scheme dark block, [data-theme] variants, or a theme toggle without a specific request. */
:root {
  --paper:#fffcf5;
  --card:#fffefb;
  --card-2:#fbf8f2;
  --ink:#201c1a;
  --ink-2:#4a4340;
  --muted:#706863;
  --faint:#938a84;
  --line:#e2ddd6;
  --accent:#a92665;
  --prov:#8a6d1d;
  --prov-bg:#fdf7e5;
  --prov-line:#e6d8ad;
  --grad:linear-gradient(135deg,#f6b97a 0%,#f4a8b8 50%,#e86aa6 100%);
  --serif:"Iowan Old Style","Palatino Linotype",Palatino,"Source Serif 4",Charter,Georgia,ui-serif,serif;
  --sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --shadow-lift:0 8px 30px rgba(61,45,35,.07);

  /* Spacing scale. Every vertical gap on this page is one of these, so the
     rhythm is decided once rather than per element. --tight binds a label to
     the thing it labels, --group separates one idea from the next, --page is
     the outer frame. Nothing else is allowed. */
  --tight:8px;
  --close:16px;
  --group:40px;
  --page:64px;
}

* { box-sizing:border-box; }
/* Body is a full-height column so the footer sits at the bottom of the
   viewport when the page is short (the composer is only a few hundred pixels
   tall) and follows the content when it is long. */
body {
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--sans); font-size:15px; line-height:1.55;
  -webkit-font-smoothing:antialiased;
  min-height:100vh; min-height:100dvh; display:flex; flex-direction:column;
}
main { flex:1 0 auto; display:flex; flex-direction:column; }
main > .shell { flex:1 0 auto; }
main > footer.site { flex:0 0 auto; margin-top:0; }
a { color:inherit; }
.shell { width:min(680px, calc(100% - 36px)); margin:0 auto; }
/* The shared footer spans the page like the masthead does, not the 680px
   column: at 680px its three-column grid squeezed the email box to nothing. */
footer.site .shell { width:min(1340px, calc(100% - 36px)); }
footer.site .newsletter { width:100%; max-width:420px; }
.sr-only {
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ---------------------------------------------------------- masthead ---- */
.masthead { border-bottom:1px solid var(--line); background:var(--paper); position:sticky; top:0; z-index:40; }
.masthead .shell { width:min(1340px, calc(100% - 36px)); min-height:58px; display:flex; align-items:center; justify-content:space-between; gap:20px; }
.wordmark { display:inline-flex; align-items:center; gap:9px; font-family:var(--serif); font-size:1.16rem; letter-spacing:-.01em; text-decoration:none; color:var(--ink); }
.wordmark .mark { width:20px; height:20px; border-radius:5px; display:block; }
.mast-nav { display:flex; align-items:center; gap:2px; flex-wrap:wrap; }
.mast-nav a { padding:6px 10px; border-radius:7px; text-decoration:none; color:var(--muted); font-size:.87rem; font-weight:550; }
.mast-nav a:hover { background:var(--card-2); color:var(--ink); }
.mast-nav a.current { color:var(--ink); font-weight:650; }

/* Subscribe call to action in the masthead, same as benchmark-board.css. Keep
   every copy in sync. --cta-fill is how much of the label (from the right) is
   orange->pink; site-footer.js sets it from the mouse x. */
.mast-nav .mast-cta {
  margin-left:10px;
  padding:5px 12px; border-radius:999px; background:#1d1a19;
  color:#fff; font-weight:650; border:0;
}
@property --cta-fill { syntax: '<percentage>'; inherits: false; initial-value: -14%; }
.mast-nav .mast-cta span, button.act span {
  --cta-fill: -14%;
  display:inline-block; color:transparent;
  -webkit-background-clip:text; background-clip:text;
  background-image:linear-gradient(90deg,#fff 0%,#fff calc(100% - var(--cta-fill) - 14%),#f6b97a calc(100% - var(--cta-fill)),#e86aa6 100%);
  transition:--cta-fill .05s ease;
}
.mast-nav a.mast-cta:hover span, button.act:hover span { --cta-fill: 62%; }
.mast-nav a.mast-cta:hover { background:#1d1a19; color:#fff; }
.mast-nav a.mast-cta:active, button.act:active { opacity:.85; }
@media (prefers-reduced-motion:reduce) { .mast-nav .mast-cta span, button.act span { transition:none; } }
@media (max-width:560px) {
  .masthead .shell { gap:10px; min-height:52px; }
  .wordmark { font-size:1.05rem; white-space:nowrap; }
  .mast-nav { flex-wrap:nowrap; }
  .mast-nav a:not(.current):not(.mast-cta) { display:none; }
  .mast-nav .mast-cta { padding:5px 12px; font-size:.82rem; }
}

/* ------------------------------------------------------------- input ---- */
/* The bottom padding lives on the content shell, not on main, so the footer
   (also inside main) can sit flush at the bottom of the page. */
main { padding:var(--page) 0 0; }
main > .shell { padding-bottom:calc(var(--page) + var(--group)); }

/* Heading structure lifted from /benchmark so the two pages read as one site:
   sticky masthead, then a left-aligned titleblock whose title-row carries the
   h1. Same serif, same regular weight, same clamp. */
.titleblock { padding:0 0 var(--group); }
/* ---- the product tabs: Evaluate | Write ---- */
/* The evaluator and the writer are one product with two verbs. A segmented
   control under the title switches between them; the current page is set in
   ink on card, the other is muted and a link. Left-aligned with the h1. */
.tabs {
  display:inline-flex; gap:2px; padding:3px; margin:0 0 var(--close);
  border:1px solid var(--line); border-radius:999px; background:var(--card-2);
}
.tabs a {
  padding:7px 18px; border-radius:999px; text-decoration:none; font-size:.88rem;
  font-weight:600; color:var(--muted);
}
.tabs a:hover { color:var(--ink); }
.tabs a[aria-current="page"] { background:var(--card); color:var(--ink); box-shadow:0 1px 2px rgba(61,45,35,.08); }

.title-row { display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
h1 {
  margin:0; font-family:var(--serif); font-weight:400;
  font-size:clamp(2.1rem, 4.2vw, 2.9rem); line-height:1.06; letter-spacing:-.02em;
  text-wrap:balance;
}
.composer {
  background:var(--card); border:1px solid var(--line); border-radius:16px;
  padding:6px 6px 12px; box-shadow:var(--shadow-lift);
}
.composer textarea {
  width:100%; border:none; background:transparent; color:var(--ink);
  font-family:var(--serif); font-size:1.18rem; line-height:1.5;
  padding:18px 16px 8px; resize:vertical; min-height:132px; outline:none;
}
.composer textarea::placeholder { color:var(--faint); }
.composer-foot { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:0 12px; }
/* Empty until it matters — either the free allowance is nearly gone or the
   character limit is close. Silent the rest of the time. */
.counter { font-size:.8rem; color:var(--faint); font-variant-numeric:tabular-nums; }
/* The site's one CTA style: dark pill, white label, orange->pink fill on hover
   (same as the masthead's and footer's Stay updated). */
button.act {
  border:none; border-radius:999px; padding:11px 24px; font:inherit; font-weight:650;
  font-size:.95rem; cursor:pointer; background:#1d1a19; color:#fff;
}
button.act:disabled { opacity:.45; cursor:not-allowed; }
button.ghost {
  border:1px solid var(--line); background:var(--card); color:var(--ink);
  border-radius:999px; padding:9px 16px; font:inherit; font-weight:600; font-size:.88rem; cursor:pointer;
}
button.ghost:hover { background:var(--card-2); }
button:focus-visible, a:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

.err { margin:var(--close) 0 0; padding:11px 14px; border-radius:10px; font-size:.88rem;
       background:var(--prov-bg); border:1px solid var(--prov-line); color:var(--prov); }

/* ----------------------------------------------------------- working ---- */
.working { text-align:center; padding:var(--page) 0; }
/* One line, same 2px track and accent as the result ticker, so the wait and the
   answer are visibly the same object. The old row of 24 dots wrapped onto a
   second line at this width and read as broken. */
.loadbar {
  max-width:440px; margin:0 auto; height:2px; border-radius:2px;
  background:var(--line); overflow:hidden;
}
.loadbar span {
  display:block; height:100%; width:0; border-radius:2px; background:var(--accent);
}
/* A write plus three parallel scorings is about 30 to 40 seconds. */
.loadbar.run span { animation:fill 40s cubic-bezier(.08,.62,.2,1) forwards; }
/* Stops short of the end: the bar is a sign of life, not a real completion
   estimate, and running it to 100% before the answer arrives would lie. */
@keyframes fill { from { width:0; } to { width:93%; } }
@media (prefers-reduced-motion: reduce) {
  .loadbar.run span { animation:none; width:40%; }
}

/* ------------------------------------------------------------ result ---- */
.result { display:none; }
.result.show { display:block; animation:rise .5s cubic-bezier(.2,.7,.3,1) both; }
@keyframes rise { from { opacity:0; transform:translateY(14px); } to { opacity:1; transform:none; } }
@media (prefers-reduced-motion: reduce) {
  .result.show { animation:none; }
}

/* The brief the jokes answer, restated small above them so the result screen
   stands on its own after the composer is hidden. */
.brief-echo {
  font-size:.85rem; color:var(--faint); margin:0 0 var(--close);
  overflow-wrap:anywhere;
}
.brief-echo b { font-weight:600; color:var(--muted); }

/* One card per batch: the best of three, chosen by the scorer. Same serif as
   the composer so what comes back reads as the same kind of object as what
   went in. */
.jokes { display:flex; flex-direction:column; gap:var(--close); margin:0; padding:0; list-style:none; }
.joke {
  background:var(--card); border:1px solid var(--line); border-radius:16px;
  padding:22px; box-shadow:var(--shadow-lift);
}
/* One size for every card: each card is the best of a batch of three, so
   none outranks another. */
.joke-text {
  font-family:var(--serif); font-size:1.42rem; line-height:1.4; letter-spacing:-.01em;
  color:var(--ink); margin:0; white-space:pre-wrap; overflow-wrap:anywhere;
}
.actions { margin:var(--group) 0 0; display:flex; justify-content:center; gap:10px; flex-wrap:wrap; }
.actions button.act { padding:10px 20px; font-size:.9rem; }
.actions button.act:disabled { opacity:.55; cursor:progress; }
.result .err { margin:var(--close) 0 0; }

/* -------------------------------------------------------------- gate ---- */
.gate { display:none; text-align:center; }
.gate.show { display:block; }
.gate p { font-family:var(--serif); font-size:1.4rem; margin:0 0 var(--group); letter-spacing:-.015em; }
.gsign {
  display:inline-flex; align-items:center; gap:9px; border:1px solid var(--line);
  background:var(--card); color:var(--ink); border-radius:999px; padding:10px 18px;
  font:inherit; font-weight:600; font-size:.92rem; cursor:pointer;
}
.gsign:hover { background:var(--card-2); }
.gsign svg { width:17px; height:17px; }

@media (max-width:560px) {
  main { padding:var(--group) 0 0; }
  main > .shell { padding-bottom:var(--page); }
  .composer textarea { font-size:1.06rem; }
}
