/* ============================================================
   CLUEDIT // cluedit.co.uk

   Modern, quiet, a little bit neon. Cool near-white by day and a
   deep indigo-black by night, with one gradient that runs violet
   to teal to amber and ties the logo and the rules together.

   Each game owns one stop of that gradient, and on its own page
   that single colour does all the work - buttons, revealed
   letters, the active tab, the pips:
     flippedit  violet
     phrasedit  teal
     cluedit    amber
   The full gradient is kept for branding (the wordmark, the
   hairline rules, the share card's edge) and is never put behind
   words, where it turns muddy.

   Two typefaces. Inter for everything a person reads. Monospace
   only for data a person counts or copies: guesses, scores, codes,
   the share text, the puzzle furniture on the tracks.

   Mobile first, thumbs assumed.
   ============================================================ */

/* Self-hosted so a font never costs a visitor a request to a third
   party - the footer promises no tracking, and it means it. */
@font-face {
  font-family: "Inter";
  src: url("fonts/inter-var-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* surfaces */
  --bg:        #f6f7fb;
  --surface:   #ffffff;
  --cell:      #ffffff;

  /* type */
  --fg:        #14161f;
  --fg-2:      #464a60;
  --fg-3:      #5f6480;   /* 4.5:1 or better on --bg */

  /* lines */
  --line:      #e4e6f0;
  --line-2:    #c5c9db;

  /* signal */
  --danger:    #e0395e;
  --success:   #0ea37a;
  --amber:     #d97706;
  --slate:     #64748b;
  --gold:      #b45309;

  /* brand */
  --accent:    #6d4aff;
  --accent-2:  #0fb894;
  --accent-3:  #e08c00;
  --brand: linear-gradient(120deg, var(--accent), var(--accent-2) 52%, var(--accent-3));

  /* per game */
  --g-flippedit: var(--accent);
  --g-phrasedit: var(--accent-2);
  --g-cluedit:   var(--accent-3);

  /* Text that sits ON a game colour. White only works on the violet;
     teal and amber are too light for it, so they take dark ink. */
  --on-flippedit: #ffffff;
  --on-phrasedit: #04261d;
  --on-cluedit:   #2a1700;
  --on-success:   #04261d;

  /* outside a game, the violet stands in */
  --tint:    var(--accent);
  --on-tint: var(--on-flippedit);

  --shadow:    0 1px 2px rgba(20,22,31,.05), 0 10px 28px rgba(20,22,31,.07);
  --shadow-sm: 0 1px 2px rgba(20,22,31,.07);

  --r:         16px;
  --r-sm:      10px;
  --r-xs:      7px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono",
          "Cascadia Mono", Menlo, Consolas, monospace;
  --wrap: min(100% - 1.6rem, 60rem);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #0c0d14;
    --surface:   #161827;
    --cell:      #191c2b;

    --fg:        #edeff8;
    --fg-2:      #b4b9d2;
    --fg-3:      #8a8fa8;

    --line:      #252940;
    --line-2:    #3b4060;

    --danger:    #ff6b8a;
    --success:   #3ddca4;
    --amber:     #fbbf24;
    --slate:     #94a3b8;
    --gold:      #fcd34d;

    --accent:    #9d7bff;
    --accent-2:  #2fdcb0;
    --accent-3:  #ffc046;

    /* every game colour is light at night, so all of them take dark ink */
    --on-flippedit: #0c0d14;
    --on-phrasedit: #0c0d14;
    --on-cluedit:   #0c0d14;
    --on-success:   #0c0d14;

    --shadow:    0 1px 2px rgba(0,0,0,.5), 0 14px 36px rgba(0,0,0,.45);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.5);
  }
}

* { box-sizing: border-box; }

/* Each daily page carries its own colour, and anything can borrow
   another game's with a tint-* class (the "now try" button does). */
body[data-game="flippedit"], .tint-flippedit, .dcard-flippedit, .game-btn[data-game="flippedit"] {
  --tint: var(--g-flippedit); --on-tint: var(--on-flippedit);
}
body[data-game="phrasedit"], .tint-phrasedit, .dcard-phrasedit, .game-btn[data-game="phrasedit"] {
  --tint: var(--g-phrasedit); --on-tint: var(--on-phrasedit);
}
body[data-game="cluedit"], .tint-cluedit, .dcard-cluedit, .game-btn[data-game="cluedit"] {
  --tint: var(--g-cluedit); --on-tint: var(--on-cluedit);
}

/* several components set display, which would otherwise beat the
   user agent's [hidden] rule */
[hidden] { display: none !important; }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 400 clamp(1rem, 0.96rem + 0.2vw, 1.05rem)/1.6 var(--font);
  font-feature-settings: "cv11";          /* Inter's single-storey a */
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* Two soft washes of the brand gradient, sat behind everything, so
   the page has some depth without any texture. */
.grain {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(60rem 32rem at 12% -8%, rgba(109,74,255,.10), transparent 60%),
    radial-gradient(48rem 28rem at 92% 4%, rgba(15,184,148,.09), transparent 62%);
}
@media (prefers-color-scheme: dark) {
  .grain {
    background:
      radial-gradient(60rem 32rem at 12% -8%, rgba(157,123,255,.17), transparent 60%),
      radial-gradient(48rem 28rem at 92% 4%, rgba(47,220,176,.11), transparent 62%);
  }
}

main.sheet {
  position: relative; z-index: 1;
  width: var(--wrap);
  margin: 0 auto;
  padding: 1.2rem 0 3rem;
}

a { color: inherit; text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { color: var(--accent); }

.dim { color: var(--fg-3); }
.tiny { font-size: .85em; }
.good { color: var(--success); }
.bad  { color: var(--danger); }
.warn { color: var(--amber); }
.ok   { color: var(--success); }

/* The one small-label style, used wherever something names the
   thing beside it. Sans, not mono: it is read, not counted. */
.kicker, .clue-label, .cat-key, .route-label, .dc-kind, .dc-state,
.purse, .share-head, .tk-panel label, .answer label, .lock-state,
.dev-label, .tstrip b, .tstrip i {
  font-family: var(--font);
  font-weight: 700;
  font-size: .72rem;
  line-height: 1.2;
  letter-spacing: .07em;
  text-transform: uppercase;
}

/* ---------- the brand lockup ---------- */
.brand {
  display: inline-flex; align-items: center; gap: .55rem;
  text-decoration: none;
}
.brand img { display: block; width: 1.5em; height: 1.5em; }
.brand-word {
  font-weight: 800; letter-spacing: -.03em;
  background: var(--brand);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* ---------- masthead ---------- */
.masthead { padding-top: .6rem; }
.masthead h1 {
  margin: 0;
  font-size: clamp(2.4rem, 1.4rem + 6vw, 4.4rem);
  letter-spacing: -.04em;
  line-height: 1;
  font-weight: 800;
}
.masthead h1 .brand img { width: .92em; height: .92em; }
.masthead .sub {
  margin: .55rem 0 0;
  font-size: 1.02rem; font-weight: 500;
  color: var(--fg-2);
}

/* a hairline carrying the brand gradient, fading out to the right */
.rule-double {
  border: 0; height: 2px;
  background: var(--brand);
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 42%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0%, #000 42%, transparent 100%);
  border-radius: 2px;
  margin: 1rem 0 1.1rem;
  opacity: .85;
}
.dateline {
  display: flex; flex-wrap: wrap; gap: .4rem;
  font-size: .76rem; font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--fg-3);
  margin: -.3rem 0 1.2rem;
}
.dateline span {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .3rem .65rem;
  white-space: nowrap;
}
.dateline span:empty { display: none; }
/* the track pages nest the live value inside its label */
.dateline span span {
  border: 0; padding: 0; margin-left: .3rem;
  color: var(--fg); font-variant-numeric: tabular-nums;
}

.backlink {
  display: inline-flex; align-items: center; margin-bottom: .7rem;
  font-size: .85rem; font-weight: 700; letter-spacing: .02em;
  color: var(--fg-3); text-decoration: none;
}

/* ---------- boot log (track pages: a terminal on purpose) ---------- */
.bootlog {
  font: 400 .8rem/1.55 var(--mono);
  white-space: pre-wrap;
  margin: 0 0 1.2rem;
  color: var(--fg-2);
  min-height: 1.5rem;
}

/* ---------- blocks of prose ---------- */
.notice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1.1rem 1.15rem;
  margin: 0 0 1.2rem;
  box-shadow: var(--shadow-sm);
}
.notice p { margin: 0 0 .5rem; }
.notice p:last-child { margin-bottom: 0; }

.standfirst {
  font-size: 1.05em; line-height: 1.55; color: var(--fg-2);
  margin: 0 0 1.2rem;
}
.standfirst strong { color: var(--fg); }

/* ---------- the three daily cards ---------- */
.daily-grid { display: grid; gap: .9rem; grid-template-columns: 1fr; margin: 0 0 1.4rem; }
@media (min-width: 52rem) { .daily-grid { grid-template-columns: repeat(3, 1fr); } }

.dcard {
  display: flex; flex-direction: column;
  text-decoration: none; color: inherit;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  padding: 1rem;
  box-shadow: var(--shadow-sm);
  position: relative; overflow: hidden;
  transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease;
}
/* a hairline of the game's own colour along the top edge */
.dcard::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--tint);
}
.dcard:hover {
  color: inherit; transform: translateY(-3px);
  border-color: var(--line-2); box-shadow: var(--shadow);
}
.dcard.done { border-color: color-mix(in srgb, var(--success) 60%, var(--line)); }

.dc-top {
  display: flex; justify-content: space-between; align-items: center;
  gap: .5rem; margin-bottom: .7rem;
}
.dc-kind { color: var(--tint); display: inline-flex; align-items: center; gap: .45rem; }
.dc-badge {
  font-size: .62rem; letter-spacing: .06em;
  background: var(--tint); color: var(--on-tint);
  border-radius: 999px; padding: .18rem .45rem;
}
.dc-state { color: var(--fg-3); text-align: right; font-weight: 600; }
.dcard.done .dc-state { color: var(--success); font-weight: 700; }
.dcard.part .dc-state { color: var(--amber); font-weight: 700; }

/* a sample of each game, drawn the way the game draws it */
.dc-art {
  display: flex; align-items: center; justify-content: center;
  gap: .3rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  min-height: 4.4rem; padding: .7rem;
  margin-bottom: .8rem;
}
.dc-tile {
  display: grid; place-items: center;
  width: 2.2rem; height: 2.6rem;
  border: 1.5px solid var(--line-2); background: var(--cell);
  border-radius: var(--r-xs);
  font: 800 1.15rem/1 var(--font);
}
.dc-tile.on { background: var(--tint); color: var(--on-tint); border-color: transparent; }
.dc-gap { width: .5rem; }
.dc-art-clue { font: italic 400 .98rem/1.4 var(--font); padding: .7rem .9rem; }
.dc-clue { text-align: center; }

.dc-name {
  font-weight: 800; letter-spacing: -.02em;
  font-size: 1.2rem; line-height: 1.15; margin-bottom: .25rem;
}
.dc-sub { color: var(--fg-2); font-size: .92rem; line-height: 1.45; flex: 1 1 auto; }
/* the whole card is the link; this is what it looks like it does */
.dc-go {
  display: block; text-align: center;
  margin-top: .9rem; padding: .72rem 1rem;
  border-radius: var(--r-sm);
  background: var(--tint); color: var(--on-tint);
  font-weight: 700; font-size: .92rem; letter-spacing: .02em;
  transition: filter .12s ease;
}
.dcard:hover .dc-go { filter: brightness(1.07); }
.dcard.done .dc-go {
  background: transparent; color: var(--tint);
  box-shadow: inset 0 0 0 1.5px var(--tint);
}

/* ---------- the badged tracks, demoted to a strip ---------- */
.track-strip { display: grid; gap: .5rem; grid-template-columns: 1fr; margin: .9rem 0 0; }
@media (min-width: 40rem) { .track-strip { grid-template-columns: repeat(3, 1fr); } }
.tstrip {
  display: flex; align-items: center; gap: .55rem; flex-wrap: wrap;
  text-decoration: none; color: inherit;
  border: 1px solid var(--line); background: var(--surface);
  border-radius: var(--r-sm);
  padding: .7rem .8rem;
}
.tstrip:hover { border-color: var(--line-2); color: inherit; }
.tstrip span { font-size: .9rem; color: var(--fg-2); flex: 1 1 auto; }
.tstrip i { font-style: normal; color: var(--fg-3); font-size: .66rem; }
.tstrip.done i { color: var(--success); }

/* ---------- the three game tabs ---------- */
.game-tabs {
  display: flex;
  gap: .35rem;
  margin: 0 0 1.1rem;
  padding: .3rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.game-btn {
  flex: 1 1 0; min-width: 0; min-height: 0;
  appearance: none; cursor: pointer;
  border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--fg-3);
  padding: .55rem .3rem .5rem;
  display: flex; flex-direction: column; align-items: center; gap: .15rem;
  position: relative; letter-spacing: 0;
  transition: background .14s ease, color .14s ease;
}
.game-btn:hover { color: var(--fg); background: var(--bg); }
.game-btn.on { background: var(--tint); color: var(--on-tint); }
.gb-name {
  font-weight: 800; letter-spacing: -.01em;
  font-size: clamp(.78rem, .62rem + .55vw, .98rem);
}
.gb-sub { font-size: .64rem; font-weight: 600; letter-spacing: .07em; opacity: .8; }
.gb-tick {
  position: absolute; top: .2rem; right: .35rem;
  font-size: .68rem; color: var(--success); line-height: 1;
}
.game-btn.on .gb-tick { color: var(--on-tint); }

/* ---------- section heads ---------- */
.kicker { color: var(--fg-3); margin: 2rem 0 .7rem; }
h2.head {
  font-size: clamp(1.45rem, 1.1rem + 1.6vw, 2rem);
  margin: 0 0 .8rem; line-height: 1.18;
  font-weight: 800; letter-spacing: -.03em;
}

/* ---------- chips ---------- */
.chip {
  display: inline-block; padding: .22rem .6rem; margin: .15rem .15rem 0 0;
  font-weight: 700; font-size: .78rem; letter-spacing: .03em;
  border: 1px solid currentColor; border-radius: 999px; text-decoration: none;
}
.chip-risk { color: var(--amber); }
.streak-warn { color: var(--amber); font-weight: 600; }
.chip-bronze { color: var(--amber); }
.chip-silver { color: var(--slate); }
.chip-gold   { color: var(--gold); }

/* ---------- expandable sections: how to play, house rules ---------- */
.how-to {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  margin: 0 0 .7rem;
}
.how-to > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .85rem 1rem;
  font-weight: 700; font-size: .95rem;
}
.how-to > summary::-webkit-details-marker { display: none; }
.how-to > summary::after {
  content: ''; flex: none;
  width: .5rem; height: .5rem;
  border-right: 2px solid var(--fg-3); border-bottom: 2px solid var(--fg-3);
  transform: rotate(45deg) translateY(-2px);
  transition: transform .18s ease;
}
.how-to[open] > summary::after { transform: rotate(-135deg) translateY(-1px); }
.how-to > summary:hover { color: var(--tint); }
.how-list { padding: 0 1rem 1rem; color: var(--fg-2); }
.how-list p { margin: 0 0 .7rem; }
.how-list ul, .how-list ol, ul.how-list { margin: 0; padding-left: 1.2rem; }
ul.how-list { padding: 0 1rem 1rem 2.2rem; }
.how-list li { margin-bottom: .4rem; }
.rules { margin-top: 1.2rem; }

/* ---------- lights (track pages) ---------- */
.progress {
  display: flex; flex-wrap: wrap; gap: .35rem; align-items: center;
  margin: 0 0 1.2rem;
}
.pip {
  font: 700 .72rem/1 var(--mono);
  border: 1px solid var(--line-2); border-radius: 999px;
  padding: .32rem .55rem;
  color: var(--fg-3);
}
.pip.done { background: var(--success); border-color: transparent; color: var(--on-success); }
.pip-label { font-size: .78rem; font-weight: 600; color: var(--fg-3); margin-left: .3rem; }

.lock {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  padding: 1.1rem;
  margin: 0 0 1.2rem;
  box-shadow: var(--shadow);
}
.lock.solved { background: transparent; box-shadow: none; border-style: dashed; }
.lock-head {
  display: flex; align-items: baseline; gap: .6rem;
  border-bottom: 1px solid var(--line); padding-bottom: .55rem; margin-bottom: .85rem;
}
.lock-no { font: 700 .8rem/1 var(--mono); color: var(--accent); }
.lock-head h2 {
  margin: 0; font-size: clamp(1.1rem, .95rem + .9vw, 1.45rem);
  flex: 1; line-height: 1.15; letter-spacing: -.02em;
}
.lock-state { color: var(--fg-3); }
.solved-line { margin: 0; font-size: .95em; color: var(--fg-2); }
.solved-line b { font-family: var(--mono); letter-spacing: .1em; color: var(--success); }
.brief { margin: 0 0 .9rem; color: var(--fg-2); }

/* puzzle furniture - mono, because it is letters to be counted */
.block {
  font: 700 clamp(1rem, .9rem + 1.2vw, 1.4rem)/1.7 var(--mono);
  letter-spacing: .22em;
  background: var(--cell);
  border: 1px dashed var(--line-2); border-radius: var(--r-sm);
  padding: .9rem .7rem; margin: 0 0 1rem;
  white-space: pre-wrap; word-break: break-word; text-align: center;
}
.tiles { display: flex; flex-wrap: wrap; gap: .4rem; justify-content: center; margin: 0 0 1rem; }
.tile {
  display: grid; place-items: center;
  width: clamp(2.4rem, 1.6rem + 3.6vw, 3.2rem);
  height: clamp(2.4rem, 1.6rem + 3.6vw, 3.2rem);
  background: var(--cell);
  border: 1px solid var(--line-2); border-radius: var(--r-xs);
  font: 800 clamp(1.1rem, .9rem + 1.6vw, 1.6rem)/1 var(--font);
  box-shadow: var(--shadow-sm);
}
.sentence {
  font-size: 1.2em; text-align: center; margin: 0 0 1rem;
  padding: .8rem; background: var(--cell);
  border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
}
.clue {
  font-size: 1.15em; font-style: italic; text-align: center;
  margin: 0 0 1rem; padding: .8rem; background: var(--cell);
  border: 1px solid var(--line); border-radius: var(--r-sm);
}
.memo { margin: 0 0 1rem; padding-left: 1.4rem; color: var(--fg-2); }
.memo li { margin-bottom: .3rem; }
.ladder { display: grid; gap: .3rem; justify-content: center; margin: 0 0 1rem; }
.rung {
  font: 700 1.2rem/1 var(--mono); letter-spacing: .3em;
  background: var(--cell); border: 1px solid var(--line-2); border-radius: var(--r-xs);
  padding: .55rem 1rem; text-align: center;
}
.rung.gap { color: var(--accent); border-style: dashed; }
.bridge { display: grid; gap: .4rem; justify-content: center; margin: 0 0 1rem; }
.brow {
  font: 700 1.15rem/1 var(--mono); letter-spacing: .18em;
  background: var(--cell); border: 1px solid var(--line); border-radius: var(--r-xs);
  padding: .5rem .8rem;
}
.brow .blank { color: var(--accent); margin-right: .3rem; }
.pad { width: 100%; border-collapse: collapse; margin: 0 0 1rem; font-size: .95em; }
.pad th {
  text-align: left; width: 3rem; font: 700 .8rem/1 var(--mono); color: var(--accent);
  border-bottom: 1px solid var(--line); padding: .5rem .4rem;
}
.pad td { border-bottom: 1px solid var(--line); padding: .5rem .4rem; color: var(--fg-2); }

/* answers */
.answer label { display: block; margin-bottom: .45rem; color: var(--fg-2); }
.answer-row { display: flex; gap: .5rem; }
.answer-row input { flex: 1 1 auto; min-width: 0; }
input[type="text"], textarea, select {
  font: 700 1.05rem/1.2 var(--mono); letter-spacing: .14em;
  padding: .7rem .75rem;
  background: var(--cell); color: var(--fg);
  border: 1px solid var(--line-2); border-radius: var(--r-sm);
  width: 100%; min-height: 3rem;
}
input:focus, textarea:focus, select:focus {
  outline: 2px solid var(--tint); outline-offset: 1px; border-color: var(--tint);
}
textarea { letter-spacing: .06em; font-weight: 400; }
select { font-family: var(--font); letter-spacing: .02em; }

/* ---------- buttons, and links dressed as buttons ---------- */
button, a.go, a.ghost {
  font: 700 .88rem/1 var(--font); letter-spacing: .02em;
  padding: .8rem 1rem; min-height: 3rem;
  cursor: pointer; border-radius: var(--r-sm);
  transition: transform .12s ease, filter .12s ease,
              background .12s ease, border-color .12s ease, color .12s ease;
}
a.go, a.ghost {
  display: inline-flex; align-items: center; justify-content: center;
  text-align: center; text-decoration: none;
}
button:active:not([disabled]), a.go:active, a.ghost:active { transform: translateY(1px); }
.go {
  background: var(--tint); color: var(--on-tint); border: 0;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}
.go:hover { filter: brightness(1.07); color: var(--on-tint); }
.go[disabled] { opacity: .5; cursor: default; filter: none; }
.ghost {
  background: var(--surface); color: var(--fg-2);
  border: 1px solid var(--line-2);
}
.ghost:hover { color: var(--tint); border-color: var(--tint); }
.ghost[disabled] { opacity: .45; cursor: default; }
.linkish {
  background: none; border: 0; padding: 0; min-height: 0;
  color: var(--fg-3); text-decoration: underline; font-weight: 600;
}

.verdict { margin: .6rem 0 .8rem; font-weight: 700; font-size: .92rem; min-height: 1.2em; }
.verdict.good { color: var(--success); }
.verdict.bad  { color: var(--danger); }

.hintbox { margin: 0 0 .6rem; }
.hint {
  margin: 0 0 .5rem; padding: .65rem .8rem;
  background: var(--cell);
  border: 1px solid var(--line); border-left: 3px solid var(--amber);
  border-radius: var(--r-sm);
  font-size: .95em; color: var(--fg-2);
}
.hint b { font-size: .78em; font-weight: 800; letter-spacing: .06em; color: var(--amber); }

/* ---------- motion ---------- */
.shake { animation: shake .34s; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  50% { transform: translateX(6px); }
  80% { transform: translateX(-3px); }
}
/* a letter turning over: it starts edge-on and swings flat, and the
   fill mode holds it edge-on until its turn in a ripple */
.cell.flip-in { animation: flip-in .34s cubic-bezier(.3,.7,.4,1.2) both; }
@keyframes flip-in {
  from { transform: perspective(300px) rotateX(-90deg); }
  to   { transform: perspective(300px) rotateX(0); }
}
.done-grid.pulse { animation: pulse .6s .25s ease both; }
@keyframes pulse {
  0%   { transform: scale(.92); opacity: 0; }
  60%  { transform: scale(1.06); opacity: 1; }
  100% { transform: scale(1); }
}

/* ---------- notepad ---------- */
.toolkit { margin: 0 0 1.2rem; }
.tk-panel {
  border: 1px solid var(--line); border-radius: var(--r);
  padding: .9rem; margin-top: .5rem;
  background: var(--surface);
}
.tk-panel label { display: block; color: var(--fg-3); margin: .6rem 0 .35rem; }
.tk-panel label:first-child { margin-top: 0; }
.tk-out {
  font: 700 1rem/1.6 var(--mono); letter-spacing: .12em;
  background: var(--cell); border: 1px dashed var(--line-2); border-radius: var(--r-sm);
  padding: .6rem; margin: 0; white-space: pre-wrap; word-break: break-word;
}

/* ---------- granted overlay ---------- */
.granted {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  background: var(--bg);
  text-align: center; padding: 2rem;
}
.g-stamp {
  font: 800 clamp(1.6rem, 1rem + 4vw, 3rem)/1 var(--font); letter-spacing: -.02em;
  border: 3px solid var(--success); border-radius: var(--r); color: var(--success);
  padding: .6rem 1.1rem; transform: rotate(-3deg); margin: 0 0 1rem;
}
.g-line { font-size: 1rem; color: var(--fg-2); }

/* ============================================================
   THE DAILIES
   ============================================================ */
.across-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem .7rem;
  font-size: .88rem; color: var(--fg-3);
  margin: 0 0 .8rem;
}
.across-head .no {
  font-weight: 800; color: var(--tint);
  font-variant-numeric: tabular-nums;
}

.clue-card {
  border: 1px solid var(--line);
  border-left: 3px solid var(--tint);
  border-radius: var(--r);
  background: var(--surface);
  padding: 1rem 1rem 1.1rem;
  margin: 0 0 1.1rem;
  box-shadow: var(--shadow-sm);
}
.clue-label { color: var(--fg-3); margin: 0 0 .5rem; }
.clue-text {
  margin: 0;
  font-size: clamp(1.25rem, 1rem + 2vw, 1.8rem); font-weight: 500;
  line-height: 1.3; letter-spacing: -.015em;
}
.clue-text b { color: var(--tint); font-weight: 600; }

.cat-line {
  margin: .7rem 0 0; padding-top: .6rem;
  border-top: 1px solid var(--line);
  font-size: .95rem;
}
.cat-key { color: var(--fg-3); margin-right: .4rem; }
/* no clue: the category is the prompt, so it gets the headline */
.clue-card.cat-mode .cat-line { margin: 0; padding: 0; border: 0; }
.clue-card.cat-mode .cat-key { display: block; margin: 0 0 .35rem; }
.clue-card.cat-mode .cat-val {
  display: block;
  font-size: clamp(1.45rem, 1.1rem + 2.4vw, 2.1rem); font-weight: 800;
  letter-spacing: -.025em; line-height: 1.15;
}

/* the answer, one box per letter */
.board {
  display: flex; flex-wrap: wrap; gap: .3rem 0;
  justify-content: center; margin: 0 0 .6rem;
}
.bword {
  display: inline-flex; flex-wrap: nowrap;
  margin: 0 .5rem .32rem 0;
}
.cell {
  display: grid; place-items: center;
  width: clamp(2rem, 1rem + 4.8vw, 3rem);
  height: clamp(2.35rem, 1.2rem + 5.4vw, 3.3rem);
  margin-right: .3rem;
  background: var(--cell);
  border: 1.5px solid var(--line-2);
  border-radius: var(--r-xs);
  box-shadow: var(--shadow-sm);
  font: 800 clamp(1.05rem, .75rem + 2.3vw, 1.55rem)/1 var(--font);
  text-transform: uppercase;
}
.cell.given {
  background: var(--tint); color: var(--on-tint);
  border-color: transparent;
}
.board-long .cell {
  width: 1.4rem; height: 1.8rem;
  font-size: .9rem;
}
.cell.punct {
  border: 0; background: transparent; box-shadow: none;
  width: .7rem; min-width: .7rem;
}

.across-msg {
  min-height: 1.4em; margin: 0 0 .6rem; text-align: center;
  font-weight: 600; font-size: .95rem;
}
.across-msg.good { color: var(--success); }
.across-msg.bad  { color: var(--danger); }
.across-msg.warn { color: var(--amber); }

.guess-form { display: flex; gap: .5rem; margin: 0 0 1rem; }
.guess-form input {
  flex: 1 1 auto; min-width: 0;
  text-align: center; letter-spacing: .24em; font-size: 1.1rem;
  padding-left: .3rem; padding-right: .3rem;
}
.guess-form .go { padding-left: 1.2rem; padding-right: 1.2rem; }

/* letters, attempts and hints: data, so the numbers are tabular */
.across-meta {
  display: flex; flex-wrap: wrap; gap: .35rem .45rem; justify-content: center;
  font-size: .76rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--fg-3);
  font-variant-numeric: tabular-nums;
  margin: 0 0 1rem;
}
.across-meta > span {
  display: inline-flex; align-items: center; gap: .45rem;
  border: 1px solid var(--line); border-radius: 999px;
  padding: .36rem .7rem; background: var(--surface);
}
.across-meta b { color: var(--fg); }
/* the six rungs, as dots: filled while still yours to spend */
.rung-pips { display: inline-flex; gap: .2rem; }
.rung-pips i {
  width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--tint);
}
.rung-pips i.spent { background: transparent; box-shadow: inset 0 0 0 1.5px var(--line-2); }

.across-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 1.2rem; }
.across-actions button { flex: 1 1 10rem; }
@media (max-width: 26rem) {
  .across-actions button { padding-left: .5rem; padding-right: .5rem; font-size: .84rem; }
}

/* ---------- PHRASEDIT: the letter keypad ----------
   Twenty-six targets on a 320px screen is the tight case, so the
   grid is fixed at seven across and the keys are square. Every key
   prints its own price. */
.keypad { margin: 0 0 1rem; }

.purse {
  display: flex; align-items: center; justify-content: center;
  gap: .5rem; flex-wrap: wrap; margin: 0 0 .6rem;
  color: var(--fg-3);
}
.purse-pips { letter-spacing: .2em; color: var(--tint); font-size: .95rem; }
.purse-count { font-variant-numeric: tabular-nums; text-transform: none; }
.purse-count b { color: var(--fg); font-size: 1.05rem; }

.keys {
  display: grid; grid-template-columns: repeat(7, 1fr);
  gap: .32rem; max-width: 24rem; margin: 0 auto;
}
@media (min-width: 30rem) { .keys { grid-template-columns: repeat(9, 1fr); } }

.key {
  position: relative; aspect-ratio: 1 / 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--cell); color: var(--fg);
  border: 1px solid var(--line-2); border-radius: var(--r-xs);
  box-shadow: var(--shadow-sm); cursor: pointer; padding: 0;
  font: 800 1.05rem/1 var(--font); letter-spacing: 0;
  transition: transform .1s ease, background .12s ease, color .12s ease;
}
.key .kl { pointer-events: none; }
.key .kc {
  position: absolute; top: 3px; right: 4px;
  font: 700 .6rem/1 var(--font); color: var(--fg-3);
}
.key.vowel { background: var(--surface); }
.key.vowel .kc { color: var(--amber); }
.key:hover:not(:disabled) {
  background: var(--tint); color: var(--on-tint);
  border-color: transparent; transform: translateY(-1px);
}
.key:hover:not(:disabled) .kc { color: var(--on-tint); opacity: .8; }

.key.hit {
  background: var(--success); border-color: transparent;
  color: var(--on-success); opacity: 1;
}
.key.miss {
  background: transparent; border-style: dashed; box-shadow: none;
  color: var(--fg-3); text-decoration: line-through;
}
.key:disabled { cursor: default; }
.key:disabled:not(.hit):not(.miss) { opacity: .32; }
.key.hit .kc, .key.miss .kc { display: none; }

.keys-note { text-align: center; margin: .55rem 0 0; }

/* ---------- FLIPPEDIT: the flip control ----------
   One button, not a keyboard. You choose whether to spend, never
   which letter, so there is nothing else to show. */
.flip-bar { margin: 0 0 1rem; text-align: center; }
.flip-bar .flip-btn { width: 100%; max-width: 22rem; }
.flip-bar .keys-note { max-width: 30rem; margin: .55rem auto 0; }

/* ---------- what has happened so far ---------- */
.rows { display: grid; gap: .3rem; margin: 0 0 1.2rem; }
.arow {
  display: grid; grid-template-columns: 1.6rem 1fr 1.4rem;
  align-items: center; gap: .5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  padding: .45rem .6rem;
  min-height: 2.5rem;
}
.arow .anum {
  font: 700 .72rem/1 var(--font); color: var(--fg-3); text-align: center;
  font-variant-numeric: tabular-nums;
}
.arow .atext {
  font: 700 .92rem/1.2 var(--mono); letter-spacing: .14em;
  text-transform: uppercase; overflow-wrap: anywhere;
}
.arow .amark { font-size: .95rem; text-align: center; }

.arow.guess-row {
  border-color: color-mix(in srgb, var(--danger) 55%, var(--line));
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 7%, var(--surface));
}
.arow.guess-row.close {
  border-color: color-mix(in srgb, var(--amber) 55%, var(--line));
  color: var(--amber);
  background: color-mix(in srgb, var(--amber) 8%, var(--surface));
}
.arow.guess-row.right {
  border-color: var(--success); color: var(--success);
  background: color-mix(in srgb, var(--success) 13%, var(--surface));
}
.hint-row {
  border-color: color-mix(in srgb, var(--amber) 45%, var(--line));
  color: var(--amber);
}
.hint-row .atext, .arow.letter-row .atext, .arow.flip-row .atext {
  font-family: var(--font); letter-spacing: .02em; font-weight: 600; font-size: .86rem;
  text-transform: none;
}
.arow.letter-row .amark { color: var(--danger); }

/* A flip is not a rung, so it sits between them: quieter, with a
   dash where the attempt number would be. */
.arow.flip-row {
  border-color: color-mix(in srgb, var(--tint) 40%, var(--line));
  border-left: 3px solid var(--tint);
  background: color-mix(in srgb, var(--tint) 6%, var(--surface));
}
.arow.flip-row .atext { color: var(--fg-2); }
.arow.flip-row .amark { color: var(--tint); }

@media (max-width: 26rem) {
  .arow { grid-template-columns: 1.3rem 1fr 1.1rem; gap: .35rem; }
  .arow .atext { font-size: .84rem; letter-spacing: .08em; }
}

/* ---------- end of game ---------- */
.done-panel {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  padding: 1.15rem; margin: 0 0 1.2rem;
  box-shadow: var(--shadow);
}
.done-head {
  margin: 0 0 .6rem; font-size: clamp(1.2rem, 1rem + 1.4vw, 1.65rem);
  line-height: 1.18; font-weight: 800; letter-spacing: -.025em;
}
.done-answer {
  margin: 0 0 .5rem; font-size: .8rem; font-weight: 600; letter-spacing: .05em;
  color: var(--fg-3); text-transform: uppercase;
}
.done-answer b {
  font-size: 1.6rem; letter-spacing: -.01em; margin-left: .2rem;
  font-weight: 800; color: var(--fg); text-transform: uppercase;
}
.done-grid {
  margin: 0 0 .6rem; font: 700 1.15rem/1.4 var(--mono); letter-spacing: .06em;
  font-variant-emoji: emoji;
}
.done-line { margin: 0 0 .8rem; color: var(--fg-2); font-size: .92rem; }
.done-stats {
  display: flex; flex-wrap: wrap; gap: .35rem .45rem;
  font-size: .74rem; font-weight: 600; letter-spacing: .04em; color: var(--fg-3);
  font-variant-numeric: tabular-nums;
  padding-top: .2rem; margin-bottom: 1rem;
}
.done-stats span {
  border: 1px solid var(--line); border-radius: 999px;
  padding: .38rem .65rem; background: var(--bg);
}
.done-stats b { color: var(--fg); font-size: 1.05em; }
.done-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: .8rem; }
.done-actions button { flex: 1 1 12rem; }
.clue-echo {
  margin: 0 0 .8rem; padding: .65rem .8rem;
  background: var(--cell);
  border: 1px solid var(--line); border-left: 3px solid var(--tint);
  border-radius: var(--r-sm);
  font-size: 1.05em; font-style: italic;
}

/* ---------- the share card ----------
   The one place inside a game that wears the full gradient: it is
   the bit that leaves the site, so it carries the brand. */
.share-card {
  position: relative; overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--bg);
  padding: 1rem .95rem .95rem;
  margin: 0 0 .9rem;
}
.share-card::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--brand);
}
.share-head {
  display: flex; align-items: center; gap: .45rem;
  margin: 0 0 .6rem;
  color: var(--fg-3);
}
.share-logo { width: 1.15rem; height: 1.15rem; display: block; }
.share-tag {
  display: inline-block;
  background: var(--tint); color: var(--on-tint);
  font-size: .9em; letter-spacing: .05em;
  border-radius: 999px;
  padding: .2rem .5rem; margin-left: auto;
}
/* exactly what gets pasted, so it stays monospace */
.share-preview {
  margin: 0 0 .6rem;
  padding: .7rem .7rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font: .84rem/1.75 var(--mono);
  white-space: pre-wrap;
  word-break: break-word;
  font-variant-emoji: emoji;
}
.share-key {
  display: flex; flex-wrap: wrap; gap: .15rem .8rem;
  margin: 0 0 .45rem;
  font-size: .78rem; color: var(--fg-3);
}
.share-safe { margin: 0 0 .75rem; font-size: .8rem; color: var(--fg-3); }
.share-actions { display: flex; flex-wrap: wrap; gap: .45rem; }
.share-actions button, .share-actions a {
  flex: 1 1 6.5rem; min-width: 0;
  padding: .75rem .5rem;
}
.done-flash {
  background: var(--success) !important;
  border-color: var(--success) !important;
  color: var(--on-success) !important;
}

/* ---------- add to home screen ---------- */
.install-card {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface); box-shadow: var(--shadow-sm);
  padding: .8rem .9rem; margin: 0 0 1.2rem;
}
.done-panel .install-card { background: var(--bg); box-shadow: none; margin-bottom: .9rem; }
.install-card img { width: 2.5rem; height: 2.5rem; border-radius: .6rem; flex: none; }
.install-text { flex: 1 1 12rem; display: flex; flex-direction: column; gap: .15rem; font-size: .92rem; }
.install-text > span { color: var(--fg-2); font-size: .86rem; }
.install-actions { display: flex; gap: .4rem; flex: 0 0 auto; }
.install-actions button { min-height: 2.6rem; padding: .6rem .9rem; }

/* iPhone and iPad get a guide, not a button: Apple lets no page
   trigger the install, so the card shows where to tap instead */
.install-ios { flex-direction: column; align-items: stretch; gap: .7rem; }
.install-top { display: flex; align-items: center; gap: .8rem; }
.install-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.install-steps li {
  display: flex; align-items: flex-start; gap: .6rem;
  font-size: .9rem; color: var(--fg-2); line-height: 1.45;
}
.install-steps b { color: var(--fg); }
.step-n {
  flex: none; width: 1.5rem; height: 1.5rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--tint); color: var(--on-tint);
  font-size: .78rem; font-weight: 800;
}
.ios-share {
  width: 1.15em; height: 1.15em; vertical-align: -.2em;
  color: #0a84ff;                 /* the blue iOS draws it in */
}
.install-ios .install-actions { justify-content: flex-end; }

/* "now try the next one", in the next game's own colour */
.next-up { margin: 0 0 .9rem; }
.next-up a.go { display: flex; width: 100%; padding: .85rem 1rem; font-size: .95rem; }
.route-label { color: var(--fg-3); margin: .8rem 0 .4rem; }
.next-line { font-size: .88rem; color: var(--fg-3); margin: .7rem 0 0; }
#countdown { font-weight: 700; color: var(--fg-2); font-variant-numeric: tabular-nums; }

/* ---------- solver's card page ---------- */
.pass-canvas {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  box-shadow: var(--shadow); margin: 0 0 1rem;
}
.pass-facts {
  display: flex; flex-wrap: wrap; gap: .3rem 1rem;
  font: .74rem/1.8 var(--mono); letter-spacing: .1em; color: var(--fg-3);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: .5rem 0; margin: 0 0 1rem;
}
.pass-facts b { color: var(--fg); }
.row-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 1.2rem; }
.row-actions button, .row-actions a.ghost, .row-actions a.go {
  flex: 1 1 12rem; min-height: 2.9rem;
}

/* ---------- verify ---------- */
.verify-out {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface);
  padding: 1.1rem; margin-top: 1rem;
}
.stamp {
  display: inline-block; border: 3px solid var(--success); border-radius: var(--r-sm);
  color: var(--success);
  font: 800 1.1rem/1 var(--font); letter-spacing: .06em;
  padding: .5rem .8rem; transform: rotate(-3deg);
}
.stamp.bad { border-color: var(--danger); color: var(--danger); }

/* ---------- the notebook ---------- */
.stripe {
  font: .74rem/1.6 var(--mono); letter-spacing: .08em;
  border: 1px solid currentColor; border-radius: var(--r-sm);
  padding: .55rem .8rem; margin: 0 0 1.2rem;
}
.stripe.tier-bronze { color: var(--amber); }
.stripe.tier-silver { color: var(--slate); }
.stripe.tier-gold   { color: var(--gold); }
.archive-body h2 {
  font-size: clamp(1.5rem, 1.2rem + 1.8vw, 2.2rem); margin: 1.4rem 0 .5rem;
  letter-spacing: -.03em;
}
.archive-body h3 {
  font-size: .82rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent); margin: 1.8rem 0 .5rem;
}
.archive-body ul { padding-left: 1.1rem; }
.archive-body li { margin-bottom: .45rem; }

/* ---------- footer ---------- */
.foot {
  border-top: 1px solid var(--line);
  margin-top: 2.4rem; padding-top: 1rem;
  font-size: .86rem; line-height: 1.7;
  color: var(--fg-3);
}
.foot a { text-decoration: none; font-weight: 600; }
.foot a:hover { color: var(--accent); }
.foot p { margin: 0 0 .35rem; }
.foot-brand {
  display: flex; align-items: center; gap: .45rem;
  margin: 0 0 .6rem !important;
}
.foot-brand img { width: 1.1rem; height: 1.1rem; display: block; }
.foot-brand b {
  font-weight: 800; letter-spacing: -.01em;
  background: var(--brand);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* ==========================================================
   TEMPORARY TEST CONTROLS - safe to delete
   Paired with #devBar in daily.html and the block marked
   "TEMPORARY TEST CONTROLS" in daily.js.
   ========================================================== */
.dev-bar {
  border: 1px dashed var(--danger); border-radius: var(--r-sm);
  background: repeating-linear-gradient(
    -45deg, transparent, transparent 8px,
    rgba(168, 50, 42, .05) 8px, rgba(168, 50, 42, .05) 16px);
  padding: .6rem .7rem;
  margin: 0 0 1.1rem;
}
.dev-label { margin: 0 0 .5rem; color: var(--danger); }
.dev-row { display: flex; flex-wrap: wrap; gap: .4rem; }
.dev-row button {
  flex: 1 1 8rem; min-width: 0; min-height: 2.4rem;
  appearance: none; cursor: pointer;
  border: 1px solid var(--danger); background: transparent; color: var(--danger);
  font-size: .76rem; padding: .5rem .4rem;
}
.dev-row button:hover { background: var(--danger); color: var(--bg); }
.dev-note { margin: .5rem 0 0; font-size: .76rem; color: var(--fg-3); }
.dev-note code { font-size: 1em; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
