/* ============================================================================
   BOSATSU — site components
   ----------------------------------------------------------------------------
   Built only against the tokens in theme.css. No literal colours, no literal
   font families. Swap the theme and this all follows.
   ============================================================================ */

/* ---------------------------------------------------------------- shell --- */

.page {
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: clamp(var(--space-s), 5vw, var(--space-l));
}

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  flex-wrap: wrap;
  padding-block: var(--space-s);
  border-bottom: 1px solid var(--rule);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  border: 0;
  color: inherit;
}
.brand:hover { border: 0; }

.brand__name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.2;
}
.brand__qualifier {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* nav: the active page is marked with a small vermilion stamp, tying wayfinding
   to the signature rather than inventing a second visual language for it. */
.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
}
.site-nav a {
  font-size: 0.9375rem;
  color: var(--fg);
  border: 0;
  padding-block: var(--space-2xs);
  position: relative;
}
.site-nav a:hover { color: var(--accent); border: 0; }
.site-nav a[aria-current="page"] { color: var(--fg); }
.site-nav a[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset-inline-start: -0.6rem;
  inset-block-start: 50%;
  translate: 0 -50%;
  inline-size: 3px;
  block-size: 3px;
  background: var(--seal);
  border-radius: 1px;
}

.site-footer {
  margin-block-start: var(--space-2xl);
  padding-block: var(--space-m);
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-m);
  align-items: baseline;
  justify-content: space-between;
  font-size: 0.9375rem;
  color: var(--muted);
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-s); }

/* section rhythm — one rule, applied once, so nothing cancels out */
.section { padding-block-start: var(--space-xl); }
.section + .section { padding-block-start: var(--space-xl); }
.section__head { margin-block-end: var(--space-m); }

/* ----------------------------------------------------------------- hero --- */
/* The thesis, not a banner. Portrait is subordinate: a quiet column beside the
   words, never a full-bleed image — full-bleed would spend the restraint the
   rest of the page depends on. */

.hero {
  padding-block: clamp(var(--space-l), 9vw, var(--space-2xl)) var(--space-l);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(var(--space-m), 6vw, var(--space-xl));
  align-items: start;
}

.hero__seal { margin-block-end: var(--space-m); }

.hero__title {
  font-size: clamp(2.2rem, 1.3rem + 3.2vw, 3.6rem);
  margin-block-end: var(--space-s);
}

.hero__thesis {
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
  color: var(--muted);
  max-width: 32rem;
  margin-block-end: var(--space-m);
}

/* The brand bar: a held-greige vertical column carrying the three glyphs
   (writing · seal · speaking) on transparent grounds. Greige in both themes —
   a calm, constant brand block rather than a photograph. */
.hero__bar {
  inline-size: clamp(9rem, 18vw, 12rem);
  align-self: stretch;              /* fill the hero row: a true vertical bar */
  min-block-size: 22rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  gap: var(--space-m);
  padding: var(--space-l) var(--space-m);
}
.hero__bar img {
  inline-size: auto;
  max-inline-size: 100%;
  object-fit: contain;
}
/* The two kanji columns (first + last) read largest; the seal in the middle is
   sized up too, but kept a step smaller so it doesn't crowd them. */
.hero__bar img:first-child,
.hero__bar img:last-child { block-size: clamp(6.5rem, 15vw, 9rem); }
.hero__bar img:nth-child(2) { block-size: clamp(5.25rem, 12vw, 7rem); }

@media (max-width: 46rem) {
  .hero { grid-template-columns: minmax(0, 1fr); }
  /* The brand bar is a subordinate, decorative aside (aria-hidden). It only
     reads as intended when it can stand as a tall column beside the words;
     laid down into a phone-width band it looked cramped and off. Rather than
     ship a compromised version, drop it below the single-column breakpoint —
     the thesis carries the hero on its own. */
  .hero__bar { display: none; }
}


/* --------------------------------------------------------------- actions - */

.actions { display: flex; flex-wrap: wrap; gap: var(--space-s); align-items: center; }

.button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: 0.9375rem;
  padding: var(--space-2xs) var(--space-s);
  border: 1px solid var(--accent);
  border-radius: 2px;
  color: var(--accent);
  background: transparent;
  transition: background 140ms ease, color 140ms ease;
}
.button:hover { background: var(--accent); color: var(--bg); border-color: var(--accent); }

/* ------------------------------------------------------------- practice --- */
/* Five engagements. Deliberately NOT numbered: they're alternatives you choose
   between, not a sequence you move through, so numbering would assert an order
   that isn't true. Hairline-ruled rows instead of cards — cards would add five
   boxes to a page whose whole argument is negative space. */

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

.practice > li {
  border-top: 1px solid var(--rule);
  padding-block: var(--space-m);
  display: grid;
  grid-template-columns: minmax(12rem, 18rem) minmax(0, 1fr);
  gap: var(--space-s) clamp(var(--space-m), 5vw, var(--space-l));
  align-items: start;
}
.practice > li:last-child { border-bottom: 1px solid var(--rule); }

.practice h3 { margin: 0; }
.practice p { margin: 0; color: var(--muted); }

@media (max-width: 46rem) {
  .practice > li { grid-template-columns: minmax(0, 1fr); gap: var(--space-xs); }
}

/* --------------------------------------------------------------- topics --- */
/* The utility face carrying the breadth claim. Set as a dense field rather than
   a list: the point is the extent of it, read at a glance. */

.topics {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-xs);
  max-width: 52rem;
}
.topics li {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.15rem var(--space-2xs);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- works --- */

.works { list-style: none; margin: 0; padding: 0; }
.works > li {
  border-top: 1px solid var(--rule);
  padding-block: var(--space-s);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-s);
  align-items: baseline;
  justify-content: space-between;
}
.works > li:last-child { border-bottom: 1px solid var(--rule); }
.works h2 { font-size: 1.1875rem; font-weight: 500; }
.works h2 a { color: var(--fg); border: 0; }
.works h2 a:hover { color: var(--accent); }
.works__year { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--muted); }

/* ---------------------------------------------------------------- talks --- */

.talks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--space-m);
}
.talk__thumb {
  inline-size: 100%;
  block-size: auto;          /* let aspect-ratio set height, not the height attr */
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 2px;
  border: 1px solid var(--rule);
  margin-block-end: var(--space-xs);
  /* Held greyscale so an external video still doesn't break the B&W photo set;
     blooms to colour on hover/focus, so the thumbnail stays recognisable. */
  filter: grayscale(1) contrast(1.02);
  transition: filter 220ms ease;
}
.talk a:hover .talk__thumb,
.talk a:focus-visible .talk__thumb { filter: grayscale(0); }
.talk h3 { margin-block-end: var(--space-2xs); font-size: 1.0625rem; }
.talk p { margin: 0; font-size: 0.9375rem; color: var(--muted); }

/* --------------------------------------------------------------- figure --- */

.figure { margin: 0; }
.figure img {
  inline-size: 100%;
  border-radius: 2px;
  border: 1px solid var(--rule);
  filter: saturate(0.92);
}
.figure figcaption {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--muted);
  margin-block-start: var(--space-2xs);
}

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-m);
}

/* -------------------------------------------------------------- contact --- */

.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li { padding-block: var(--space-2xs); }
.contact-list .label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
}

/* ---------------------------------------------------------------- tags --- */
/* The shared vocabulary made visible. A topic chip carries the same small
   vermilion stamp the nav uses for the current page — the one warm gesture,
   reused as a wayfinding mark, never as decoration. */

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-xs);
  margin-block-start: var(--space-s);
}
.tag {
  display: inline-flex;
  align-items: center;
  min-block-size: 1.5rem;          /* 24px — WCAG 2.5.8 target size */
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.1rem var(--space-2xs);
  white-space: nowrap;
  line-height: 1.4;
}
a.tag:hover { color: var(--accent); border-color: var(--accent); }
.tag--topic { color: var(--fg); }
.tag--topic::before {
  content: "";
  display: inline-block;
  inline-size: 4px;
  block-size: 4px;
  border-radius: 1px;
  background: var(--seal);
  margin-inline-end: 0.45em;
}

/* -------------------------------------------------------------- events --- */
/* Upcoming talks. Date column left, detail right — the same hairline-ruled row
   rhythm as the engagements list, so Speaking and Practice feel of a piece. */

.events { list-style: none; margin: 0; padding: 0; }
.event {
  border-top: 1px solid var(--rule);
  padding-block: var(--space-m);
  display: grid;
  grid-template-columns: minmax(7rem, 10rem) minmax(0, 1fr);
  gap: var(--space-xs) clamp(var(--space-m), 5vw, var(--space-l));
  align-items: baseline;
}
.event:last-child { border-bottom: 1px solid var(--rule); }
.event__when time {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--fg);
  letter-spacing: 0.02em;
}
.event__what h3 { margin: 0 0 var(--space-2xs); font-size: 1.1875rem; }
.event__venue { margin: 0 0 var(--space-2xs); color: var(--fg); }
.event__meta { margin: 0; color: var(--muted); font-size: 0.9375rem; }
.event__desc { margin-block-start: var(--space-xs); color: var(--muted); }
.event .tags { margin-block-start: var(--space-xs); }
@media (max-width: 46rem) {
  .event { grid-template-columns: minmax(0, 1fr); gap: var(--space-2xs); }
}

/* ------------------------------------------------------------ projects --- */

.projects { list-style: none; margin: 0; padding: 0; }
.project {
  border-top: 1px solid var(--rule);
  padding-block: var(--space-l);
}
.project:last-child { border-bottom: 1px solid var(--rule); }
.project__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-s);
  flex-wrap: wrap;
}
.project__head h2 { font-size: 1.5rem; }
.project__status { font-size: 0.75rem; color: var(--muted); }
.project__tagline {
  font-family: var(--font-display);
  font-size: 1.1875rem;
  color: var(--muted);
  max-width: none;
  margin-block: var(--space-2xs) var(--space-s);
}
.project__links { font-family: var(--font-mono); font-size: 0.8125rem; margin-block-start: var(--space-s); }

/* A project with a logo lays out two columns: text left, mark right. */
.project--logo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(9rem, 16rem);
  gap: clamp(var(--space-m), 5vw, var(--space-l));
  align-items: center;                 /* centre the mark against the text */
}
.project__logo {
  margin: 0;
  display: grid;
  place-items: center;                 /* centre the mark within its column */
}
.project__logo img {
  inline-size: clamp(8rem, 18vw, 12rem);
  block-size: auto;
}
@media (max-width: 46rem) {
  .project--logo { grid-template-columns: minmax(0, 1fr); }
  .project__logo { order: -1; justify-items: start; }
  .project__logo img { inline-size: 7rem; }
}

/* ----------------------------------------------------- anchored topics --- */
/* Each subject is an anchor target, so a tag on a note or a talk can jump the
   reader straight to it. Arriving via that link lights the chip briefly. */

.topics li { display: inline-flex; align-items: baseline; gap: 0.4em; }
.topics__count { color: var(--warm); border: 0; }
a.topics__count:hover { color: var(--accent); }
.topics li:target {
  border-color: var(--accent);
  color: var(--fg);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  scroll-margin-block-start: var(--space-l);
}

/* ---------------------------------------------------------- media band --- */
/* Full page-width photograph. Used on Speaking, never on the home page: a
   full-bleed image there would spend the restraint the rest of the site keeps. */

.media-band { margin: var(--space-m) 0 0; }
.media-band img {
  inline-size: 100%;
  block-size: auto;
  display: block;
  border-radius: 2px;
  border: 1px solid var(--rule);
  filter: saturate(0.92);
}

/* --------------------------------------------------------- posts teaser --- */
/* The "latest note" block on the home page. Styled here, not in tufte.css,
   because the home page does not load the long-form layer. */

.posts--teaser { list-style: none; margin: 0; padding: 0; }
.posts--teaser > li { border-top: 1px solid var(--rule); padding-block: var(--space-s); }
.posts--teaser h3 { font-size: 1.1875rem; margin-block-end: var(--space-2xs); }
.posts--teaser h3 a { color: var(--fg); border: 0; }
.posts--teaser h3 a:hover { color: var(--accent); }
.posts--teaser p { color: var(--muted); margin-block-end: var(--space-2xs); }
.posts--teaser time { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); }

/* ------------------------------------------------------- contact form --- */

.contact-form { max-width: 38rem; margin-block-start: var(--space-m); }
.contact-form__honey { position: absolute !important; left: -9999px; height: 0; overflow: hidden; }
.field { margin-block-end: var(--space-s); }
.field label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-block-end: var(--space-2xs);
}
.field__opt { text-transform: none; letter-spacing: 0; }
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form input[type="number"],
.contact-form select,
.contact-form textarea {
  inline-size: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--fg);
  background: color-mix(in srgb, var(--fg) 3%, transparent);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: var(--space-xs) var(--space-s);
  line-height: 1.5;
}
.contact-form textarea { resize: vertical; }
.contact-form input:focus-visible,
.contact-form select:focus-visible,
.contact-form textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

.button { cursor: pointer; }
button.button { font-family: inherit; }

/* section that sits directly under the header wants less air above it */
.section--tight { padding-block-start: var(--space-l); }

/* ----------------------------------------------------------------- 404 --- */
/* The one page where the seal leads rather than signs off: 不在 stamped above
   the heading, so the answer arrives before the explanation. Everything else
   is the ordinary section rhythm — a dead end should still feel like the
   same building. */
.section--404 > .seal { margin-block-end: var(--space-m); }
.section--404 .section__head { margin-block-start: 0; }
/* the closing line is a separate thought from the three ways out */
.section--404 .actions { margin-block-end: var(--space-m); }

/* ---------------------------------------------------------- htmx states --- */
/* The swap is announced to screen readers by site.js; this is the visual half.
   Kept to opacity only: a spinner would be louder than anything else on the
   page and would break the calm the whole design is buying. */

#main.htmx-swapping { opacity: 0.4; transition: opacity 120ms ease; }
#main.htmx-settling { opacity: 1; }

.htmx-indicator { opacity: 0; transition: opacity 180ms ease; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }
