/* Trotika studio. One ink, one ground, one scale, one easing. */

/* 1. Tokens */
:root {
  --oxblood: #3D2022;
  --bone: #F5F5F2;

  --ink: var(--oxblood);
  --ground: var(--bone);
  --ink-press: color-mix(in srgb, var(--ink) 72%, var(--ground));

  --font-text: "Hanken Grotesk", "Hanken Fallback", Arial, Helvetica, sans-serif;
  --font-meta: "Courier Prime", "Courier Prime Fallback", "Courier New", monospace;

  --fs-body: clamp(17px, 14px + 0.5vw, 21px);
  --fs-panel: 15px; /* panel prose sits two steps under the 21 px title so a sentence reads as a note; 16 on phone (section 10) */
  --fs-meta: 14px; /* flat: the metadata face never drops below 14 on touch screens */

  /* 1.333 gives a 28 px line box at 21 px, so the desktop item pitch is 4 + 28 + 4 = 36 */
  --lh-body: 1.333;
  --lh-panel: 1.4;
  --lh-meta: 1.3;
  --ls-body: -0.01em;
  --ls-meta: 0.02em;

  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-6: 24px;
  --s-8: 32px;
  --s-12: 48px;
  --s-16: 64px;
  --s-24: 96px;

  --col-max: 800px;
  --label-w: 160px;
  --counter-w: 36px;
  --title-x: 48px;
  --measure-tagline: 20em;
  --measure-panel: 360px;
  --gutter: 32px;

  /* The row grid: label beside list. Phone stacks the label above the list (section 10). */
  --row-cols: var(--label-w) minmax(0, 1fr);
  --row-gap: var(--s-4);

  --ease: cubic-bezier(0.2, 0, 0, 1);
  --dur-panel: 320ms;
  --dur-hover: 200ms;
  --dur-fade: 600ms;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-scheme="light"]) {
    --ink: var(--bone);
    --ground: var(--oxblood);
  }
  :root:not([data-scheme="light"]) body {
    -webkit-font-smoothing: antialiased;
  }
}

:root[data-scheme="dark"] {
  --ink: var(--bone);
  --ground: var(--oxblood);
}
:root[data-scheme="dark"] body {
  -webkit-font-smoothing: antialiased;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-panel: 0ms;
    --dur-hover: 0ms;
    --dur-fade: 0ms;
  }
}

/* 2. Metric-matched fallbacks */
@font-face {
  font-family: "Hanken Fallback";
  src: local("Arial"), local("Helvetica");
  size-adjust: 102.6%;
  ascent-override: 100%;
  descent-override: 30.3%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Courier Prime Fallback";
  src: local("Courier New");
  size-adjust: 99.9%;
  ascent-override: 78.1%;
  descent-override: 34.2%;
  line-gap-override: 0%;
}

/* 3. Reset */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
}
html {
  overflow-x: clip;
  color-scheme: light dark;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  min-block-size: 100vh;
  min-block-size: 100svh;
  display: flex;
  flex-direction: column;
  padding: var(--gutter);
  background: var(--ground);
  color: var(--ink);
  font: 400 var(--fs-body) / var(--lh-body) var(--font-text);
  letter-spacing: var(--ls-body);
  hyphens: none;
}
h1, h2, h3 {
  font: inherit;
  letter-spacing: inherit;
}
::selection {
  background: var(--ink);
  color: var(--ground);
}

/* Page fade: once per session, on a cold start, once fonts are ready.
   The head script adds fonts-ready before first paint on return visits and under reduced motion. */
html.js body {
  opacity: 0;
}
html.js.fonts-ready body {
  opacity: 1;
  transition: opacity var(--dur-fade) var(--ease);
}
html:not(.js) body {
  opacity: 1;
}

/* 4. Layout */
header, main, footer, .mark {
  max-inline-size: calc(var(--col-max) - 2 * var(--gutter));
}
header, main, footer {
  position: relative;
  z-index: 1;
}
main {
  margin-block-start: var(--s-12);
}
footer {
  margin-block-start: auto;
  padding-block-start: var(--s-12);
}

/* The mark. It is the first thing in the header. Below 1000 px it is inline at the top
   of the column, left-aligned to the gutter like everything else, 60 percent wide (max 432).
   From 1000 px it is fixed in the ground (section 4.1), so header order does not affect it.
   It is not a link while "/" still resolves to the mercury page. */
.mark {
  display: block;
  color: var(--ink);
  inline-size: 60%;
  max-inline-size: 432px;
  margin-block-end: var(--s-12);
}
.mark svg {
  display: block;
  inline-size: 100%;
  block-size: auto;
}

/* 4.1 Desktop mark: fixed, hung from the right gutter like the words hang from the left,
   vertically centred, 36vw wide (max 640). The width also yields to the column so the mark never
   crosses the widest open prose (ink ends at x 616): 320 wide at 1000, 432 at 1200, 518 at 1440,
   640 from 1778. The brief sanctions this over a watermark; ink stays at full opacity. */
@media (min-width: 1000px) {
  .mark {
    position: fixed;
    top: 50%;
    right: var(--gutter);
    left: auto;
    inline-size: min(36vw, calc(100vw - 648px - var(--gutter)), 640px);
    max-inline-size: none;
    margin: 0;
    padding: 0;
    transform: translateY(-50%);
    pointer-events: none;
    z-index: 0;
  }
}

/* 4.2 Ink under the paper: a fixed, transparent canvas at the root, below header, main and footer
   (all z-index 1). Pointer events off; the shader reads the pointer from the window. */
.ink {
  position: fixed;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  display: block;
  z-index: 0;
  pointer-events: none;
}

/* 5. Type */
.tagline {
  max-inline-size: var(--measure-tagline);
  text-wrap: balance;
}
.row-label {
  padding-block-start: var(--s-1);
}
.counter,
.meta,
.sublist-numbered > li::before {
  font: 400 var(--fs-meta) / var(--lh-meta) var(--font-meta);
  letter-spacing: var(--ls-meta);
  font-variant-numeric: tabular-nums;
}
.panel-body {
  font-size: var(--fs-panel);
  line-height: var(--lh-panel);
  padding-block: var(--s-2) var(--s-4);
  text-wrap: pretty;
  overflow-wrap: break-word;
}
/* The prose measure sits on the paragraphs and lists, so a single metadata line can run past it */
.panel-body > p,
.panel-body > .sublist {
  max-inline-size: var(--measure-panel);
}
.panel-body p + p {
  margin-block-start: var(--s-4);
}
.panel-body p + .sublist {
  margin-block-start: var(--s-4);
}
.panel-body > .meta {
  margin-block-start: var(--s-4);
  max-inline-size: none;
  text-wrap: balance;
}
.panel-body > .out {
  margin-block-start: var(--s-2);
}
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 6. Rows and items */
.row {
  display: grid;
  grid-template-columns: var(--row-cols);
  column-gap: var(--row-gap);
  align-items: start;
}
.row + .row {
  margin-block-start: var(--s-6);
}
.list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.item {
  display: grid;
  grid-template-columns: var(--counter-w) minmax(0, 1fr);
  column-gap: var(--s-3);
  align-items: baseline;
  padding-block: var(--s-1);
  min-width: 0;
}
.item > .panel {
  grid-column: 2;
}
.sublist {
  margin: 0;
  padding: 0;
  list-style: none;
  text-wrap: pretty;
}
.sublist > li + li {
  margin-block-start: var(--s-1);
}
.sublist-numbered {
  counter-reset: item;
}
.sublist-numbered > li {
  counter-increment: item;
  display: grid;
  grid-template-columns: var(--counter-w) minmax(0, 1fr);
  column-gap: var(--s-3);
  align-items: baseline;
}
.sublist-numbered > li::before {
  content: "(" counter(item, decimal-leading-zero) ")";
}

/* 7. Controls. The hit zone is 36 px on the desktop pitch (no zone overlaps the item below)
   and 44 px on touch widths (section 10). */
.toggle, .link {
  all: unset;
  cursor: pointer;
  position: relative;
  display: inline;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-hover) var(--ease);
}
.toggle::before, .link::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block: calc(50% - 18px);
}
.t {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
  text-decoration-skip-ink: none;
  text-decoration-color: currentColor;
  transition: text-decoration-color var(--dur-hover) var(--ease);
}
.arrow {
  inline-size: 0.55em;
  block-size: 0.55em;
  margin-inline-start: var(--s-2);
  vertical-align: 0.05em;
}

@media (hover: hover) {
  .toggle:hover .t,
  .link:hover .t {
    text-decoration-color: transparent;
  }
}

.toggle:focus-visible,
.link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 2px;
}
:focus:not(:focus-visible) {
  outline: none;
}

.toggle:active,
.link:active {
  color: var(--ink-press);
  transition: none;
}

.toggle[aria-expanded="true"] .t {
  text-decoration-color: transparent;
}

/* 8. Panels */
.panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  scroll-margin-block-end: var(--gutter);
  transition: grid-template-rows var(--dur-panel) var(--ease), visibility 0s linear var(--dur-panel);
}
.panel[data-open="true"] {
  grid-template-rows: 1fr;
  visibility: visible;
  transition-delay: 0s, 0s;
}
.panel-inner {
  position: relative; /* the links' absolute hit zones clip with the panel, so a closed panel adds no scroll height */
  min-block-size: 0;
  overflow: hidden;
}
html.is-booting .panel,
html.is-booting .t {
  transition: none;
}

/* No JS: every panel open, titles are plain text, nothing claims to be a control */
html:not(.js) .panel {
  grid-template-rows: 1fr;
  visibility: visible;
}
html:not(.js) .toggle {
  cursor: default;
}
html:not(.js) .toggle .t {
  text-decoration: none;
}
html:not(.js) .toggle::before {
  display: none;
}

/* 9. Contact: the panel sits in the list column like every other row's content,
   so the letters land at the counter stop and the values on the title line */
.row-contact > .panel {
  grid-column: 2;
}
.row-contact .panel-body {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  padding-block: 0;
}
.row-contact .t {
  overflow-wrap: anywhere;
}

/* 10. Tablet and phone: 44 px touch pitch, block-wide hit zones, mark inline at the top.
   The focus ring is drawn on the word, not the block, so it reads the same as on desktop. */
@media (max-width: 999px) {
  .item {
    min-block-size: 44px;
    padding-block: var(--s-2);
    align-content: start;
  }
  .toggle, .link {
    display: block;
    inline-size: 100%;
    text-align: left;
  }
  .toggle::before, .link::before {
    inset-block: calc(50% - 22px);
  }
  .toggle:focus-visible,
  .link:focus-visible {
    outline: none;
  }
  .toggle:focus-visible .t,
  .link:focus-visible .t {
    outline: 2px solid currentColor;
    outline-offset: 3px;
    border-radius: 2px;
  }
  .row-label {
    padding-block-start: var(--s-2);
  }
  footer {
    margin-block-start: var(--s-16);
    padding-block-start: 0;
  }
}

/* Phone: the label stacks above its list. One rule for everything that hangs beneath
   a title: it starts at the title's own edge (x 68 at a 20 px gutter). */
@media (max-width: 639px) {
  :root {
    --gutter: 20px;
    --fs-panel: 16px;
  }
  main {
    margin-block-start: var(--s-6);
  }
  footer {
    margin-block-start: var(--s-12);
  }
  .mark {
    margin-block-end: var(--s-8);
  }
  .row {
    grid-template-columns: 1fr;
  }
  .row > *,
  .row-contact > .panel {
    grid-column: 1;
  }
  .row-label {
    padding-block-start: 0;
    margin-block-end: var(--s-2);
  }
}

/* 11. Print */
@media print {
  .mark {
    position: static;
    transform: none;
    inline-size: 40%;
    margin: 0 auto var(--s-8);
    padding: 0;
  }
  .panel {
    grid-template-rows: 1fr;
    visibility: visible;
  }
  body {
    opacity: 1;
  }
}
