/* style.css - colours, body size and fonts come from the variables at the top. */

/* fonts */
/* Saitamaar is the body face, self-hosted and subset to the ~540 glyphs this site shows.
   add a character outside that range and it needs re-cutting (fonttools, throwaway venv):

     pyftsubset saitamaar.ttf \
       --unicodes="U+0020-007E,U+00A0-00FF,U+2010-205E,U+2190-2193,U+2500-257F,U+2744,U+300C,U+300D,U+3040-30FF" \
       --flavor=woff2 --output-file=font/saitamaar.woff2

   DotGothic16 sits below it as the Google Fonts fallback - see --f-head/--f-body. */
@font-face {
  font-family: "Saitamaar";
  src: url("font/saitamaar.woff2") format("woff2");
  font-display: swap;
  /* Saitamaar's box is roomy; these pin it to the real ink so layouts stay put. */
  ascent-override: 88%;
  descent-override: 12%;
  line-gap-override: 0%;
}

:root {
  --ink: #022859;
  --wall: #AFCAD1;
  --wall-img: url("img/wall-day.svg");
  --paper: #C4EEF2;
  --paper-soft: #FCFEFE;
  --mint: #AFCAD1;
  --bar: #022859;
  --bar-text: #FCFEFE;
  --head: #022859;
  --text: #022859;
  --muted: #2d4b7a;
  --link: #0b4aa0;
  --visited: #3a4f94;
  --mark: #7EBCF2;
  --accent: #0b5cc2;
  --accent-text: #FCFEFE;
  --chip: #FCFEFE;
  --shadow: #022859;

  /* aliased to the frame's colours, so the dark block needs no override. */
  --clock-bg: var(--paper);
  --clock-fg: var(--text);

  /* page box width. the pat egg's right offset is derived from it too. */
  --box: 760px;

  /* floor under the box height; the taller side column normally sets it. */
  --box-h: 620px;

  /* small-and-dense body copy. --measure caps prose; 48ch fills the centre column. */
  --fs-body: 14px;
  --lh-body: 1.35;
  --measure: 48ch;

  /* --f-logo keeps DotGothic16: Saitamaar's kana are proportional, so the wordmark sat uneven. */
  --f-logo: "DotGothic16", "Saitamaar", "Courier New", monospace;
  --f-head: "Saitamaar", "DotGothic16", "Courier New", monospace;
  --f-body: "Saitamaar", "DotGothic16", "Courier New", monospace;
}

:root[data-theme="dark"] {
  --ink: #010f26;
  --wall: #022859;
  --wall-img: url("img/wall-night.svg");
  --paper: #124282;
  --paper-soft: #0a3270;
  --mint: #1a4d94;
  --bar: #7EBCF2;
  --bar-text: #022859;
  --head: #C4EEF2;
  --text: #FCFEFE;
  --muted: #AFCAD1;
  --link: #7EBCF2;
  --visited: #C4EEF2;
  --mark: #7EBCF2;
  --accent: #7EBCF2;
  --accent-text: #022859;
  --chip: #124282;
  --shadow: #010a1a;
}

/* theme transition */
/* transition `color` only where a text colour is set, or text snaps per DOM level.
   add a selector below whenever you declare a text `color`. */
*,
*::before,
*::after {
  transition:
    background-color 0.35s ease,
    border-color 0.35s ease,
    box-shadow 0.35s ease;
}

body,
a,
.site-title,
.tagline,
.marquee,
.nav-title,
.bar,
.nav-list a,
.theme-btn,
.stamp-note,
.col-main h1,
.col-main h2,
.sticker,
.avatar,
.chips li:nth-child(3n),
.post-date,
.pin,
.article .meta,
.shot,
.link-grid a,
.link-grid .ico,
.link-grid small,
.btn88,
textarea.code,
.feed-scroll b,
.foot-date,
.hit-counter,
.hit-label,
.folder-card,
.folder-count,
.folder-back,
.viewer-hint,
/* calendar/clock text colours come from theme variables, so they fade with them */
.cal-title,
.cal-nav,
.cal-table th,
.cal-table td,
.cal-table .is-today,
.clock-cap,
.clock-screen,
.pat-flair span {
  /* same timings, plus `color` */
  transition-property: background-color, border-color, box-shadow, color;
}

/* animated elements: no theme transition */
.marquee-track,
.pat-btn img {
  transition: none;
}

* { box-sizing: border-box; }

html { scrollbar-color: var(--bar) var(--wall); }

/* cursor */
/* doesn't animate on safari :( */
@keyframes cursor-anim {
  0.00% { cursor: url("data:image/webp;base64,UklGRpoAAABXRUJQVlA4TI0AAAAvH8AHECcgECA4d25DIEBIp5yAoMj/0eY/APBnSeCgttWwAQf8f2qAtyrYLNS/qTZkm4KI/k+AlDGXYie3Yje3vp0RkZNyRHnSZDQ5spgUj/7FdXKdo+Pk+A3vD0wsXtYgGgtyUACOykUInNVeNSCxqpt7IO4iF/1gx45WwgLFstw08qq5Nfk3klSSVnMA") 0 0, auto; }
  25.00% { cursor: url("data:image/webp;base64,UklGRqIAAABXRUJQVlA4TJYAAAAvH8AHEC8gECD4n3JmQyBASLOmHEG2zWY29Jt9/gMA/DPlZOCgbSNBmmGwrXQAJv9H4B/Bgzj+YHZv9o9BRP8nQMroS7GTW7GbW//OiMjOcMRwp8gosmXRGSz9xHVyna3j5HiGzxc6Fi+rEYUF2RgAjq7A2SpAnTE5G2JWoxZ+QFigu+GikO+KqZBy4/f2RrGSpKE5F30=") 0 0, auto; }
  50.00% { cursor: url("data:image/webp;base64,UklGRqAAAABXRUJQVlA4TJQAAAAvH8AHEB8gEEjaH3oNAUHRdcsJCIr8H23+A/BXgaNIkhynzyI4uUWzYuDt24/I7EsIdGbO8hKNmVUchIj+T8A+gLqHPvEknsDzd4BA2NSmwhlnFMqVb13TSDm9lLom5Tco1/x9E45yI2xdpxkA5LR8Ca73BMBy/RGrur4YAK6uKfUkAFaUXwDgynwTzMzBKPv9bi90") 0 0, auto; }
  75.00% { cursor: url("data:image/webp;base64,UklGRpYAAABXRUJQVlA4TIoAAAAvH8AHECcgECD4n3JmQyBASLOmnECA4H/KmfkPAPBnysBBI0mCsuvgZhxsgwJQgH9Zfz8HKIjo/wRIXblUJ31Up3307a6qTparlpOha+jIIlls/U8CT7TNXu/M4mEFNVjQwQJwpQJ3NICSdXEH4qpgNv6BsEB3y8Mg3w2XQeqDz9MHw06Slq69yQE=") 0 0, auto; }
}
html { animation: cursor-anim 2000ms step-end infinite; }
a,button,input,textarea,label,[role=button],select,option { cursor: inherit !important; }

@media (prefers-reduced-motion: reduce) {
  /* the first frame stands in for the animation */
  html { animation: none; cursor: url("data:image/webp;base64,UklGRpoAAABXRUJQVlA4TI0AAAAvH8AHECcgECA4d25DIEBIp5yAoMj/0eY/APBnSeCgttWwAQf8f2qAtyrYLNS/qTZkm4KI/k+AlDGXYie3Yje3vp0RkZNyRHnSZDQ5spgUj/7FdXKdo+Pk+A3vD0wsXtYgGgtyUACOykUInNVeNSCxqpt7IO4iF/1gx45WwgLFstw08qq5Nfk3klSSVnMA") 0 0, auto; }
}

body {
  margin: 0;
  /* top padding leaves room for the header kitty to sit above the frame */
  padding: 58px 16px 48px;
  background-color: var(--wall);
  background-image: var(--wall-img);
  background-size: 64px 64px;
  image-rendering: pixelated;
  color: var(--text);
  font-family: var(--f-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: 0.01em;
  overflow-wrap: break-word;   /* long words wrap instead of stretching the page */
}

img { image-rendering: pixelated; max-width: 100%; height: auto; }

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

a { color: var(--link); text-underline-offset: 3px; }
a:visited { color: var(--visited); }
a:hover { background: var(--mark); color: var(--ink); text-decoration-style: wavy; }
a:focus-visible,
button:focus-visible {
  outline: 3px dashed var(--accent);
  outline-offset: 3px;
}

.skip {
  position: absolute;
  left: -999px;
  top: 8px;
  background: var(--paper);
  border: 3px solid var(--ink);
  padding: 4px 10px;
  z-index: 50;
}
.skip:focus { left: 8px; }

/* page shell */

.wrap {
  max-width: var(--box);
  margin: 0 auto;
  position: relative;
}

.top {
  position: relative;
  /* right padding reserves room for the corner sticker; sync if its size changes. */
  padding: 0 calc(208px + 30px + 16px) 20px 20px;
  /* 118px: this height sets where the frame's top edge lands. */
  min-height: 118px;
}

.site-title {
  display: inline-block;
  margin: 14px 0 0;
  padding: 6px 18px 10px;
  background: var(--paper);
  border: 3px solid var(--ink);
  box-shadow: 5px 5px 0 var(--shadow);
  transform: rotate(-1.6deg);
  font-family: var(--f-logo);
  font-weight: 700;
  font-size: clamp(26px, 7vw, 52px);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--head);
  text-decoration: none;
  text-shadow: 3px 3px 0 var(--mark);
}
.site-title:visited { color: var(--head); }
.site-title:hover { background: var(--paper); color: var(--accent); }

.tagline {
  margin: 10px 0 0 34px;
  font-size: 13px;
  color: var(--text);
  background: var(--paper);
  display: inline-block;
  padding: 0 10px;
  border: 2px solid var(--ink);
  transform: rotate(0.8deg);
}

.top .cat-wrap {
  position: absolute;
  right: 30px;
  bottom: -6px;
  /* rendered peek width; breakpoints shrink it, so keep it in one place. */
  --cat-w: 208px;
  width: var(--cat-w);
  height: 158px;                 /* just clears the tallest sticker (peek: 455/610 x 208 = 155.2px) */
  z-index: 3;
  pointer-events: none;
  /* clip 6px in so the sticker line lands on the frame's top edge. */
  clip-path: inset(0 0 6px 0);
}

.top .cat {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: auto;
  /* diving down reads as falling, so it accelerates */
  transition-property: transform;
  transition-duration: 0.35s;
  transition-timing-function: cubic-bezier(0.5, 0, 0.8, 0.5);
  transition-delay: 0s;
}

/* each art file has transparent bottom padding; nudge it up so ink meets the frame. */
.top .cat-peek { bottom: calc(6px - 11 / 610 * var(--cat-w)); }

/* sleepy is wider; 91% keeps its visible art a touch narrower than peek's. */
.top .cat-sleepy {
  width: 91%;
  left: 50%;
  bottom: calc(6px - 17 * 0.91 / 668 * var(--cat-w));
}

/* day mode: peek out, sleepy parked below the page edge */

.top .cat-peek {
  transform: translateY(0);
  transition-duration: 0.45s;
  transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: 0.28s;
}
/* 130px clears sleepy's 122px art */
.top .cat-sleepy {
  transform: translateX(-50%) translateY(130px);
}

/* night mode: sleepy out, peek parked below the page edge */

/* 110px clears peek's 98px art */
:root[data-theme="dark"] .top .cat-peek {
  transform: translateY(110px);
  transition-duration: 0.35s;
  transition-timing-function: cubic-bezier(0.5, 0, 0.8, 0.5);
  transition-delay: 0s;
}
:root[data-theme="dark"] .top .cat-sleepy {
  transform: translateX(-50%) translateY(0);
  transition-duration: 0.45s;
  transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: 0.28s;
}

.frame {
  background: var(--paper);
  border: 3px solid var(--ink);
  box-shadow: 7px 7px 0 var(--shadow);
  overflow: hidden;
  /* column so marquee/footer keep their height and .cols takes the rest. */
  display: flex;
  flex-direction: column;
  min-height: var(--box-h);
}

.marquee {
  flex: 0 0 auto;
  overflow: hidden;
  white-space: nowrap;
  background: var(--bar);
  color: var(--bar-text);
  border-bottom: 3px solid var(--ink);
  font-family: var(--f-head);
  font-size: 13px;
  padding: 3px 0;
}
.marquee-track {
  display: inline-flex;
  animation: slide 150s linear infinite;
}
.marquee-track span { padding-right: 2.2em; }
@keyframes slide { to { transform: translateX(-50%); } }

.cols {
  display: grid;
  /* both sides 190px; the taller one sizes the box, see .col-main. */
  grid-template-columns: 190px minmax(0, 1fr) 190px;
  grid-template-areas: "nav main feed";
  gap: 0;
  flex: 1 1 auto;   /* fills the box when the --box-h floor wins */
  min-height: 0;
}

/* only the middle column scrolls: the sides must be seen whole. */
.col-nav {
  grid-area: nav;
  background: var(--mint);
  border-right: 3px solid var(--ink);
  padding: 14px 12px 18px;
}
.col-main {
  grid-area: main;
  padding: 20px 20px 26px;
  min-width: 0;
  overflow-y: auto;
  scrollbar-color: var(--bar) var(--paper);
  /* size containment keeps long posts from stretching the box; the stacked query undoes it. */
  contain: size;
}
.col-feed {
  grid-area: feed;
  background: var(--paper-soft);
  border-left: 3px solid var(--ink);
  padding: 14px 12px 18px;
}

/* keyboard focus ring lets arrow/PageUp scroll the prose; the skip link lands here. */
.col-main:focus-visible { outline: 3px dashed var(--accent); outline-offset: -3px; }

/* nav */

.nav-title,
.bar {
  margin: 0;
  background: var(--bar);
  color: var(--bar-text);
  font-family: var(--f-head);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.3;
  padding: 3px 10px;
  border: 3px solid var(--ink);
}

.nav-list {
  list-style: none;
  margin: 0 0 18px;
  padding: 8px 0 8px;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  border-top: 0;
}
.nav-list a {
  display: block;
  /* 28px clears the 16px heart marker; the tight right keeps "guestbook" on one line. */
  padding: 2px 8px 2px 28px;
  font-family: var(--f-head);
  font-size: 16px;
  text-decoration: none;
  color: var(--text);
  position: relative;
}
.nav-list a:visited { color: var(--text); }
.nav-list a::before {
  content: "";
  position: absolute;
  /* a real icon size, so the pixel art draws 1:1 instead of resampling. */
  left: 9px;
  top: 5px;
  width: 16px;
  height: 16px;
  background: url("img/icons/blue_heart.ico") center / contain no-repeat;
  opacity: 0.65;
}
.nav-list a:hover { background: var(--mark); color: var(--ink); }
.nav-list a:hover::before { opacity: 1; }
.nav-list a[aria-current="page"] {
  background: var(--mark);
  color: var(--ink);
  font-weight: 700;
}
.nav-list a[aria-current="page"]::before { opacity: 1; background-image: url("img/heart.svg"); }

/* the "things i like" category opens, so its row is a button rather than a link. */

.nav-sub-toggle {
  display: block;
  width: 100%;
  position: relative;
  /* same geometry as .nav-list a: 28px clears the 16px heart marker. */
  padding: 2px 26px 2px 28px;
  text-align: left;
  background: none;
  border: 0;
  font-family: var(--f-head);
  font-size: 16px;
  line-height: 1.35;
  color: var(--text);
}
.nav-sub-toggle:hover { background: var(--mark); color: var(--ink); }
.nav-sub-toggle::before {
  content: "";
  position: absolute;
  left: 9px;
  top: 5px;
  width: 16px;
  height: 16px;
  background: url("img/icons/blue_heart.ico") center / contain no-repeat;
  opacity: 0.65;
}
.nav-sub-toggle:hover::before,
.nav-sub-toggle[aria-expanded="true"]::before { opacity: 1; }

/* Saitamaar's subset has no pointing triangles, so borders draw the caret. */
.nav-caret {
  position: absolute;
  right: 10px;
  top: 8px;
  width: 0;
  height: 0;
  border-left: 6px solid var(--text);
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  transition: transform 0.18s ease;
}
.nav-sub-toggle[aria-expanded="true"] .nav-caret { transform: rotate(90deg); }

.nav-sub {
  list-style: none;
  margin: 0 0 2px 16px;
  padding: 2px 0 4px 10px;
  border-left: 2px dotted var(--muted);
}
.nav-sub a { padding: 2px 6px 2px 20px; font-size: 15px; }
.nav-sub a::before { left: 4px; top: 6px; width: 13px; height: 13px; }
.nav-sub[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .nav-caret { transition: none; }
}

.theme-btn {
  display: block;
  width: 100%;
  margin: 0 0 20px;
  padding: 4px 8px;
  font-family: var(--f-head);
  font-size: 14px;
  color: var(--text);
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
  /* !important: the cursor pack forces cursor on every button. */
  cursor: pointer !important;
}
.theme-btn:hover { background: var(--mark); color: var(--ink); }
.theme-btn:active { box-shadow: none; transform: translate(3px, 3px); }

.stamp {
  display: block;
  margin: 0 auto 6px;
  border: 3px solid var(--ink);
  background: var(--paper-soft);
  padding: 2px;
  width: max-content;
  transform: rotate(2deg);
}
.stamp img { display: block; width: 88px; height: 31px; }
.stamp-note { font-size: 13px; text-align: center; margin: 0 0 4px; color: var(--muted); }

.sprite-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-top: 26px;
}
.sprite-row img { width: 56px; height: auto; }
.sprite-row img:nth-child(2) { width: 46px; margin-bottom: 4px; }

/* main content */

.col-main h1 {
  margin: 0 0 12px;
  font-family: var(--f-head);
  font-size: clamp(28px, 7vw, 40px);
  line-height: 1.15;
  color: var(--head);
}
.col-main h2:not(.bar) {
  margin: 24px 0 8px;
  font-family: var(--f-head);
  /* 22px, not 25px: the old size wrapped "what you will find here". */
  font-size: clamp(18px, 4.6vw, 22px);
  line-height: 1.2;
  color: var(--head);
}
.col-main p { margin: 0 0 11px; max-width: var(--measure); }
.col-main ul:not(.plain) { max-width: var(--measure); padding-left: 22px; }

/* justify prose, with hyphens so a monospace face does not open rivers of gaps. */
.col-main p,
.col-main blockquote,
.col-main ul:not(.plain):not(.link-grid):not(.post-list):not(.gallery):not(.folder-grid) > li {
  text-align: justify;
  text-justify: inter-word;   /* Firefox justifies between letters otherwise */
  hyphens: auto;
  -webkit-hyphens: auto;      /* Safari still needs the prefix */
}

.box {
  position: relative;
  margin: 0 0 24px;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 4px 4px 0 var(--shadow);
}
.box > .bar { border: 0; border-bottom: 3px solid var(--ink); }
.box-body { padding: 12px 14px 6px; }
.box-body > :last-child { margin-bottom: 8px; }

/* guestbook */
/* third-party iframe brings its own styling; the border seats it in the page. */
.guestbook-embed {
  border: 3px solid var(--ink);
  background: var(--paper);
  overflow: hidden;
}
.guestbook-embed iframe {
  display: block;
  width: 100%;
  height: clamp(520px, 78vh, 900px);
  border: 0;
}

.hello { padding: 16px 16px 6px; background: var(--paper-soft); }
.hello h1 { margin-top: 0; }

.sticker {
  position: absolute;
  top: -14px;
  right: 18px;
  padding: 1px 10px;
  background: var(--accent);
  color: var(--accent-text);
  border: 3px solid var(--ink);
  font-family: var(--f-head);
  font-size: 13px;
  transform: rotate(4deg);
}

.keeper-row {
  display: grid;
  grid-template-columns: 100px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
.avatar {
  width: 100px;
  height: 100px;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 8px;
  font-size: 13px;
  line-height: 1.3;
  color: var(--muted);
  border: 3px dashed var(--ink);
  background: var(--mint);
  transform: rotate(-2deg);
}

.thumbs { display: flex; gap: 14px; margin: 4px 0 12px; flex-wrap: wrap; }
.thumbs a {
  display: grid;
  place-items: center;
  width: 84px;
  height: 70px;
  background: var(--tint, var(--mint));
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
}
.thumbs li:nth-child(1) a { transform: rotate(-2deg); }
.thumbs li:nth-child(2) a { transform: rotate(1.5deg); }
.thumbs li:nth-child(3) a { transform: rotate(-1deg); }
.thumbs a:hover { background: var(--mark); }
/* fit previews inside the frame at any aspect ratio; photos get smooth rendering. */
.thumbs img {
  max-width: 56px;
  max-height: 56px;
  width: auto;
  height: auto;
  object-fit: contain;
  image-rendering: auto;
}

.chips { list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chips li {
  padding: 0 10px;
  border: 2px dashed var(--ink);
  background: var(--chip);
  font-size: 13px;
}
.chips li:nth-child(odd)  { transform: rotate(-1.2deg); }
.chips li:nth-child(even) { transform: rotate(1deg); }
.chips li:nth-child(3n)   { background: var(--mark); color: var(--ink); }

.plain { list-style: none; margin: 0; padding: 0; }

.post-list { list-style: none; margin: 0; padding: 0; }
.post-list > li {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr);
  gap: 14px;
  padding: 12px 0;
  border-top: 2px dotted var(--muted);
}
.post-list > li:first-child { border-top: 0; }
.post-date {
  align-self: start;
  text-align: center;
  font-family: var(--f-head);
  font-size: 13px;
  line-height: 1.25;
  padding: 3px 4px;
  background: var(--mark);
  color: var(--ink);
  border: 2px solid var(--ink);
}
.post-list h2, .post-list h3 {
  margin: 0 0 2px;
  font-family: var(--f-head);
  font-size: clamp(18px, 5vw, 21px);
  line-height: 1.25;
}
.post-list p { margin: 0 0 6px; font-size: 13px; }   /* teaser: a step under body copy */
.post-list .chips { margin: 0; }
.post-list .chips li { font-size: 12px; }

.pin {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  font-size: 12px;
  font-family: var(--f-head);
  background: var(--accent);
  color: var(--accent-text);
  border: 2px solid var(--ink);
  vertical-align: middle;
  transform: rotate(-3deg);
}

/* article */
.article h1 { font-size: clamp(26px, 7vw, 36px); }
.article .meta { color: var(--muted); font-size: 13px; margin: 0 0 22px; }
.article blockquote {
  margin: 18px 0;
  padding: 6px 16px;
  border-left: 6px solid var(--bar);
  background: var(--paper-soft);
  max-width: 42ch;   /* a step in from --measure so quotes read inset */
}
.article code {
  padding: 0 5px;
  background: var(--chip);
  border: 2px solid var(--ink);
  font-size: 13px;
}
.article .after {
  margin-top: 30px;
  padding-top: 12px;
  border-top: 3px double var(--ink);
  display: flex;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* gallery */
.gallery {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: grid;
  /* 128px, not 160px: at 160px the whole gallery collapsed to one column. */
  grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
  gap: 18px 16px;
}
.gallery li { margin: 0; }
/* tilt in a variable so hover transforms compose instead of cancelling it. */
.gallery li:nth-child(odd)  { --rot: -0.8deg; }
.gallery li:nth-child(even) { --rot: 0.9deg; }
.gallery li.wide { grid-column: span 2; }
.shot {
  display: block;
  padding: 6px 6px 4px;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 4px 4px 0 var(--shadow);
  text-decoration: none;
  color: var(--text);
  transform: rotate(var(--rot, 0deg));
  /* no transition here: hover only changes transform, and that snaps. */
}
.shot:visited { color: var(--text); }
/* hover is one small step up, and it is instant: nothing eases in or out. */
.shot:hover { transform: rotate(var(--rot, 0deg)) scale(1.04); }
.shot .pic {
  display: grid;
  place-items: center;
  /* a definite row makes the img's max-height: 100% count; auto counts as none. */
  grid-template-rows: 100%;
  height: 116px;
  padding: 4px;
  overflow: hidden;
  border: 2px solid var(--ink);
  background: var(--tint, var(--mint));
}
.wide .shot .pic { height: 116px; }
/* scale to fit so previews stay uniform; smooth rendering because these are photos. */
.shot .pic img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  image-rendering: auto;
}
.shot .cap { display: block; padding-top: 5px; font-size: 12px; line-height: 1.3; }
.shot.empty {
  background: transparent;
  box-shadow: none;
  border-style: dashed;
  color: var(--muted);
}
.shot.empty .pic { height: auto; min-height: 116px; border-style: dashed; background: transparent; padding: 10px; text-align: center; font-size: 13px; line-height: 1.35; }

/* gallery: folders */
.folder-grid {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: grid;
  /* same 128px as .gallery, to keep the folder cards two-up in a .box-body. */
  grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
  gap: 18px 16px;
}
.folder-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 8px 8px;
  text-align: center;
  text-decoration: none;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 4px 4px 0 var(--shadow);
  color: var(--text);
  /* same as .shot: no transition, so the card snaps rather than easing. */
}
.folder-card:visited { color: var(--text); }
/* the card grows a step on hover and that is all: instant, no colour shift. */
.folder-card:hover { transform: scale(1.04); }
.folder-card:active { box-shadow: none; transform: translate(3px, 3px); }
.folder-icon { display: block; width: 80px; height: auto; }
.folder-name { font-family: var(--f-head); font-size: 15px; line-height: 1.25; }
.folder-count { font-size: 13px; line-height: 1.2; color: var(--muted); }

/* gallery: inside a folder */
/* the two boxes swap by the hidden attribute, so there is nothing to animate. */
#gallery-root[hidden],
#gallery-folder-view[hidden] { display: none; }

.folder-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
}
.folder-back {
  display: inline-block;
  padding: 0 8px;
  font-family: var(--f-head);
  font-size: 13px;
  text-decoration: none;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
  color: var(--text);
}
.folder-back:visited { color: var(--text); }
.folder-back:hover { background: var(--mark); color: var(--ink); }
.folder-title { font-family: var(--f-head); font-size: 16px; }

/* gallery: the picture viewer */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 20px;
}
.viewer[hidden] { display: none; }
.viewer-backdrop {
  position: absolute;
  inset: 0;
  --backdrop: rgba(1, 15, 38, 0.86);
  background: var(--backdrop);
  /* !important: the cursor pack forces cursor on every <a>; this is the close backdrop. */
  cursor: zoom-out !important;
}
/* a text-less link has nothing to highlight, so keep the backdrop colour on hover. */
.viewer-backdrop:hover { background: var(--backdrop); }
.viewer-figure {
  position: relative;
  margin: 0;
  padding: 14px 14px 10px;
  background: var(--paper);
  border: 3px solid var(--ink);
  box-shadow: 6px 6px 0 var(--shadow);
  max-width: min(94vw, 1200px);
  /* fitted picture height, and the taller box once zoomed (the frame stops hugging then). */
  --frame-h: 74vh;
  --zoom-h: 92vh;
  /* no transition on the figure: the picture appears and leaves in one step. */
}
.viewer-frame {
  display: grid;
  place-items: center;
  padding: 24px;
  border: 2px solid var(--ink);
  background: var(--tint, var(--mint));
}
/* fit to screen; a fixed width made big sheets postage-stamp tiny. */
.viewer-frame img {
  max-width: min(88vw, 1160px);
  max-height: calc(var(--frame-h) - 56px);   /* the frame's padding + border, plus a little slack */
  width: auto;
  height: auto;
  object-fit: contain;
  image-rendering: auto;
}
/* zoomed: the frame becomes its own scroll window instead of hugging the picture. */
.viewer.is-zoomable .viewer-frame img { cursor: zoom-in; }
.viewer.is-zoomed .viewer-figure {
  display: flex;
  flex-direction: column;
  width: min(96vw, 1400px);
  max-width: min(96vw, 1400px);
  height: var(--zoom-h);
}
.viewer.is-zoomed .viewer-frame { flex: 1 1 0; min-height: 0; overflow: auto; }
.viewer.is-zoomed .viewer-frame img { max-width: none; max-height: none; cursor: zoom-out; }
.viewer-hint { display: none; padding-top: 4px; font-size: 13px; color: var(--muted); }
.viewer.is-zoomable .viewer-hint { display: block; }
.viewer figcaption { padding-top: 8px; font-size: 13px; }
.viewer-close { position: relative; display: inline-block; margin-top: 6px; }
html.gallery-locked { overflow: hidden; }

/* things i like */

.likes-grid {
  display: grid;
  /* a fixed 128px column keeps a cover at its own size instead of stretching it. */
  grid-template-columns: repeat(auto-fill, 128px);
  justify-content: start;
  gap: 18px 16px;
  margin: 12px 0 8px;
  /* a tall cover must not push the covers beside it down. */
  align-items: start;
}

/* the cover is the whole control: the image and nothing else, no frame or background. */
.like-tile {
  display: block;
  padding: 0;
  border: 0;
  background: none;
}
.like-tile img {
  display: block;
  width: 100%;
  height: auto;
  /* box art and album art are photos; the global img rule is for the site's pixel art. */
  image-rendering: auto;
}
/* the only sign of hover is a small grow, and it is instant on purpose: no transition. */
.like-tile:hover { transform: scale(1.04); }

/* the why-text is not a box: it spans the grid, sitting in the row gap it opens. */
.like-why-row {
  grid-column: 1 / -1;
  padding: 2px 0 4px;
}
.like-why-row[hidden] { display: none; }
.like-why-row h3 {
  margin: 0 0 6px;
  font-family: var(--f-head);
  font-size: 16px;
  line-height: 1.3;
}
.like-why-row p { margin: 0 0 8px; }
.like-why-row p:last-child { margin-bottom: 0; }

/* links page */
.link-grid {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
}
.link-grid a {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
  text-decoration: none;
  color: var(--text);
}
.link-grid a:visited { color: var(--text); }
.link-grid a:hover { background: var(--mark); color: var(--ink); }
.link-grid .ico {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  font-family: var(--f-head);
  font-weight: 700;
  font-size: 17px;
  color: var(--ink);
  background: var(--c, var(--mint));
  border: 2px solid var(--ink);
}
/* icon centred at a real .ico size, so the pixel art stays crisp */
.link-grid .ico img { display: block; width: 32px; height: 32px; }
.link-grid strong { display: block; font-family: var(--f-head); font-size: 16px; line-height: 1.2; }
.link-grid small { display: block; color: var(--muted); font-size: 13px; line-height: 1.3; }
.link-grid a:hover small { color: var(--ink); }

.btn88-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 14px; }
.btn88 {
  width: 88px;
  height: 31px;
  display: grid;
  place-items: center;
  border: 2px solid var(--ink);
  background: var(--c, var(--mint));
  color: var(--ink);
  font-family: var(--f-head);
  font-size: 12px;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  image-rendering: auto;
}
.btn88:visited { color: var(--ink); }
.btn88:hover { background: var(--mark); }

textarea.code {
  width: 100%;
  max-width: var(--measure);
  height: 78px;
  padding: 8px;
  font-family: var(--f-body);
  font-size: 13px;
  line-height: 1.4;
  color: var(--text);
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  resize: vertical;
}

/* right column */

.feed-box {
  margin: 0 0 22px;
  border: 3px solid var(--ink);
  background: var(--paper);
}
.feed-box .bar { border: 0; border-bottom: 3px solid var(--ink); }
.feed-scroll {
  /* no inner scroller; wrap words whole, or the bold label chops them in half. */
  padding: 8px 12px;
  overflow-wrap: normal;
}
.feed-scroll p { margin: 0 0 10px; font-size: 13px; line-height: 1.5; }
.feed-scroll b {
  font-family: var(--f-head);
  font-weight: 700;
  background: var(--mark);
  color: var(--ink);
  padding: 0 4px;
  margin-right: 6px;
}

/* right column: calendar, Italy clock and the "right now i'm..." note */
/* same .feed-box furniture as the updates box, so the column reads as one stack. */

.cal-box {
  margin: 0 0 22px;
  border: 3px solid var(--ink);
  background: var(--paper-soft);
  box-shadow: 4px 4px 0 var(--shadow);
}

/* the month line: a .bar with an arrow at either end */
.cal-head {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 1px 3px;
  background: var(--bar);
  border-bottom: 3px solid var(--ink);
}
.cal-title {
  flex: 1 1 auto;
  margin: 0;
  text-align: center;
  font-family: var(--f-head);
  font-weight: 600;
  font-size: 14px;
  line-height: 1.5;
  color: var(--bar-text);
  white-space: nowrap;
}
.cal-nav {
  flex: 0 0 auto;
  width: 20px;
  padding: 0;
  font-family: var(--f-head);
  font-size: 17px;
  line-height: 1.4;
  color: var(--bar-text);
  background: none;
  border: 0;
  /* !important: see "cursor" near the top of this file */
  cursor: pointer !important;
}
.cal-nav:hover { background: var(--mark); color: var(--ink); }

.cal-grid { padding: 6px 4px 5px; }
.cal-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-family: var(--f-head);
  font-size: 13px;
  text-align: center;
}
.cal-table th {
  padding: 0 0 3px;
  font-weight: 600;
  font-size: 11px;
  color: var(--muted);
}
.cal-table td {
  padding: 1px 0;
  line-height: 1.45;
  color: var(--text);
}
.cal-table .is-blank { color: transparent; }
.cal-table .is-today {
  background: var(--mark);
  color: var(--ink);
  font-weight: 700;
  /* inset shadow highlights the cell without changing row height */
  box-shadow: inset 0 0 0 2px var(--ink);
}

/* flavour days: the icon stands in for the day number, and a note opens on hover/focus */

.cal-table td.has-flavor { position: relative; }
.cal-flavor {
  /* fill the cell, so the icon centres and the note hangs off the top edge */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cal-flavor img { display: block; width: 8px; height: 8px; }
.cal-tip {
  display: none;
  position: absolute;
  right: 0;
  bottom: 100%;
  margin-bottom: 3px;
  /* over the weekday header and the rows above */
  z-index: 5;
  white-space: nowrap;
  padding: 2px 6px;
  font-family: var(--f-head);
  font-size: 12px;
  line-height: 1.4;
  color: var(--bar-text);
  background: var(--bar);
  border: 2px solid var(--ink);
  box-shadow: 2px 2px 0 var(--shadow);
}
/* the whole day is the target: an 8px icon is fiddly to hit on its own. */
.cal-table td.has-flavor:hover .cal-tip,
.cal-flavor:focus .cal-tip { display: block; }

.clock { margin: 0 0 22px; text-align: center; }
.clock-cap {
  margin: 0 0 4px;
  font-family: var(--f-head);
  font-weight: 600;
  font-size: 13px;
  color: var(--muted);
}
.clock-screen {
  display: block;
  padding: 4px 6px 5px;
  background: var(--clock-bg);
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
  font-family: var(--f-head);
  font-weight: 700;
  font-size: 26px;
  line-height: 1.2;
  letter-spacing: 0.05em;
  /* Saitamaar advances are asymmetric; 0.19em (~5px) recentres the digits. */
  text-indent: 0.19em;
  color: var(--clock-fg);
  /* tabular digits, so the number never shifts */
  font-variant-numeric: tabular-nums;
}
.clock-sep {
  /* cancel the colon's off-centre advance so its gaps look even */
  margin: 0 0.06em 0 -0.06em;
  /* LCD-style blink; steps(1) makes it hard on/off */
  animation: clock-blink 1s steps(1, end) infinite;
}
@keyframes clock-blink { 50% { opacity: 0.15; } }

.mini-pics { display: flex; gap: 10px; align-items: flex-end; justify-content: flex-end; }
.mini-pics img { height: auto; }
.mini-pics img:nth-child(1) { width: 58px; }
.mini-pics img:nth-child(2) { width: 62px; margin-bottom: -2px; }

/* footer */

.foot {
  /* a flex item of .frame: it keeps its own height under .cols */
  flex: 0 0 auto;
  border-top: 3px solid var(--ink);
  background: var(--mint);
  position: relative;
  /* the 38px row plus this padding centres it evenly in the strip */
  padding: 8px 0;
}
.foot-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 14px;
}

.foot-date {
  margin: 0;
  font-size: 13px;
  color: var(--text);
  white-space: nowrap;
}

/* hit counter */
.hit-counter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 6px 12px;
  background: var(--paper-soft);
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
  font-family: var(--f-head);
  font-size: 13px;
  color: var(--text);
  transform: rotate(-0.5deg);
}
.hit-icon {
  font-size: 14px;
  line-height: 1;
}
#hit-count {
  font-family: var(--f-head);
  font-weight: 700;
  font-size: 14px;
  min-width: 3ch;
  text-align: right;
}
.hit-label {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* small screens */

/* the corner sticker reaches ~33px above the box, so keep this padding at least 40px */
@media (max-width: 1000px) {
  body { padding: 40px 10px 32px; }
}

/* header stops sitting beside the sticker; 760px is where the box would collide */
@media (max-width: 760px) {
  body { padding: 22px 10px 32px; }
  .top {
    padding: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  .site-title { margin-top: 4px; }
  .tagline { margin: 0 0 0 10px; max-width: 100%; }
  .top .cat-wrap {
    position: relative;
    right: auto;
    bottom: auto;
    align-self: center;
    --cat-w: min(66vw, 189px);
    height: auto;
    aspect-ratio: 610 / 455;   /* matches mitsu_peek.webp, the tallest sticker */
    margin: 0 0 -6px;          /* tuck the artwork down onto the frame's top edge */
  }
}

@media (max-width: 880px) {
  /* stacked, the box grows with the page; drop size containment here. */
  .col-main { contain: none; }
  .cols {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "nav" "main" "feed";
    /* a short page still fills the box with paper */
    min-height: 620px;
  }
  .col-nav { border-right: 0; border-bottom: 3px solid var(--ink); padding: 14px; }
  .col-feed { border-left: 0; border-top: 3px solid var(--ink); }
  .nav-list { display: flex; flex-wrap: wrap; padding: 6px 4px; border-top: 0; }
  .nav-list li { flex: 1 1 auto; }
  .nav-list a { padding: 2px 8px 2px 28px; }   /* 28px clears the 16px heart marker, same as desktop */
  /* the category takes its own line here, and its pages run along one. */
  .nav-list li.nav-group { flex: 1 0 100%; }
  .nav-sub {
    display: flex;
    flex-wrap: wrap;
    margin: 0 0 2px;
    padding: 0 0 0 16px;
    border-left: 0;
  }
  .col-nav .stamp,
  .col-nav .stamp-note,
  .col-nav .sprite-row { display: none; }
  .theme-btn { width: auto; margin-bottom: 0; }
  .col-main { padding: 20px 16px 26px; }
  .guestbook-embed iframe { height: 70vh; }
  .keeper-row { grid-template-columns: 1fr; }
  .gallery li.wide { grid-column: auto; }
  .hit-counter { transform: none; }
  /* full-width feed: keep the calendar and clock a sane size, centred */
  .cal-box,
  .clock { max-width: 300px; margin-inline: auto; }
  .foot-row { flex-direction: column; gap: 6px; text-align: center; }
}

@media (max-width: 560px) {
  body { padding: 18px 8px 28px; }
  .box-body { padding: 10px 12px 4px; }
  .hello { padding: 16px 14px 6px; }
  .sticker { font-size: 13px; right: 10px; }
  .marquee { font-size: 13px; }
  .top .cat-wrap { --cat-w: min(72vw, 160px); }
  .article .after { justify-content: flex-start; }
}

@media (max-width: 420px) {
  .post-list > li { grid-template-columns: 1fr; gap: 6px; }
  .post-date { justify-self: start; padding: 0 8px; }
  .nav-list a { font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
}

/* lists that are layout, not prose: no bullet indent */
.col-main ul.link-grid,
.col-main ul.post-list,
.col-main ul.gallery,
.col-main ul.folder-grid { padding-left: 0; }

img.avatar {
  object-fit: cover;
  padding: 0;
  border-style: solid;
  image-rendering: auto;
}

/* easter egg: pat the image (built in site.js) */

.pat {
  --pat-w: 104px;
  --pat-gap: 14px;           /* air between the cat and the box edge */
  --pat-hide: 64%;           /* how much of the image is tucked out of view */
  position: fixed;
  /* park the cat in the gutter beside .wrap; its right offset derives from --box. */
  right: calc((100vw - var(--box)) / 2 - var(--pat-w) - var(--pat-gap));
  bottom: 0;
  width: var(--pat-w);
  z-index: 30;
  transform: translateY(var(--pat-hide));
  transition: transform 0.28s cubic-bezier(0.2, 0.9, 0.3, 1);
}
.pat.is-open { transform: translateY(0); }

.pat-btn {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  /* !important: see "cursor" near the top of this file */
  cursor: pointer !important;
  line-height: 0;
  -webkit-tap-highlight-color: transparent;
}
.pat-btn img {
  display: block;
  width: 100%;
  height: auto;
  image-rendering: auto;
  transform-origin: 50% 100%;
  user-select: none;
}
.pat-btn.pop img { animation: pat-pop 0.16s ease-out; }
@keyframes pat-pop { 50% { transform: scale(0.93, 0.9); } }

/* flair above, counter below the image */
.pat-hud {
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}

.pat-count {
  margin: 0;
  padding: 1px 10px;
  white-space: nowrap;
  background: var(--paper-soft);
  color: var(--text);
  border: 3px solid var(--ink);
  box-shadow: 3px 3px 0 var(--shadow);
  font-family: var(--f-head);
  font-size: 13px;
  line-height: 1.5;
  opacity: 0;
  transform: rotate(-2deg);
  transition: opacity 0.45s ease;      /* slow fade out */
}
.pat-count.show { opacity: 1; transition-duration: 0.1s; }

/* milestone flair ("patting spree!" and friends) */
.pat-flair {
  margin: 0;
  white-space: nowrap;
  opacity: 0;
  transform: rotate(-2deg);
  transform-origin: 100% 100%;
  transition: opacity 0.45s ease;
}
.pat-flair span {
  display: inline-block;
  padding: 0 12px;
  background: var(--accent);
  color: var(--accent-text);
  border: 3px solid var(--ink);
  box-shadow: 4px 4px 0 var(--shadow);
  font-family: var(--f-head);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.4;
}
.pat-flair.show { opacity: 1; transition-duration: 0.1s; }
.pat-flair.show span { animation: pat-shake 0.18s linear infinite; }   /* --shake and --tilt are set per tier in site.js */
.pat-flair.pop { animation: flair-pop 0.28s ease-out; }

/* after the last tier, the flair slowly fades (duration is set in site.js) */
.pat-flair.show.fading {
  opacity: 0;
  transition-property: opacity;
  transition-timing-function: linear;
  transition-duration: 30s;
}

@keyframes pat-shake {
  0%   { transform: translate(0, 0) rotate(0deg); }
  20%  { transform: translate(calc(var(--shake, 1px) * -1), calc(var(--shake, 1px) * 0.5)) rotate(calc(var(--tilt, 0.3) * -1deg)); }
  40%  { transform: translate(var(--shake, 1px), calc(var(--shake, 1px) * -0.6)) rotate(calc(var(--tilt, 0.3) * 1deg)); }
  60%  { transform: translate(calc(var(--shake, 1px) * -0.7), calc(var(--shake, 1px) * -0.4)) rotate(calc(var(--tilt, 0.3) * 0.6deg)); }
  80%  { transform: translate(calc(var(--shake, 1px) * 0.8), calc(var(--shake, 1px) * 0.6)) rotate(calc(var(--tilt, 0.3) * -0.6deg)); }
  100% { transform: translate(0, 0) rotate(0deg); }
}
@keyframes flair-pop {
  0%   { transform: rotate(-2deg) scale(0.6); }
  60%  { transform: rotate(-2deg) scale(1.15); }
  100% { transform: rotate(-2deg) scale(1); }
}

/* below 1012px the gutter cannot hold the cat, so hide it */
@media (max-width: 1011px) {
  .pat { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .pat { transition: none; }
  .clock-sep { animation: none; }
  .pat-btn.pop img { animation: none; }
  .pat-flair.show span,
  .pat-flair.pop { animation: none; }
  /* swap the header kitty instantly instead of animating it */
  .top .cat-peek,
  .top .cat-sleepy,
  :root[data-theme="dark"] .top .cat-peek,
  :root[data-theme="dark"] .top .cat-sleepy { transition: none; }
}