/* ==========================================================================
   br. Components
   Built only from Semantic tokens in tokens.css (never raw values).
   ========================================================================== */


/* Base ------------------------------------------------------------------- */
html { background: var(--br-color-page-bg); }
body {
  background: var(--br-color-page-bg);
  color: var(--br-color-text-primary);
  font-family: var(--br-font-family-body);
  transition: background-color var(--br-transition-theme-switch), color var(--br-transition-theme-switch);
}
::selection {
  background: var(--br-color-accent-default);
  color: var(--br-color-on-accent);
}
:focus-visible {
  outline: var(--br-border-width-strong) solid var(--br-color-focus-ring);
  outline-offset: 2px;
}


/* Button ----------------------------------------------------------------- */
.br-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--br-space-gap-sm);
  height: var(--br-size-button-height);
  padding: 0 calc(var(--br-space-button-padding-x) + var(--br-space-inset-sm));
  border-radius: var(--br-radius-button);
  border: var(--br-border-width-default) solid transparent;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--br-transition-hover),
    border-color var(--br-transition-hover),
    transform var(--br-transition-press);
}
.br-btn:active { transform: scale(var(--br-motion-scale)); }

.br-btn--primary {
  background: var(--br-color-button-primary-bg);
  color: var(--br-color-button-primary-fg);
}
.br-btn--primary:hover { background: var(--br-color-button-primary-bg-hover); }
.br-btn--primary:active { background: var(--br-color-button-primary-bg-pressed); }

.br-btn--secondary {
  background: var(--br-color-button-secondary-bg);
  color: var(--br-color-button-secondary-fg);
  border-color: var(--br-color-button-secondary-border);
}
.br-btn--secondary:hover { border-color: var(--br-color-button-secondary-border-hover); }

/* Reveal arrow: a ↗ slides in after the label on hover/focus and the button grows —
   for links that leave the site. */
.br-btn--reveal-arrow { gap: 0; }
.br-btn--reveal-arrow .br-btn__arrow {
  flex: none;
  width: 0;
  height: var(--br-icon-sm);
  margin-left: 0;
  opacity: 0;
  transition:
    width var(--br-transition-hover),
    margin-left var(--br-transition-hover),
    opacity var(--br-transition-hover);
}
.br-btn--reveal-arrow:hover .br-btn__arrow,
.br-btn--reveal-arrow:focus-visible .br-btn__arrow {
  width: var(--br-icon-sm);
  margin-left: var(--br-space-gap-xs);
  opacity: 1;
}

/* Ghost: outline button for use on dark feature cards. */
.br-btn--ghost {
  background: transparent;
  color: var(--br-color-card-feature-fg);
  border-color: var(--br-color-card-feature-fg-muted);
}
.br-btn--ghost:hover { border-color: var(--br-color-card-feature-fg); }


/* Nav item --------------------------------------------------------------- */
.br-nav-item {
  display: inline-flex;
  align-items: center;
  height: var(--br-size-nav-item-height);
  padding: 0 var(--br-space-inset-md);
  border-radius: var(--br-radius-nav);
  color: var(--br-color-nav-item-fg);
  transition: background-color var(--br-transition-hover), color var(--br-transition-hover);
}
.br-nav-item:hover { background: var(--br-color-nav-item-bg-hover); }


/* Chip ------------------------------------------------------------------- */
.br-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--br-space-inset-xs) var(--br-space-inset-sm);
  border-radius: var(--br-radius-chip);
  background: var(--br-color-bg-subtle);
  color: var(--br-color-text-primary);
}
.br-chip--accent {
  background: var(--br-color-card-highlight-bg);
  color: var(--br-color-card-highlight-fg);
}


/* Card ------------------------------------------------------------------- */
.br-card {
  display: block;
  background: var(--br-color-card-bg);
  border: var(--br-border-width-default) solid var(--br-color-card-border);
  border-radius: var(--br-radius-card);
  overflow: hidden;
  transition: border-color var(--br-transition-hover), transform var(--br-transition-hover);
}
a.br-card:hover {
  border-color: var(--br-color-border-strong);
  transform: translateY(calc(var(--br-motion-distance) / -4));
}


/* List row (contact) ----------------------------------------------------- */
.br-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--br-space-gap-md);
  padding: var(--br-space-inset-lg) var(--br-space-inset-xs);
  border-bottom: var(--br-border-width-default) solid var(--br-color-border-default);
  cursor: pointer;
  transition: padding var(--br-transition-hover), background-color var(--br-transition-hover);
}
.br-row:hover {
  padding-left: var(--br-space-inset-md);
  padding-right: var(--br-space-inset-md);
  background: var(--br-color-bg-subtle);
}


/* Input ------------------------------------------------------------------ */
.br-input {
  height: var(--br-size-input-height);
  padding: 0 var(--br-space-inset-md);
  border: var(--br-border-width-default) solid var(--br-color-input-border);
  border-radius: var(--br-radius-input);
  background: var(--br-color-input-bg);
  color: var(--br-color-text-primary);
  font-family: var(--br-font-family-body);
  font-size: var(--br-font-body-md-size);
  outline: none;
  transition: border-color var(--br-transition-hover);
}
.br-input::placeholder { color: var(--br-color-input-placeholder); }
.br-input:focus { border-color: var(--br-color-input-border-focus); }


/* Card variants ---------------------------------------------------------- */
.br-card--highlight {
  background: var(--br-color-card-highlight-bg);
  border-color: var(--br-color-card-highlight-bg);
  color: var(--br-color-card-highlight-fg);
}
.br-card--tint {
  background: var(--br-color-card-tint-bg);
  border-color: var(--br-color-card-tint-bg);
}
/* Quote mark: large decorative opening quote for principle / quote cards.
   It fills the free space above the quote and reaches a little below its first line
   (heading-sm line + gap-sm), sitting behind the text. Put it right before the <blockquote>. */
.br-quote-mark {
  flex: 1 1 0; /* only the space left above the quote, never its own height */
  min-height: var(--br-size-control-md);
  margin-bottom: calc(-1 * (var(--br-font-heading-sm-line-height) + var(--br-space-gap-sm)));
  color: var(--br-color-quote-mark);
  pointer-events: none;
}
.br-quote-mark svg { display: block; height: 100%; width: auto; }

.br-card--feature {
  background: var(--br-color-card-feature-bg);
  border-color: var(--br-color-card-feature-bg);
  color: var(--br-color-card-feature-fg);
}


/* Segmented filter (nav) ------------------------------------------------- */
.br-segmented {
  display: inline-flex;
  align-items: center;
  gap: var(--br-space-nav-item-gap);
  padding: var(--br-space-nav-padding);
  background: color-mix(in srgb, var(--br-color-card-bg) 70%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border: var(--br-border-width-default) solid var(--br-color-card-border);
  border-radius: var(--br-radius-nav);
}
.br-segmented .br-nav-item {
  height: var(--br-size-control-sm);
  padding: 0 var(--br-space-inset-md);
  border: 0;
  background: transparent;
  cursor: pointer;
}
.br-segmented .br-nav-item:hover { background: var(--br-color-nav-item-bg-hover); }
@media (max-width: 819px) {
  /* Mobile keeps the 40px touch height (control-sm) but uses desktop's 16px side padding. */
  .br-segmented .br-nav-item {
    padding: 0 calc(var(--br-space-inset-md) + var(--br-space-inset-xs));
  }
}
.br-segmented .br-nav-item--active,
.br-segmented .br-nav-item--active:hover {
  background: var(--br-color-nav-item-active-bg);
  color: var(--br-color-nav-item-active-fg);
}


/* Bento grid ------------------------------------------------------------- */
/* 4 columns on desktop, 2 on mobile; dense flow packs mixed sizes.
   Tracks are half a row tall so the smallest card (--half) can exist:
   --half = ½ row, default = 1 row, --h2 = 2 rows. */
.br-bento {
  display: grid;
  grid-template-columns: repeat(var(--br-layout-bento-columns), minmax(0, 1fr));
  grid-auto-rows: minmax(calc((var(--br-size-bento-row) - var(--br-space-bento-gap)) / 2), auto);
  grid-auto-flow: row dense;
  gap: var(--br-space-bento-gap);
}
.br-bento-cell { position: relative; min-width: 0; grid-column: span 1; grid-row: span 2; }
.br-bento-cell--w2 { grid-column: span 2; }
.br-bento-cell--h2 { grid-row: span 4; }
.br-bento-cell--half { grid-row: span 1; }
@media (max-width: 819px) {
  .br-bento-cell--half { grid-column: span 2; } /* full width on mobile: no holes, one line */
}
.br-bento-cell > * {
  height: 100%;
  transition:
    opacity var(--br-transition-card-reorder),
    transform var(--br-transition-card-reorder),
    translate var(--br-transition-card-push),
    scale var(--br-transition-card-push),
    border-color var(--br-transition-hover);
}
/* Hover push (set from JS): the hovered card grows via `scale`, neighbours
   move away via `translate`. Replaces the default card lift inside the bento. */
.br-bento-cell > a.br-card:hover { transform: none; }
.br-bento-cell--dim > a.br-card:hover { transform: scale(var(--br-motion-scale)); }
.br-bento-cell--hover { z-index: 1; }

/* Float: while a card is hovered the others drift a few px in place.
   Amplitude eases in/out through a registered property, so nothing snaps. */
@property --br-float-amp {
  syntax: '<length>';
  inherits: true;
  initial-value: 0px;
}
.br-bento { transition: --br-float-amp var(--br-transition-card-push); }
.br-bento--floating { --br-float-amp: var(--br-motion-float-distance); }
@keyframes br-float {
  0%, 100% { translate: 0 0; }
  25% { translate: calc(var(--br-float-amp) * 0.5) calc(var(--br-float-amp) * -0.6); }
  50% { translate: 0 calc(var(--br-float-amp) * -1); }
  75% { translate: calc(var(--br-float-amp) * -0.5) calc(var(--br-float-amp) * -0.4); }
}
.br-bento-cell { animation: br-float 5.6s ease-in-out infinite; }
.br-bento-cell:nth-child(4n+1) { animation-duration: 5.2s; animation-delay: -1.3s; }
.br-bento-cell:nth-child(4n+2) { animation-duration: 6.1s; animation-delay: -3.7s; }
.br-bento-cell:nth-child(4n+3) { animation-duration: 5.7s; animation-delay: -2.2s; }
.br-bento-cell:nth-child(4n)   { animation-duration: 6.6s; animation-delay: -4.4s; }
.br-bento-cell--hover { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .br-bento-cell { animation: none; }
}
.br-bento-cell--dim > * {
  opacity: var(--br-opacity-dim);
  transform: scale(var(--br-motion-scale));
}


/* Icon button (round) ---------------------------------------------------- */
.br-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--br-size-hit-area-min);
  height: var(--br-size-hit-area-min);
  padding: 0;
  border-radius: var(--br-radius-pill);
  border: var(--br-border-width-default) solid var(--br-color-button-secondary-border);
  background: var(--br-color-button-secondary-bg);
  color: var(--br-color-icon-default);
  cursor: pointer;
  transition:
    background-color var(--br-transition-hover),
    border-color var(--br-transition-hover),
    color var(--br-transition-hover),
    transform var(--br-transition-press);
}
.br-icon-btn:hover { border-color: var(--br-color-button-secondary-border-hover); }
.br-icon-btn:active { transform: scale(var(--br-motion-scale)); }
.br-icon-btn svg { width: var(--br-icon-button); height: var(--br-icon-button); }
.br-icon-btn--inverse {
  background: var(--br-color-card-feature-bg);
  border-color: var(--br-color-card-feature-bg);
  color: var(--br-color-card-feature-fg);
}
.br-icon-btn--inverse:hover { border-color: var(--br-color-focus-ring); }
/* Plain: borderless icon action on dark feature cards; brightens on hover. */
.br-icon-btn--plain {
  background: transparent;
  border-color: transparent;
  color: var(--br-color-card-feature-fg-muted);
}
/* External: on hover/focus the icon fades back and a ↗ appears centered over it —
   the link leaves the site. */
.br-icon-btn--external { position: relative; }
.br-icon-btn--external svg { transition: opacity var(--br-transition-hover); }
.br-icon-btn .br-icon-btn__external {
  position: absolute;
  inset: 0;
  margin: auto;
  width: var(--br-icon-sm); /* 16px in every mode */
  height: var(--br-icon-sm);
  opacity: 0;
  transform: translate(calc(var(--br-space-inset-xs) * -1), var(--br-space-inset-xs));
  transition: opacity var(--br-transition-hover), transform var(--br-transition-hover);
}
.br-icon-btn--external:hover svg:not(.br-icon-btn__external),
.br-icon-btn--external:focus-visible svg:not(.br-icon-btn__external) { opacity: var(--br-opacity-dim); }
.br-icon-btn--external:hover .br-icon-btn__external,
.br-icon-btn--external:focus-visible .br-icon-btn__external { opacity: 1; transform: none; }

/* Morph: the round icon button stretches into a pill and swaps its icon for a short label
   (e.g. copy email → "Copied"). Toggle .is-copied. */
.br-icon-btn--morph {
  position: relative;
  transition:
    width var(--br-transition-card-filter),
    border-color var(--br-transition-hover),
    color var(--br-transition-hover);
}
.br-icon-btn--morph svg,
.br-icon-btn--morph .br-icon-btn__label { transition: opacity var(--br-transition-hover); }
.br-icon-btn--morph .br-icon-btn__label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  white-space: nowrap;
  opacity: 0;
}
.br-icon-btn--morph.is-copied {
  pointer-events: none; /* not clickable while it shows the confirmation */
  cursor: default;
  width: calc(var(--br-size-hit-area-min) * 2);
  border-color: var(--br-color-card-feature-fg-muted);
  color: var(--br-color-card-feature-fg);
}
.br-icon-btn--morph.is-copied svg { opacity: 0; }
.br-icon-btn--morph.is-copied .br-icon-btn__label { opacity: 1; }
.br-icon-btn--plain:hover {
  border-color: var(--br-color-card-feature-fg-muted);
  color: var(--br-color-card-feature-fg);
}

/* Visually hidden, still read by screen readers (e.g. live status messages). */
.br-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}



/* Avatar ----------------------------------------------------------------- */
/* Round avatar: initials on the accent surface, or an <img> child (photo). */
.br-avatar {
  --br-avatar-size: var(--br-size-avatar-lg);
  flex: none;
  display: grid;
  place-items: center;
  width: var(--br-avatar-size);
  height: var(--br-avatar-size);
  border-radius: var(--br-radius-pill);
  overflow: hidden;
  background: var(--br-color-card-highlight-bg);
  color: var(--br-color-card-highlight-fg);
  font-family: var(--br-font-family-accent);
  font-weight: var(--br-font-weight-extrabold);
  font-size: calc(var(--br-avatar-size) * 0.36);
  letter-spacing: var(--br-font-tracking-tight);
  line-height: 1;
}
.br-avatar--md { --br-avatar-size: var(--br-size-avatar-md); }
.br-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* Revision: show a word struck out and its replacement (<del class="br-strike"> + <ins class="br-insert">). */
.br-strike {
  color: var(--br-color-text-secondary);
  text-decoration: line-through;
  text-decoration-thickness: var(--br-border-width-strong);
}
.br-insert { text-decoration: none; }

/* Highlight: marker-style emphasis inside running text (lime surface, so it stays legible). */
.br-highlight {
  background: var(--br-color-card-highlight-bg);
  color: var(--br-color-card-highlight-fg);
  font-weight: var(--br-font-weight-medium);
  padding: 0 var(--br-space-inset-xs);
  border-radius: var(--br-radius-sm);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}


/* Status dot ------------------------------------------------------------- */
/* Small "live / available" dot with a slow pulse ring. */
.br-status-dot {
  position: relative;
  flex: none;
  width: var(--br-space-gap-md);
  height: var(--br-space-gap-md);
  border-radius: var(--br-radius-pill);
  background: var(--br-color-status-success-text);
}
.br-status-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: inherit;
  animation: br-pulse 2.4s var(--br-easing-standard) infinite;
}
/* Tile: small illustrated square for personal cards (64px, 48 on mobile).
   Tint ground with surface-coloured line art. */
.br-tile {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: var(--br-size-icon-tile);
  height: var(--br-size-icon-tile);
  border-radius: var(--br-radius-md);
  overflow: hidden;
  background: color-mix(in srgb, var(--br-color-bg-tint) 75%, var(--br-color-border-strong)); /* ground */
  color: var(--br-color-card-bg); /* line art */
}
@media (max-width: 819px) {
  .br-tile { width: var(--br-size-control-lg); height: var(--br-size-control-lg); }
}

/* Map tile (.br-tile.br-map-tile): roads drawn full-bleed, a .br-status-dot pin with a soft halo. */
.br-map-tile svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.br-map-tile .br-status-dot {
  outline: var(--br-space-inset-xs) solid color-mix(in srgb, var(--br-color-status-success-text) 25%, transparent);
}

/* Cycle tile (.br-tile.br-tile--cycle): up to 4 stacked icons that take turns, 2.5s each.
   Reduced motion shows only the first one. */
.br-tile--cycle svg {
  position: absolute;
  width: 55%;
  height: 55%;
  opacity: 0;
  animation: br-tile-cycle 10s var(--br-easing-standard) infinite;
}
.br-tile--cycle svg:nth-child(2) { animation-delay: 2.5s; }
.br-tile--cycle svg:nth-child(3) { animation-delay: 5s; }
.br-tile--cycle svg:nth-child(4) { animation-delay: 7.5s; }
/* Bare tile (.br-tile--bare): no ground, larger art in the success green (same as the location pin). */
.br-tile--bare {
  background: none;
  color: var(--br-color-status-success-text);
}
.br-tile--bare.br-tile--cycle svg { width: 80%; height: 80%; }
/* Line art keeps the same on-screen stroke as the 20px UI icons (1.5 on a 16 grid = 1.875px),
   however large the tile draws it. */
.br-tile--cycle svg path {
  vector-effect: non-scaling-stroke;
  stroke-width: 1.875px;
}
/* Signal tile (.br-tile.br-tile--bare.br-tile--signal): an emblem that blinks like a failing light. */
.br-tile--signal svg { width: 80%; height: 80%; }
.br-tile--signal svg ellipse {
  vector-effect: non-scaling-stroke;
  stroke-width: 1.875px;
}
.br-tile--signal .br-tile__emblem { animation: br-flicker 4s steps(1, end) infinite; }
@keyframes br-flicker {
  0%, 100% { opacity: 1; }
  3% { opacity: 0.25; }
  6% { opacity: 1; }
  41% { opacity: 0.4; }
  44% { opacity: 1; }
  70% { opacity: 0.6; }
  72% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .br-tile--signal .br-tile__emblem { animation: none; }
}
@keyframes br-tile-cycle {
  0%   { opacity: 0; transform: translateY(var(--br-motion-distance)); }
  5%   { opacity: 1; transform: none; }
  22%  { opacity: 1; transform: none; }
  27%  { opacity: 0; transform: translateY(calc(var(--br-motion-distance) * -1)); }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .br-tile--cycle svg { animation: none; }
  .br-tile--cycle svg:first-child { opacity: 1; }
}

@keyframes br-pulse {
  0% { transform: scale(1); opacity: 0.6; }
  80%, 100% { transform: scale(2.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .br-status-dot::after { animation: none; }
}
