/* =========================================================
   tin.design — components
   Uses semantic tokens from tokens.css only. No hex values here.
   ========================================================= */

/* ---------- Button ----------
   Variant sets the look:   .btn-solid · .btn-soft · .btn-outline · .btn-ghost
   Colour is separate:      navy by default · .btn-danger
   Size:                    .btn-sm (32) · default (40) · .btn-lg (48)
   Shape:                   12px corners · text · text + icon · icon only (.btn-icon, needs aria-label)
   Element:                 <button> for actions, <a class="btn"> for navigation
   States:                  hover (only on hover-capable devices) · focus-visible · pressed (scale .97, darker; lighter on navy)
                            disabled (rare) · loading [aria-busy="true"] keeps its colour
   .is-hover / .is-focus / .is-active only exist to show frozen states on design-system.html */
.btn {
  /* size */
  --btn-h: 40px; --btn-px: var(--space-5); --btn-gap: var(--space-2); --btn-icon: var(--icon-size-md);
  /* colour (navy) */
  --tone: var(--color-accent);
  --tone-hover: var(--color-accent-hover);
  --tone-press: var(--color-accent);
  --on-tone: var(--color-on-accent);
  --tone-text: var(--color-text);
  --tone-text-hover: var(--color-text);
  --tone-soft: var(--color-fill-hover);
  --tone-soft-hover: var(--color-fill-pressed);
  --tone-border: var(--color-border-control);
  /* resolved by the variant */
  --btn-bg: transparent; --btn-fg: var(--tone-text); --btn-border: transparent;

  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--btn-gap);
  height: var(--btn-h); min-width: var(--btn-h); padding: 0 var(--btn-px);
  border: 1px solid var(--btn-border); border-radius: var(--radius-md);
  background: var(--btn-bg); color: var(--btn-fg);
  font-family: var(--font-body); font-size: var(--type-ui-size); font-weight: var(--weight-medium); line-height: 1;
  text-decoration: none; white-space: nowrap; cursor: pointer; user-select: none;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}
.btn .icon { width: var(--btn-icon); height: var(--btn-icon); }
.btn:focus-visible, .btn.is-focus { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.btn:active, .btn.is-active { transform: scale(0.97); }

/* sizes */
.btn-sm { --btn-h: 32px; --btn-px: var(--space-3); --btn-gap: 6px; --btn-icon: var(--icon-size-sm); font-size: var(--type-small-size); }
.btn-lg { --btn-h: 48px; --btn-px: var(--space-6); font-size: 1rem; }
.btn-icon { padding: 0; width: var(--btn-h); }
.btn-block { width: 100%; }

/* colour: danger */
.btn-danger {
  --tone: var(--color-danger);
  --tone-hover: var(--color-danger-hover);
  --tone-press: var(--color-danger-hover);
  --on-tone: var(--color-on-danger);
  --tone-text: var(--color-danger);
  --tone-text-hover: var(--color-danger-hover);
  --tone-soft: var(--color-danger-bg);
  --tone-soft-hover: var(--color-danger-bg-hover);
  --tone-border: var(--color-danger);
}

/* variant: solid. The one main action in a view. */
.btn-solid { --btn-bg: var(--tone); --btn-fg: var(--on-tone); }
.btn-solid.is-hover { --btn-bg: var(--tone-hover); }
.btn-solid:active, .btn-solid.is-active { --btn-bg: var(--tone-press); }

/* variant: soft. Tinted, for secondary actions that still need presence ("Try again" in an error). */
.btn-soft { --btn-bg: var(--tone-soft); --btn-fg: var(--tone-text); }
.btn-soft.is-hover { --btn-bg: var(--tone-soft-hover); --btn-fg: var(--tone-text-hover); }
.btn-soft:active, .btn-soft.is-active { --btn-bg: var(--tone-soft-hover); }

/* variant: outline. Second action next to a solid one, or a standalone action on a card. */
.btn-outline { --btn-bg: var(--color-surface); --btn-fg: var(--tone-text); --btn-border: var(--tone-border); }
.btn-outline.is-hover { --btn-border: var(--tone-text); --btn-fg: var(--tone-text-hover); }
.btn-outline:active, .btn-outline.is-active { --btn-bg: var(--tone-soft); }

/* variant: ghost. Toolbars and the chat panel, where a fill or border adds clutter. */
.btn-ghost { --btn-fg: var(--tone-text); }
.btn-ghost.is-hover { --btn-bg: var(--tone-soft); --btn-fg: var(--tone-text-hover); }
.btn-ghost:active, .btn-ghost.is-active { --btn-bg: var(--tone-soft-hover); }

/* on navy surfaces: everything inverts, and pressing gets lighter instead of darker */
.on-accent .btn:not(.btn-danger) {
  --tone: var(--color-on-accent);
  --tone-hover: var(--color-surface);
  --tone-press: var(--color-surface);
  --on-tone: var(--color-accent);
  --tone-text: var(--color-on-accent);
  --tone-text-hover: var(--color-on-accent);
  --tone-soft: var(--color-fill-inverse-hover);
  --tone-soft-hover: var(--color-fill-inverse-pressed);
  --tone-border: var(--color-icon);
}
.on-accent .btn-outline:not(.btn-danger) { --btn-bg: transparent; }
.on-accent .btn:focus-visible, .on-accent .btn.is-focus { outline-color: var(--color-highlight); }

/* disabled: rare. Only for send while a reply is streaming. */
.btn:disabled, .btn[aria-disabled="true"] {
  --btn-bg: var(--color-disabled-bg); --btn-fg: var(--color-disabled-text); --btn-border: transparent;
  cursor: not-allowed; transform: none;
}
.btn-ghost:disabled, .btn-ghost[aria-disabled="true"] { --btn-bg: transparent; }

/* loading: not the same as disabled. Scripts must also ignore clicks while aria-busy is set,
   so a double click can't send twice. */
/* loading: not the same as disabled. Keeps its colour and width; a spinner sits over the
   transparent label, which screen readers still read. */
.btn[aria-busy="true"] { cursor: not-allowed; color: transparent; transform: none; }
.btn-spinner { display: none; }
.btn[aria-busy="true"] .btn-spinner {
  display: block; position: absolute; inset: 0; margin: auto;
  width: var(--btn-icon); height: var(--btn-icon);
  border: 2px solid var(--btn-fg); border-right-color: transparent; border-radius: 50%;
  animation: btn-spin 700ms linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* hover only on devices that really hover, so a tap never leaves a hover colour behind */
@media (hover: hover) {
  .btn-solid:hover { --btn-bg: var(--tone-hover); }
  .btn-soft:hover { --btn-bg: var(--tone-soft-hover); --btn-fg: var(--tone-text-hover); }
  .btn-outline:hover { --btn-border: var(--tone-text); --btn-fg: var(--tone-text-hover); }
  .btn-ghost:hover { --btn-bg: var(--tone-soft); --btn-fg: var(--tone-text-hover); }
}

/* touch screens: never smaller than 44px to tap */
@media (pointer: coarse) {
  .btn { min-height: var(--target-min); }
  .btn-icon { min-width: var(--target-min); }
}
@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
  .btn:active, .btn.is-active { transform: none; }
  .btn[aria-busy="true"] .btn-spinner { animation-duration: 2s; }
}

/* ---------- Avatar ----------
   Sizes: .avatar-xs (24) · .avatar-sm (32) · default (40) · .avatar-lg (80)
   Content: a photo, with initials underneath as the fallback if the photo fails to load
   Badge: .avatar-badge marks the AI twin (yellow, sparkle icon)
   Markup: <span class="avatar"><img src="…" alt="" onerror="this.remove()">TM</span> */
.avatar {
  --av: 40px;
  position: relative; flex: none;
  display: inline-grid; place-items: center;
  width: var(--av); height: var(--av); border-radius: 50%;
  background: var(--color-accent); color: var(--color-on-accent);
  font-family: var(--font-body); font-weight: var(--weight-medium);
  font-size: calc(var(--av) * 0.38); line-height: 1; letter-spacing: 0.02em;
  user-select: none;
}
.avatar img { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.avatar::after { content: ""; position: absolute; inset: 0; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--color-fill-pressed); pointer-events: none; }
.avatar-xs { --av: 24px; }
.avatar-sm { --av: 32px; }
.avatar-lg { --av: 80px; }
.avatar-badge {
  position: absolute; right: -2px; bottom: -2px; z-index: 1;
  width: max(14px, calc(var(--av) * 0.4)); height: max(14px, calc(var(--av) * 0.4));
  display: grid; place-items: center; border-radius: 50%;
  background: var(--color-highlight); color: var(--color-on-highlight);
  box-shadow: 0 0 0 2px var(--avatar-ring, var(--color-surface));
}
.avatar-badge .icon { width: 65%; height: 65%; }
.avatar-link { display: inline-flex; border-radius: 50%; }
.avatar-link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* ---------- Tag ----------
   A short, non-interactive label. Not a button, not a link.
   Variants: neutral (default) · .tag-highlight · .tag-solid · .tag-outline · .tag-danger · .tag-on-media
   Sizes: .tag-sm (20) · default (24)
   Optional 14px icon before the text */
.tag {
  --tag-h: 24px; --tag-bg: var(--color-fill-hover); --tag-fg: var(--color-text); --tag-border: transparent;
  display: inline-flex; align-items: center; gap: var(--space-1);
  height: var(--tag-h); padding: 0 var(--space-2);
  border: 1px solid var(--tag-border); border-radius: var(--radius-xs);
  background: var(--tag-bg); color: var(--tag-fg);
  font-family: var(--font-body); font-size: var(--type-label-size); font-weight: var(--weight-medium); line-height: 1;
  white-space: nowrap; vertical-align: middle;
}
.tag .icon { width: 14px; height: 14px; }
.tag-sm { --tag-h: 20px; padding: 0 6px; font-size: 11px; }
.tag-sm .icon { width: 12px; height: 12px; }
.tag-highlight { --tag-bg: var(--color-highlight); --tag-fg: var(--color-on-highlight); }
.tag-solid { --tag-bg: var(--color-accent); --tag-fg: var(--color-on-accent); }
.tag-outline { --tag-bg: transparent; --tag-fg: var(--color-text-secondary); --tag-border: var(--color-border); }
.tag-danger { --tag-bg: var(--color-danger-bg); --tag-fg: var(--color-danger); }
.tag-on-media { --tag-bg: var(--color-surface); --tag-fg: var(--color-text); box-shadow: 0 1px 2px var(--color-shadow); }

/* ---------- Site header ----------
   Avatar (28) + name as one link on the left, nav on the right.
   Nav links: plain text, no underline. Hover/focus: yellow fill with
   3px horizontal padding, fades in. Focus also gets a navy outline. */
.site-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); padding-block: var(--space-4); }
.site-header .avatar { --av: 28px; }
.site-header-brand { display: inline-flex; align-items: center; gap: 10px; color: var(--color-text); text-decoration: none; }
.site-header-brand:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; border-radius: 2px; }
.site-header-name { font-family: var(--font-body); font-size: var(--type-ui-size); font-weight: var(--weight-semibold); line-height: 1.3; }
.site-header-nav { display: flex; align-items: center; gap: var(--space-5); }
.nav-link {
  color: var(--color-text); text-decoration: none;
  font-family: var(--font-body); font-size: var(--type-ui-size); font-weight: var(--weight-medium); line-height: 1.3;
  padding: 0 3px; margin: 0 -3px; border-radius: 2px;
  background-color: transparent;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.nav-link:focus-visible { background-color: var(--color-highlight); outline: 2px solid var(--color-focus); outline-offset: 2px; }
@media (hover: hover) { .nav-link:hover { background-color: var(--color-highlight); } }
@media (prefers-reduced-motion: reduce) { .nav-link { transition: none; } }

/* =========================================================
   Batch 2 · home page (chat-first, per the agreed prototype)
   ========================================================= */

/* ---------- Container ----------
   Centres content at --page-max with fluid gutters. */
.container { width: 100%; max-width: calc(var(--page-max) + 2 * var(--gutter)); margin-inline: auto; padding-inline: max(var(--gutter), env(safe-area-inset-left, 0px)) max(var(--gutter), env(safe-area-inset-right, 0px)); }

/* ---------- Suggestion ----------
   A question the visitor can send in one click. Clickable, unlike a tag.
   Sizes: default (36) · .suggestion-sm (28, "Ask about this" on case study sections)
   Icon: none on the home chips · plus in the chat panel list · chat-circle for "Ask about this"
   Always <button type="button">. Once asked, it's removed from the list. */
.suggestion {
  --sg-h: 36px; --sg-bg-hover: var(--color-surface);
  position: relative;
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-height: var(--sg-h); max-width: 100%; padding: 6px 14px;
  border: 1px solid var(--color-border); border-radius: var(--radius-pill);
  background: transparent; color: var(--color-text);
  font-family: var(--font-body); font-size: var(--type-small-size); font-weight: var(--weight-regular); line-height: 1.3;
  text-align: left; cursor: pointer; user-select: none;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
}
.suggestion:has(.icon) { padding-left: 10px; }
.suggestion .icon { width: var(--icon-size-sm); height: var(--icon-size-sm); color: var(--color-icon); transition: color var(--duration-fast) var(--ease-out); }
.suggestion.is-hover { background: var(--sg-bg-hover); border-color: var(--color-border-control); }
.suggestion.is-hover .icon { color: var(--color-text); }
.suggestion:focus-visible, .suggestion.is-focus { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.suggestion:active, .suggestion.is-active { transform: scale(0.97); background: var(--color-fill-pressed); border-color: var(--color-border-control); }
.suggestion:disabled { color: var(--color-disabled-text); cursor: not-allowed; transform: none; background: transparent; border-color: var(--color-border); }
.suggestion:disabled .icon { color: var(--color-border-control); }
.suggestion-sm { --sg-h: 28px; padding: 4px 10px; gap: 6px; font-size: 13px; font-weight: var(--weight-medium); color: var(--color-text-secondary); }
.suggestion-sm:has(.icon) { padding-left: 8px; }
.suggestion-sm .icon { width: 14px; height: 14px; color: currentColor; }
.suggestion-sm.is-hover { color: var(--color-text); }
.suggestion-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.on-surface .suggestion { --sg-bg-hover: var(--color-fill-hover); }
@media (hover: hover) {
  .suggestion:hover { background: var(--sg-bg-hover); border-color: var(--color-border-control); }
  .suggestion:hover .icon { color: var(--color-text); }
  .suggestion-sm:hover { color: var(--color-text); }
  .suggestion:disabled:hover { background: transparent; border-color: var(--color-border); }
}
@media (pointer: coarse) {
  .suggestion { min-height: var(--target-min); }
  .suggestion-sm { min-height: var(--sg-h); }
  .suggestion-sm::after { content: ""; position: absolute; inset: -8px -2px; }
}

/* ---------- Composer ----------
   The chat input. .composer-lg is the big pill on home; the docked version
   comes with the chat panel. Send is a round solid icon button. */
.composer {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; padding: 6px 6px 6px 22px;
  background: var(--color-surface); border-radius: var(--radius-pill);
  box-shadow: 0 1px 2px var(--color-shadow), 0 10px 30px var(--color-shadow);
  transition: box-shadow var(--duration-fast) var(--ease-out);
}
.composer:focus-within, .composer.is-focus { box-shadow: 0 0 0 2px var(--color-focus), 0 10px 30px var(--color-shadow); }
.composer input {
  flex: 1; min-width: 0; padding: 9px 0; border: 0; outline: none; background: transparent;
  color: var(--color-text); font-family: var(--font-body); font-size: 16px; line-height: 1.4; /* 16px stops iOS zooming in */
}
.composer input::placeholder { color: var(--color-text-secondary); }
.composer .btn { border-radius: var(--radius-pill); }
.composer-lg { max-width: 560px; }

/* ---------- Hero ----------
   Plain intro: a single two-line paragraph, body size. */
.hero { padding-block: var(--space-10) var(--space-8); }
.hero-intro { max-width: 500px; }

/* ---------- Project card ----------
   The tile in the home work grid, Pentagram style: a 4:3 image, square
   corners, then a caption on the page background (no white container).
   The whole tile is one link.
   Hover: the image scales 1.04, the other tiles dim to 40%, and the
   title takes the yellow highlight. All off under prefers-reduced-motion. */
.card-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap-hairline); row-gap: var(--space-10); }
.card { display: flex; flex-direction: column; min-width: 0; color: inherit; text-decoration: none; transition: opacity var(--duration-base) var(--ease-out); }
.card-grid:hover .card:not(:hover) { opacity: .4; }
.card-media { aspect-ratio: 4 / 3; overflow: hidden; }
.card-media img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform var(--duration-slow) var(--ease-out); }
.card:hover .card-media img { transform: scale(1.04); }
.card-body { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; padding: 14px var(--space-8) 0 0; }
.card-title {
  font-family: var(--font-body); font-size: var(--type-title-size); line-height: var(--type-title-leading);
  font-weight: var(--type-title-weight); letter-spacing: var(--type-title-tracking); margin: 0;
  padding: 0 3px; margin-inline: -3px; border-radius: 2px;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.card:hover .card-title { background-color: var(--color-highlight); }
.card-text {
  font-family: var(--font-body); font-size: var(--type-small-size); line-height: var(--type-small-leading); letter-spacing: -0.014em;
  color: var(--color-text-secondary); max-width: 44ch;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 6px; border-radius: 2px; }
@media (max-width: 640px) { .card-grid { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) {
  .card, .card-media img, .card-title { transition: none; }
  .card:hover .card-media img { transform: none; }
}

/* ---------- Site footer ----------
   One quiet line under the work: name and year, LinkedIn, email. */
.site-footer { margin-top: var(--section-space); color: var(--color-text-secondary); }
.site-footer-inner { padding-block: var(--space-6) var(--space-8); border-top: 1px solid var(--color-border); display: flex; justify-content: space-between; align-items: center; gap: var(--space-3) var(--space-6); flex-wrap: wrap; }
.site-footer nav { display: flex; gap: var(--space-5); }
