/* =========================================================
   PANTRY components v0.2
   Button, text link, bubble, photo frame, focus. Every value comes from tokens.css.
   The site uses these for every button and text link. Section CSS may
   only place them (width, margin), never restyle them.
   Shown in pantry-ds.html. Rules: DESIGN-SYSTEM.md.
   ========================================================= */

:root {
  /* Button padding. Small buttons use half of it. */
  --btn-padding: var(--space-24);
  /* Bubble tail: a square this big, turned 45 degrees. */
  --bubble-tail: var(--space-8);
}

/* ---------- Button ----------
   .btn                   primary: red, ink text
   .btn--secondary        ink outline
   .btn--small            half padding
   .btn--hairline         canvas, ink text, rule-coloured hairline; red on hover
   .btn--on-dark          for ink backgrounds (combine with the others)
   Hover: a fill wipes in from the left and the arrow steps right.
   Markup: <a class="btn"><span>Label</span><span class="btn-arrow" aria-hidden="true">→</span></a> */

.btn {
  --btn-bg: var(--color-red-signal);
  --btn-fg: var(--color-ink);
  --btn-line: transparent;
  --btn-fill: var(--color-ink);
  --btn-fg-hover: var(--color-canvas);

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
  padding: var(--btn-padding);
  border: 0;
  border-radius: var(--radius);
  /* Inset shadow instead of a border, so the wipe covers the outline too. */
  box-shadow: inset 0 0 0 var(--line-width) var(--btn-line);
  background: var(--btn-bg);
  color: var(--btn-fg);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: var(--text-action-size);
  font-weight: var(--text-body-weight);
  line-height: var(--text-action-lh);
  text-align: left;
  cursor: pointer;
  isolation: isolate;
  overflow: hidden;
  transition: color var(--duration) var(--ease);
}

.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--btn-fill);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--duration) var(--ease);
}

.btn-arrow {
  font-size: var(--text-lead-size);
  line-height: 1;
  transition: transform var(--duration) var(--ease);
}

.btn:hover {
  color: var(--btn-fg-hover);
}

.btn:hover::before {
  transform: scaleX(1);
}

.btn:hover .btn-arrow,
.btn:focus-visible .btn-arrow {
  transform: translateX(var(--space-8));
}

.btn--small {
  gap: var(--space-8);
  padding: calc(var(--btn-padding) / 2);
}

.btn--small .btn-arrow {
  font-size: var(--text-body-size);
}

.btn--secondary {
  --btn-bg: transparent;
  --btn-line: var(--color-ink);
}

.btn--hairline {
  --btn-bg: var(--color-canvas);
  --btn-line: var(--color-rule);
  --btn-fill: var(--color-red-signal);
}

.btn--on-dark {
  --btn-fill: var(--color-canvas);
  --btn-fg-hover: var(--color-ink);
  --focus-ring: var(--color-canvas);
}

.btn--secondary.btn--on-dark {
  --btn-fg: var(--color-canvas);
  --btn-line: var(--color-canvas);
}

/* ---------- Text link ----------
   Ink, thin underline. Hover: the underline turns red.
   .link--on-dark: canvas text, for ink backgrounds. */

.link {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-thickness: var(--line-width);
  text-underline-offset: 0.2em;
  transition: text-decoration-color var(--duration) var(--ease);
}

.link:hover {
  text-decoration-color: var(--color-red-signal);
}

.link--on-dark {
  color: var(--color-canvas);
  --focus-ring: var(--color-canvas);
}

/* ---------- Bubble ----------
   A small mono note that points at something: a hint, never content.
   Canvas, ink hairline, a tail on one side.
   .bubble--down    tail under its left end, pointing down
   .bubble--down-end  tail under its right end, pointing down
   .bubble--left    tail on its left side, pointing left
   Markup: <span class="bubble bubble--down">Drag me</span> */

.bubble {
  position: relative;
  display: inline-block;
  padding: var(--space-8) var(--space-12);
  border: var(--line-width) solid var(--color-ink);
  border-radius: var(--radius);
  background: var(--color-canvas);
  color: var(--color-ink);
  font-family: var(--font-mono);
  font-size: var(--text-caption-size);
  font-weight: var(--text-body-weight);
  line-height: var(--text-caption-lh);
  white-space: nowrap;
}

.bubble::after {
  content: "";
  position: absolute;
  width: var(--bubble-tail);
  height: var(--bubble-tail);
  border: 0 solid var(--color-ink);
  background: var(--color-canvas);
}

.bubble--down::after {
  top: 100%;
  left: var(--space-12);
  border-width: 0 var(--line-width) var(--line-width) 0;
  transform: translateY(-50%) rotate(45deg);
  margin-top: calc(var(--line-width) * -1);
}

.bubble--down-end::after {
  top: 100%;
  right: var(--space-12);
  border-width: 0 var(--line-width) var(--line-width) 0;
  transform: translateY(-50%) rotate(45deg);
  margin-top: calc(var(--line-width) * -1);
}

.bubble--left::after {
  top: 50%;
  right: 100%;
  border-width: 0 0 var(--line-width) var(--line-width);
  transform: translate(50%, -50%) rotate(45deg);
  margin-right: calc(var(--line-width) * -1);
}

/* ---------- Focus ----------
   One ring for every link and control on the site, not just these
   components: ink on light, canvas on dark. A dark block sets
   --focus-ring: var(--color-canvas) once (see contact.css). Keyboard only.
   :where() keeps it at the lowest weight, so a section never needs its
   own focus rule. */

:where(a, button, input, select, textarea, summary):focus {
  outline: none;
}

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: calc(var(--line-width) * 2) solid var(--focus-ring, var(--color-ink));
  outline-offset: var(--space-4);
}

@media (prefers-reduced-motion: reduce) {
  .btn,
  .btn::before,
  .btn-arrow,
  .link {
    transition: none;
  }
}

/* ---------- Photo frame ----------
   A frame that cycles through its photos, no border. Every photo sits in
   the same box with the same size and anchor (object-fit: contain,
   centred), so only the picture changes, never its place in the frame.
   Set the frame's shape with --photo-frame-ratio (the real ratio of the
   photos). It is media: place it with .col and no .cell, line to line.
   scripts/photo-cycle.js changes the photo with a glitch (stepped slices
   that slide sideways), starts 1.5s after the frame scrolls into view,
   pauses when it is offscreen and holds one still photo with reduced
   motion. Without it, the first photo shows.
   Markup: <div class="photo-frame" data-photo-cycle>
             <img class="photo-frame-img is-current" src="" alt="">
             <img class="photo-frame-img" src="" alt="" aria-hidden="true">
           </div> */

.photo-frame {
  position: relative;
  width: 100%;
  aspect-ratio: var(--photo-frame-ratio, 1 / 1);
  border-radius: var(--radius);
  background: var(--photo-frame-bg, transparent);
  isolation: isolate;
  overflow: clip;
}

.photo-frame-img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  opacity: 0;
  user-select: none;
  -webkit-user-drag: none;
}

.photo-frame-img.is-current {
  opacity: 1;
}

/* The photo arriving sits above the one leaving. */
.photo-frame-img.is-entering {
  z-index: 1;
}

/* ---------- ASCII image ----------
   scripts/ascii.js draws an image as mono characters on a canvas laid over
   it, in the image's own box (object-fit: contain), so the image's parent
   must be positioned. Character density follows how dark each cell is;
   colour follows what it is: red, dark red, ink or grey. While the page
   scrolls, the photo shows through one patch at a time, opening top to
   bottom dot by dot. The image stays in
   the page for its alt text but is hidden under the canvas. Values are
   --ascii-* in tokens.css. Without the script, the plain image shows.
   Markup: <div style="position: relative"><img src="" alt="" data-ascii></div>
   (data-ascii attaches on its own; or PantryAscii.attach(img) from JS). */

.ascii-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  user-select: none;
}

img.is-ascii {
  visibility: hidden;
}
