/* ---------------------------------------------------------------------------
   COMMIT FONT
   Near-black, monospace, tiny letterspaced labels, one accent colour borrowed
   from whichever contribution theme is selected. The grid is the only loud
   thing on the page, and it is sized to fill whatever room it is given.
--------------------------------------------------------------------------- */

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

:root {
  --bg: #0a0a0b;
  --panel: #111113;
  --panel-2: #17171a;
  --line: #232327;
  --line-soft: #1b1b1f;
  --ink: #ece9e3;
  --ink-dim: #8e8b85;
  --ink-faint: #5d5a55;

  /* --cell and --radius are written by app.js so the grid fills its column. */
  --cell: 15px;
  --gap: 3px;
  --radius: 3px;
  --day-col: 30px;

  --shell: min(1240px, 100% - 3rem);
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

body[data-theme='gh'] {
  --l0: #161b22;
  --l1: #0e4429;
  --l2: #006d32;
  --l3: #26a641;
  --l4: #39d353;
  --card-bg: #0d1117;
  --card-ink: #e6edf3;
  --card-dim: #7d8590;
  --card-line: #21262d;
  --accent: #39d353;
  --accent-ink: #04160b;
  --radius-ratio: 0.19;
}

body[data-theme='claude'] {
  --l0: #2f2f31;
  --l1: #3d5896;
  --l2: #4f74c8;
  --l3: #7c9ce8;
  --l4: #a9c2f5;
  --card-bg: #1d1d1f;
  --card-ink: #ecebe8;
  --card-dim: #8b8984;
  --card-line: #2c2c2f;
  --accent: #7c9ce8;
  --accent-ink: #0b1226;
  --radius-ratio: 0.27;
}

html {
  background: var(--bg);
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(
      120% 70% at 50% -10%,
      color-mix(in srgb, var(--accent) 9%, transparent) 0%,
      transparent 60%
    ),
    var(--bg);
  color: var(--ink);
  font-family: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  transition: background 500ms var(--ease);
}

.grain {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

main {
  width: var(--shell);
  margin-inline: auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* --- top bar --------------------------------------------------------------- */

.topbar {
  width: var(--shell);
  margin: 0 auto;
  padding: 1.75rem 0 2.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.mark {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.mark__glyph {
  width: 13px;
  height: 13px;
  border-radius: 2.5px;
  background: var(--accent);
  box-shadow: 0 0 18px color-mix(in srgb, var(--accent) 55%, transparent);
  animation: pulse 3.4s var(--ease) infinite;
  transition: background 400ms var(--ease);
}

@keyframes pulse {
  0%,
  72%,
  100% {
    opacity: 1;
  }
  84% {
    opacity: 0.25;
  }
}

.mark__word {
  font-family: 'Silkscreen', 'Geist Mono', monospace;
  font-size: 15px;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.topbar__tools {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.seg {
  display: flex;
  border: 1px solid var(--line);
  border-radius: 7px;
  overflow: hidden;
}

.seg button {
  background: transparent;
  border: 0;
  border-right: 1px solid var(--line);
  color: var(--ink-dim);
  font: inherit;
  font-size: 11.5px;
  padding: 0.42rem 0.9rem;
  cursor: pointer;
  transition: all 180ms var(--ease);
  white-space: nowrap;
}

.seg button:last-child {
  border-right: 0;
}

.seg button:hover {
  color: var(--ink);
  background: var(--panel-2);
}

.seg button[aria-checked='true'] {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

.icon-btn {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--ink-dim);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: all 180ms var(--ease);
}

.icon-btn:hover {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 50%, var(--line));
}

.icon-btn__off {
  display: none;
}

.icon-btn[aria-pressed='false'] {
  color: var(--ink-faint);
}

.icon-btn[aria-pressed='false'] .icon-btn__on {
  display: none;
}

.icon-btn[aria-pressed='false'] .icon-btn__off {
  display: block;
}

/* --- input row ------------------------------------------------------------- */

.stage {
  margin-bottom: 2rem;
}

.entry {
  display: flex;
  align-items: flex-end;
  gap: 1.5rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.7rem;
  transition: border-color 300ms var(--ease);
}

.entry:focus-within {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
}

.prompt {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.prompt__caret {
  font-size: clamp(22px, 4vw, 34px);
  color: var(--accent);
  line-height: 1;
  transition: color 400ms var(--ease);
}

#text {
  flex: 1;
  min-width: 0;
  background: none;
  border: 0;
  outline: none;
  color: var(--ink);
  font: inherit;
  font-size: clamp(22px, 4vw, 34px);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 0;
  caret-color: var(--accent);
}

#text::placeholder {
  color: var(--ink-faint);
}

.handle-field {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding-bottom: 0.35rem;
  flex: 0 0 auto;
}

.handle-field label {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

#handle {
  /* 13ch of text plus the horizontal padding, or the placeholder clips. */
  width: 15.5ch;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  padding: 0.4rem 0.6rem;
  outline: none;
  transition: border-color 200ms var(--ease), width 220ms var(--ease);
}

#handle:focus {
  border-color: color-mix(in srgb, var(--accent) 65%, var(--line));
  width: 16ch;
}

.presets {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 1.15rem 0 0;
  padding: 0;
}

.presets button {
  background: var(--panel);
  border: 1px solid var(--line-soft);
  color: var(--ink-dim);
  font: inherit;
  font-size: 12px;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  cursor: pointer;
  transition: all 180ms var(--ease);
}

.presets button:hover,
.presets button:focus-visible {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
  outline: none;
  transform: translateY(-1px);
}

/* --- the plaque ------------------------------------------------------------ */

.plaque {
  position: relative;
  /* Room above the card for the mascot to stand in. */
  --perch: 40px;
  padding-top: var(--perch);
}

.card {
  background: var(--card-bg);
  color: var(--card-ink);
  border: 1px solid var(--card-line);
  border-radius: 12px;
  padding: 1.3rem 1.4rem 1.15rem;
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(255, 255, 255, 0.02) inset;
  transition: background 400ms var(--ease), border-color 400ms var(--ease),
    color 400ms var(--ease);
}

.card__head,
.card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.card__head {
  margin-bottom: 1rem;
}

.card__count,
.card__handle,
.card__streak {
  margin: 0;
  font-size: 13px;
  color: var(--card-dim);
}

.card__count strong,
.card__streak strong {
  color: var(--card-ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.card__handle {
  font-weight: 500;
  color: var(--card-ink);
}

.card__scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  padding-bottom: 0.35rem;
}

.card__grid {
  display: grid;
  grid-template-columns: var(--day-col) max-content;
  grid-template-rows: 16px max-content;
  gap: 5px 5px;
  width: max-content;
}

.months {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  height: 16px;
  font-size: 11px;
  color: var(--card-dim);
}

.months span {
  position: absolute;
  top: 0;
  white-space: nowrap;
}

.days {
  grid-column: 1;
  grid-row: 2;
  display: grid;
  grid-template-rows: repeat(7, var(--cell));
  gap: var(--gap);
  font-size: 11px;
  color: var(--card-dim);
}

.days span {
  display: flex;
  align-items: center;
  height: var(--cell);
  line-height: 1;
}

.cells {
  grid-column: 2;
  grid-row: 2;
  display: grid;
  grid-template-columns: repeat(53, var(--cell));
  grid-auto-flow: column;
  grid-template-rows: repeat(7, var(--cell));
  gap: var(--gap);
}

.cells i {
  display: block;
  width: var(--cell);
  height: var(--cell);
  border-radius: var(--radius);
  background: var(--l0);
  outline: 1px solid rgba(27, 31, 35, 0.06);
  outline-offset: -1px;
  transition: background 260ms var(--ease);
}

.cells i[data-level='1'] {
  background: var(--l1);
}
.cells i[data-level='2'] {
  background: var(--l2);
}
.cells i[data-level='3'] {
  background: var(--l3);
}
.cells i[data-level='4'] {
  background: var(--l4);
}

.cells.is-drawing i {
  animation: commit 420ms var(--ease) both;
  animation-delay: calc(var(--i) * 5ms);
}

@keyframes commit {
  0% {
    transform: scale(0.2);
    opacity: 0;
  }
  60% {
    transform: scale(1.12);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.card__foot {
  margin-top: 1rem;
}

.legend {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  color: var(--card-dim);
}

.legend span:first-child {
  margin-right: 3px;
}
.legend span:last-child {
  margin-left: 3px;
}

.legend i {
  width: 11px;
  height: 11px;
  border-radius: 2px;
  background: var(--l0);
  outline: 1px solid rgba(27, 31, 35, 0.06);
  outline-offset: -1px;
}

.legend i[data-level='1'] {
  background: var(--l1);
}
.legend i[data-level='2'] {
  background: var(--l2);
}
.legend i[data-level='3'] {
  background: var(--l3);
}
.legend i[data-level='4'] {
  background: var(--l4);
}

.tip {
  margin: 0.7rem 0 0;
  min-height: 1.2em;
  font-size: 11.5px;
  letter-spacing: 0.03em;
  color: var(--ink-faint);
}

/* --- mascots --------------------------------------------------------------- */

/* Bottom-aligned inside the plaque's top padding, so whatever the mascot's
   height it always perches on the card's top edge. */
.mascot {
  position: absolute;
  top: 0;
  right: 26px;
  height: calc(var(--perch) + 9px);
  display: flex;
  align-items: flex-end;
  z-index: 3;
  cursor: pointer;
}

.mascot .snake,
.mascot .bot {
  display: none;
  align-items: flex-end;
  gap: 3px;
}

body[data-theme='gh'] .mascot .snake,
body[data-theme='claude'] .mascot .bot {
  display: flex;
}

/* Both mascots are made of the same squares as the grid, so they take the
   active palette automatically. */
.snake__seg,
.bot__body,
.bot__antenna {
  display: block;
  border-radius: 4px;
  background: var(--l3);
}

.snake__seg {
  width: 17px;
  height: 17px;
  border-radius: 5px;
  animation: slither 1.15s ease-in-out infinite;
}

/* Tail shades start at level 2 — level 1 is close enough to the page
   background that the tail would simply vanish. */
.snake__seg:nth-child(1) {
  animation-delay: 0ms;
  background: var(--l2);
}
.snake__seg:nth-child(2) {
  animation-delay: 90ms;
  background: var(--l3);
}
.snake__seg:nth-child(3) {
  animation-delay: 180ms;
  background: var(--l3);
}

.snake__head {
  position: relative;
  width: 25px;
  height: 25px;
  border-radius: 8px;
  background: var(--l4);
  animation-delay: 270ms;
}

@keyframes slither {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-4px);
  }
}

.snake__tongue {
  position: absolute;
  right: -7px;
  top: 60%;
  width: 7px;
  height: 2px;
  background: var(--accent);
  opacity: 0;
  animation: flick 2.6s ease-in-out infinite;
}

@keyframes flick {
  0%,
  86%,
  100% {
    opacity: 0;
    transform: scaleX(0.3);
  }
  90%,
  94% {
    opacity: 1;
    transform: scaleX(1);
  }
}

/* Needs to out-specify `.mascot .bot`, whose flex-end would shove the antenna
   to one side once the axis flips to a column. */
.mascot .bot {
  flex-direction: column;
  align-items: center;
  gap: 0;
}

.bot__antenna {
  width: 4px;
  height: 9px;
  border-radius: 2px;
  background: var(--l2);
  animation: bob 2.2s ease-in-out infinite;
}

.bot__body {
  position: relative;
  width: 36px;
  height: 31px;
  border-radius: 10px;
  background: var(--l4);
  animation: bob 2.2s ease-in-out infinite;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

@keyframes bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-3px);
  }
}

.eye {
  position: relative;
  display: block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--card-bg);
  transition: height 90ms var(--ease);
}

.snake__head .eye {
  position: absolute;
  top: 7px;
}

.snake__head .eye:nth-of-type(1) {
  left: 6px;
}
.snake__head .eye:nth-of-type(2) {
  left: 14px;
}

.eye b {
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  background: var(--card-bg);
  transition: transform 120ms var(--ease);
}

.mascot.is-blinking .eye {
  height: 1.5px;
}

/* Reactions to typing: everything speeds up and leans in. */
.mascot[data-state='typing'] .snake__seg,
.mascot[data-state='typing'] .bot__antenna,
.mascot[data-state='typing'] .bot__body {
  animation-duration: 0.42s;
}

.mascot[data-state='happy'] .snake__seg,
.mascot[data-state='happy'] .bot__body,
.mascot[data-state='happy'] .bot__antenna {
  animation: hop 0.42s var(--ease) 2;
}

@keyframes hop {
  0%,
  100% {
    transform: translateY(0) scale(1);
  }
  40% {
    transform: translateY(-9px) scale(1.08);
  }
}

.mascot__say {
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  margin: 0;
  padding: 0.28rem 0.6rem;
  border-radius: 8px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-size: 11px;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(4px) scale(0.94);
  transform-origin: 85% 100%;
  transition: all 220ms var(--ease);
  pointer-events: none;
}

.mascot__say.is-on {
  opacity: 1;
  transform: translateY(0) scale(1);
}

.mascot__say::after {
  content: '';
  position: absolute;
  right: 14px;
  top: 100%;
  border: 5px solid transparent;
  border-top-color: var(--line);
}

/* --- call to action -------------------------------------------------------- */

.cta {
  display: flex;
  justify-content: center;
  padding: 2.75rem 0 1rem;
}

.btn-download {
  background: var(--accent);
  border: 0;
  border-radius: 9px;
  color: var(--accent-ink);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0.85rem 2.4rem;
  cursor: pointer;
  box-shadow: 0 10px 30px -12px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: all 180ms var(--ease);
}

.btn-download:hover,
.btn-download:focus-visible {
  outline: none;
  transform: translateY(-2px);
  filter: brightness(1.08);
  box-shadow: 0 16px 38px -12px color-mix(in srgb, var(--accent) 80%, transparent);
}

.btn-download:active {
  transform: translateY(0);
}

/* --- footer ---------------------------------------------------------------- */

.foot {
  width: var(--shell);
  margin: 0 auto;
  padding: 1.25rem 0 2.5rem;
  text-align: center;
  font-size: 12px;
  color: var(--ink-faint);
}

.foot p {
  margin: 0;
}

.foot__heart {
  font-size: 11px;
  display: inline-block;
  animation: beat 2.4s var(--ease) infinite;
}

@keyframes beat {
  0%,
  70%,
  100% {
    transform: scale(1);
  }
  78% {
    transform: scale(1.25);
  }
  86% {
    transform: scale(1.05);
  }
}

.foot a {
  color: var(--ink-dim);
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
  transition: color 180ms var(--ease);
}

.foot a:hover {
  color: var(--accent);
}

/* --- narrow screens -------------------------------------------------------- */

@media (max-width: 860px) {
  :root {
    --shell: calc(100% - 2rem);
  }

  .topbar {
    padding: 1.25rem 0 1.75rem;
  }

  /* Stack the handle under the word rather than squeezing both onto one line. */
  .entry {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
  }

  .handle-field {
    padding-bottom: 0;
    justify-content: space-between;
  }

  #handle,
  #handle:focus {
    width: 16ch;
  }

  .card {
    padding: 0.9rem 0.85rem 0.8rem;
  }

  .card__head,
  .card__foot {
    gap: 0.4rem;
  }

  .card__scroll {
    -webkit-overflow-scrolling: touch;
  }

  /* The Mon/Wed/Fri column costs 35px that the squares need more, and at this
     scale the labels are illegible anyway. */
  .card__grid {
    grid-template-columns: max-content;
    gap: 4px 0;
  }

  .days {
    display: none;
  }

  .months,
  .cells {
    grid-column: 1;
  }

  .months {
    height: 13px;
    font-size: 9.5px;
  }

  .card__count,
  .card__handle,
  .card__streak {
    font-size: 12px;
  }

  .mascot {
    right: 8px;
    transform: scale(0.85);
    transform-origin: 100% 100%;
  }

  .cta {
    padding: 2rem 0 0.5rem;
  }

  .btn-download {
    width: 100%;
    padding: 0.95rem 1rem;
  }
}

@media (max-width: 480px) {
  .mark__word {
    font-size: 13px;
  }

  .seg button {
    padding: 0.42rem 0.65rem;
    font-size: 11px;
  }

  .presets {
    gap: 0.35rem;
  }

  .presets button {
    font-size: 11.5px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
