/* ==========================================================================
   ABTB 2026 front-end -- Trendy
   Generated from prototypes/trendy.html (git-tracked; edit the prototype, re-run
   the extractor, do not hand-edit this file for design changes).
   Fonts are self-hosted next door in ../font/abtb2026/ -- no CDN, matching the
   direction of the 2025 performance pass.
   ========================================================================== */

@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(../font/abtb2026/playfair-500-italic-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(../font/abtb2026/playfair-500-italic-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(../font/abtb2026/playfair-500-italic-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../font/abtb2026/playfair-500-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../font/abtb2026/playfair-500-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../font/abtb2026/playfair-500-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../font/abtb2026/playfair-600-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../font/abtb2026/playfair-600-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../font/abtb2026/playfair-600-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(../font/abtb2026/playfair-700-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(../font/abtb2026/playfair-700-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(../font/abtb2026/playfair-700-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-400-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-400-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-400-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-500-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-500-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-500-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-700-1.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-700-2.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(../font/abtb2026/roboto-700-3.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

  :root {
    color-scheme: light;
    --brand: #003399;
    --paper: #e9ecf3;
    --surface: #ffffff;
    --surface-raised: #ffffff;
    --ink: #13151b;
    --ink-soft: #5c606b;
    --ink-faint: #8b8f9a;
    --line: #dbdfe8;
    --accent: #003399;
    --accent-soft: #e9edfa;
    --accent-hover: #2b5fd9;
    --on-accent: #ffffff;      /* text/icons sitting on an --accent fill */
    /* Cards keep their own accent so the chrome can go more vivid without
       dragging the grid with it. Identical to --accent in light; deliberately
       the softer blue in dark, which is what the card hover wants. */
    --card-accent: #003399;
    --card-accent-soft: #e9edfa;
    --logo-ink: var(--accent);
    --glow: rgba(0,51,153,.16);
    --card-shadow: 0 1px 2px rgba(20,28,55,.06), 0 14px 32px -16px rgba(20,28,55,.16);
    --footer-bg: #0a1128;
    --footer-ink: #c7cbe0;
    --footer-ink-soft: #7a80a0;
  }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
      color-scheme: dark;
      --paper: #0c0e13;
      --surface: #171a21;
      --surface-raised: #1d2029;
      --ink: #edeef2;
      --ink-soft: #979bA7;
      --ink-faint: #676b76;
      --line: #262a34;
      --accent: #4f86ff;         /* vivid enough to still read as the brand blue */
      --accent-soft: #16223c;
      --accent-hover: #7ea6ff;
      --on-accent: #0c0e13;      /* near-black on the light blue, not white */
      --logo-ink: #ffffff;       /* the wordmark reads better plain white on dark */
      --card-accent: #86a8ee;    /* softer than the chrome blue -- easier on a wall of images */
      --card-accent-soft: #1b2740;
      --glow: rgba(134,168,238,.24);
      --card-shadow: 0 1px 2px rgba(0,0,0,.3), 0 16px 36px -16px rgba(0,0,0,.55);
    }
  }
  :root[data-theme="dark"] {
    color-scheme: dark;
    --paper: #0c0e13;
    --surface: #171a21;
    --surface-raised: #1d2029;
    --ink: #edeef2;
    --ink-soft: #979bA7;
    --ink-faint: #676b76;
    --line: #262a34;
    --accent: #4f86ff;
    --accent-soft: #16223c;
    --accent-hover: #7ea6ff;
    --on-accent: #0c0e13;
    --logo-ink: #ffffff;
    --card-accent: #86a8ee;
    --card-accent-soft: #1b2740;
    --glow: rgba(134,168,238,.24);
    --card-shadow: 0 1px 2px rgba(0,0,0,.3), 0 16px 36px -16px rgba(0,0,0,.55);
  }

  * { box-sizing: border-box; }
  html { scroll-behavior: smooth; }
  body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: 'Roboto', sans-serif;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    transition: background .3s ease, color .3s ease;
  }
  a { color: inherit; text-decoration: none; }
  img { max-width: 100%; display: block; }
  .display { font-family: 'Playfair Display', Georgia, serif; }

  .container {
    max-width: 1360px;
    margin: 0 auto;
    padding: 0 clamp(16px, 4vw, 40px);
  }

  /* ================= HEADER ================= */
  header.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    border-bottom: 1px solid var(--line);
    transition: box-shadow .25s ease, background .3s ease, border-color .3s ease;
  }
  header.site-header.scrolled { box-shadow: 0 6px 24px rgba(10,17,40,0.10); }

  .header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 16px clamp(16px, 4vw, 40px);
  }
  .logo-mark { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
  .logo-mark svg { height: 20px; width: auto; }
  .logo-mark svg path { fill: var(--logo-ink); transition: fill .3s ease; }
  .logo-mark .tagline {
    position: relative;
    font-size: 10.5px;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--ink-soft);
    padding-left: 11px;
    line-height: 1.3;
    display: none;
    transition: color .4s ease;
  }
  /* The rule is a pseudo-element rather than a border, so it can gain weight and
     reach on hover without nudging the caption sideways by the extra pixel.
     Nothing in the block moves: the divider does the work. */
  .logo-mark .tagline::before {
    content: '';
    position: absolute; left: 0; top: 50%;
    width: 1px; height: 100%;
    transform: translateY(-50%);
    background: var(--ink-faint);
    transition: width .38s cubic-bezier(.2, .8, .2, 1),
                height .38s cubic-bezier(.2, .8, .2, 1),
                background .38s ease;
  }
  .logo-mark:hover .tagline { color: var(--ink); }
  .logo-mark:hover .tagline::before { width: 2px; height: 136%; background: var(--accent); }
  .logo-mark:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; border-radius: 4px; }
  /* the colour shift is welcome either way; only the growth is motion */
  @media (prefers-reduced-motion: reduce) {
    .logo-mark .tagline::before { transition: background .38s ease; }
  }
  @media (min-width: 640px) { .logo-mark .tagline { display: block; } }

  nav.main-nav { display: none; align-items: center; gap: 4px; }
  nav.main-nav a {
    font-size: 16px;
    font-weight: 500;
    padding: 10px 18px;
    border-radius: 100px;
    color: var(--ink);
    position: relative;
    transition: color .15s ease, background .15s ease;
  }
  nav.main-nav a:hover { background: var(--accent-soft); color: var(--accent); }
  nav.main-nav a.current { color: var(--accent); font-weight: 700; }
  @media (min-width: 900px) { nav.main-nav { display: flex; } }

  .header-actions { display: flex; align-items: center; gap: 10px; }

  .theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink);
    cursor: pointer;
    flex-shrink: 0;
    transition: color .18s ease, background .18s ease, border-color .18s ease, transform .18s ease;
  }
  .theme-toggle:hover {
    border-color: var(--accent); color: var(--accent);
    background: var(--accent-soft); transform: translateY(-1px);
  }
  .theme-toggle:active { transform: translateY(0); }
  .theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .theme-toggle svg { width: 18px; height: 18px; transition: transform .35s cubic-bezier(.2,.8,.2,1); }
  .theme-toggle:hover svg { transform: rotate(22deg); }
  .theme-toggle .icon-moon { display: none; }
  :root[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
  :root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: none; }
    :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: block; }
  }

  .btn-contact {
    display: none;
    align-items: center; justify-content: center; gap: 8px;
    font-size: 15px;
    font-weight: 600;
    color: var(--on-accent);
    background: var(--accent);
    padding: 10px 22px;
    border-radius: 100px;
    white-space: nowrap;            /* never let the label break onto a second line */
    flex-shrink: 0;
    transition: filter .15s ease, transform .15s ease;
  }
  .btn-contact:hover { filter: brightness(1.15); transform: translateY(-1px); }
  .btn-contact:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
  .btn-contact svg { width: 18px; height: 18px; }
  @media (min-width: 900px) { .btn-contact { display: inline-flex; } }
  /* Narrow desktop / wide tablet: the label crowds the nav, so the button drops
     to the envelope alone and matches the other two round header controls. */
  @media (max-width: 1180px) {
    .btn-contact { width: 40px; height: 40px; padding: 0; }
    .btn-contact .btn-contact-text { display: none; }
  }
  @media (min-width: 1181px) { .btn-contact svg { display: none; } }

  .menu-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: var(--surface);
    cursor: pointer;
  }
  .menu-toggle svg path { stroke: var(--ink); }
  @media (min-width: 900px) { .menu-toggle { display: none; } }

  /* ================= MOBILE NAVIGATION =================
     The hamburger has been in the header since the first prototype with
     nothing behind it. This is what it opens: a right-hand sheet carrying the
     full navigation, site search, the project categories, contacts, socials
     and the theme control — everything a desktop visitor gets from the header
     and the footer combined.

     Closed state is the `inert` attribute rather than display:none, so the
     panel can animate in and out. inert takes it out of the tab order and out
     of the accessibility tree just as thoroughly, without killing the
     transition the way display:none does. */
  .mobile-nav { position: fixed; inset: 0; z-index: 200; pointer-events: none; }
  .mobile-nav.open { pointer-events: auto; }
  @media (min-width: 900px) { .mobile-nav { display: none; } }

  .mobile-nav-scrim {
    position: absolute; inset: 0;
    background: rgba(8, 10, 18, .55);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    opacity: 0;
    transition: opacity .3s ease;
  }
  .mobile-nav.open .mobile-nav-scrim { opacity: 1; }

  .mobile-nav-panel {
    position: absolute; top: 0; right: 0;
    width: min(420px, 88vw);
    height: 100%;
    height: 100dvh;                 /* mobile browser chrome must not clip the footer of the sheet */
    display: flex;
    flex-direction: column;
    padding: 18px clamp(18px, 5vw, 26px) 26px;
    overflow-y: auto;
    overscroll-behavior: contain;   /* scrolling to the end of the sheet must not start scrolling the page */
    background: var(--surface);
    border-left: 1px solid var(--line);
    box-shadow: -24px 0 60px -30px rgba(8, 10, 18, .5);
    transform: translateX(101%);
    transition: transform .34s cubic-bezier(.2, .8, .2, 1);
  }
  .mobile-nav.open .mobile-nav-panel { transform: none; }
  @media (prefers-reduced-motion: reduce) {
    .mobile-nav-scrim, .mobile-nav-panel { transition: none; }
  }

  .mobile-nav-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
  .mobile-nav-title {
    font-size: 11px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--ink-faint);
  }
  .mobile-nav-close {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; margin-right: -6px;
    border: 1px solid var(--line); border-radius: 100px;
    background: var(--surface); color: var(--ink); cursor: pointer;
    transition: border-color .18s ease, color .18s ease;
  }
  .mobile-nav-close svg { width: 18px; height: 18px; }
  .mobile-nav-close:hover { border-color: var(--accent); color: var(--accent); }
  .mobile-nav-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

  .mobile-nav-search {
    display: flex; align-items: center; gap: 10px;
    margin: 12px 0 16px; padding: 0 15px; height: 46px;
    border: 1px solid var(--line); border-radius: 100px; background: var(--paper);
    transition: border-color .18s ease;
  }
  .mobile-nav-search svg { width: 18px; height: 18px; color: var(--ink-faint); flex-shrink: 0; }
  .mobile-nav-search input {
    flex: 1; min-width: 0; border: 0; background: none;
    font: inherit; font-size: 15px; color: var(--ink); outline: none;
  }
  .mobile-nav-search:focus-within { border-color: var(--accent); }

  .mobile-nav-links { display: flex; flex-direction: column; }
  .mobile-nav-links > a {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 15px 0;
    font-size: 21px; font-weight: 700; letter-spacing: -.01em;
    color: var(--ink);
    border-bottom: 1px solid var(--line);
    transition: color .18s ease;
  }
  .mobile-nav-links > a:hover, .mobile-nav-links > a.current { color: var(--accent); }
  .mobile-nav-links > a svg { width: 16px; height: 16px; opacity: .4; flex-shrink: 0; }
  .mobile-nav-links > a:hover svg { opacity: 1; }
  .mobile-nav-links > a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

  .mobile-nav-sub {
    display: flex; flex-wrap: wrap; gap: 6px;
    padding: 13px 0 16px;
    border-bottom: 1px solid var(--line);
  }
  .mobile-nav-sub a {
    font-size: 13px; font-weight: 600; color: var(--ink-soft);
    border: 1px solid var(--line); border-radius: 100px; padding: 6px 12px;
    transition: color .18s ease, border-color .18s ease, background .18s ease;
  }
  .mobile-nav-sub a:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

  .mobile-nav-foot { margin-top: auto; padding-top: 26px; display: flex; flex-direction: column; gap: 14px; }
  .mobile-nav-contacts { display: flex; flex-direction: column; gap: 7px; }
  .mobile-nav-contacts a { font-size: 15.5px; font-weight: 600; color: var(--ink); transition: color .18s ease; }
  .mobile-nav-contacts a:hover { color: var(--accent); }
  .mobile-nav-social { display: flex; flex-wrap: wrap; gap: 14px; }
  .mobile-nav-social a {
    font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
    border-bottom: 1px solid var(--line);
    transition: color .18s ease, border-color .18s ease;
  }
  .mobile-nav-social a:hover { color: var(--accent); border-color: var(--accent); }
  .mobile-nav-utility { display: flex; align-items: center; gap: 12px; padding-top: 4px; }
  .mobile-nav-utility-label { font-size: 13px; color: var(--ink-soft); }

  /* The page behind the sheet must not scroll with it. position:fixed plus a
     negative top is the only version that holds on iOS Safari, where overflow
     hidden on <body> alone does nothing; the offset is restored on close so
     the reader keeps their place. */
  body.nav-open { position: fixed; width: 100%; overflow: hidden; }

  /* ================= CATEGORY HERO ================= */
  .cat-hero { padding-top: clamp(36px, 7vw, 76px); padding-bottom: clamp(24px, 4vw, 40px); }
  .breadcrumb {
    display: flex; gap: 8px; align-items: center;
    font-size: 14.5px; color: var(--ink-soft); margin-bottom: 22px;
  }
  .breadcrumb a:hover { color: var(--accent); }
  .breadcrumb .sep { color: var(--ink-soft); }
  .breadcrumb .current { color: var(--ink); font-weight: 600; }

  .cat-hero h1 {
    font-size: clamp(40px, 7vw, 74px);
    font-weight: 600;
    margin: 0 0 12px;
    letter-spacing: -0.015em;
    line-height: 1.02;
    text-wrap: balance;
  }
  .cat-count { font-size: 13.5px; color: var(--ink-soft); margin: 0 0 22px; }
  .cat-count strong { color: var(--accent); font-weight: 700; }
  .cat-desc { max-width: 58ch; color: var(--ink-soft); font-size: 17px; margin: 0; }

  /* ================= PROJECT GRID (bento, caption-panel cards) ================= */
  /* fluid column count — reflows continuously with viewport width, not fixed breakpoints */
  .project-grid {
    /* Uniform row rhythm. --row-h is the height of one single-cell card; JS keeps
       it in sync with the measured column width (--card-ratio = height / width).
       Every card fills its row exactly, so every gap and every row is identical.
       auto-fill (not auto-fit) keeps empty tracks alive, so a filtered-down grid
       keeps the same card size instead of stretching survivors across the row. */
    --col-min: 240px;
    --card-ratio: 1.3333;            /* 3/4 portrait cell */
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--col-min), 1fr));
    grid-auto-rows: var(--row-h, auto);
    grid-auto-flow: dense;
    gap: clamp(14px, 2.4vw, 28px);
    padding: clamp(28px, 5vw, 56px) 0 clamp(56px, 9vw, 104px);
  }

  .project-card {
    --mx: 50%; --my: 50%; --rx: 0deg; --ry: 0deg;
    /* aspect-ratio is the no-JS fallback; it goes inert as soon as --row-h
       resolves to a length and height:100% gets a definite row to fill */
    aspect-ratio: 3/4;
    /* both axes definite once --row-h lands, which stops aspect-ratio
       from re-deriving the width and overflowing the grid track */
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    position: relative;
    border-radius: 20px;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--line);
    box-shadow: var(--card-shadow);
    opacity: 0;
    transform: perspective(1000px) rotateX(var(--rx)) rotateY(var(--ry)) translateY(22px);
    transition: opacity .6s ease, transform .5s cubic-bezier(.2,.8,.2,1), box-shadow .3s ease, border-color .3s ease;
  }
  .project-card.in-view {
    opacity: 1;
    transform: perspective(1000px) rotateX(var(--rx)) rotateY(var(--ry)) translateY(0);
  }
  .project-card::after {
    content: '';
    position: absolute; inset: 0;
    background: radial-gradient(420px circle at var(--mx) var(--my), var(--glow), transparent 62%);
    opacity: 0;
    transition: opacity .3s ease;
    pointer-events: none;
    z-index: 2;
  }
  .project-card:hover {
    box-shadow: 0 22px 44px -16px var(--glow), 0 4px 14px -4px var(--glow);
    border-color: var(--card-accent);
  }
  .project-card:hover::after { opacity: 1; }

  /* Promoted card: two columns wide, exactly one row tall -- same height and the
     same bottom edge as the single-cell cards in its row, with the image filling
     the extra width as a panorama. The 8/5 aspect-ratio is only the no-JS
     fallback (a touch shorter than the real 2x1 cell, so it never inflates rows).
     The caption panel keeps the standard height so panels line up across the row. */
  .project-card.wide, .project-card.large { grid-column: span 1; }
  @media (min-width: 600px) {
    .project-card.wide  { grid-column: span 2; aspect-ratio: 8/5; }
    .project-card.large { grid-column: span 2; grid-row: span 2; aspect-ratio: 10/13; }
  }

  .card-media { position: relative; flex: 1 1 auto; min-height: 0; background: var(--paper); overflow: hidden; }
  .card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

  .card-info { flex: 0 0 auto; height: 110px; overflow: hidden; padding: 16px 20px; display: flex; align-items: flex-start; gap: 14px; }
  .card-index {
    font-family: ui-monospace, "Cascadia Code", "SF Mono", Consolas, monospace;
    font-size: 12px;
    color: var(--ink-faint);
    padding-top: 4px;
    flex-shrink: 0;
  }
  .card-text { min-width: 0; }
  .card-tag {
    display: inline-block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--card-accent);
    background: var(--card-accent-soft);
    padding: 3px 9px;
    border-radius: 100px;
    margin-bottom: 8px;
    /* the caption panel is a fixed height, so a long tag list clips instead of
       wrapping and pushing the title out of the card */
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .card-name {
    font-family: 'Roboto', sans-serif;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.01em;
    line-height: 1.28;
    margin: 0;
    color: var(--ink);
    overflow-wrap: break-word;
    transition: color .2s ease;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .project-card.wide .card-name  { font-size: 25px; -webkit-line-clamp: 1; }
  /* the 2x2 card is tall enough for a two-line title; its caption panel grows to
     match, and its bottom edge still lines up with the row it ends on */
  .project-card.large .card-name { font-size: 28px; -webkit-line-clamp: 2; }
  @media (min-width: 600px) { .project-card.large .card-info { height: 148px; } }
  .project-card:hover .card-name { color: var(--card-accent); }

  /* ================= FOOTER (always dark, independent of page theme) ================= */
  footer.site-footer { background: var(--footer-bg); color: var(--footer-ink); padding: clamp(48px, 8vw, 80px) 0 28px; margin-top: 0; }
  .footer-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 32px 40px; padding-bottom: 40px; border-bottom: 1px solid rgba(255,255,255,.09); }
  .footer-brand svg path { fill: #fff; }
  .footer-brand svg { height: 20px; margin-bottom: 18px; }
  .footer-brand p { color: var(--footer-ink-soft); font-size: 13.5px; max-width: 34ch; }
  .footer-col h5 { font-size: 13px; text-transform: uppercase; letter-spacing: .08em; color: var(--footer-ink-soft); margin: 0 0 14px; font-weight: 700; }
  .footer-col a, .footer-col p { display: block; font-size: 14px; color: var(--footer-ink); margin-bottom: 10px; }
  .footer-col a:hover { color: #fff; }
  .footer-search-band {
    padding: 22px 0; border-bottom: 1px solid rgba(255,255,255,.09);
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
  }
  .lang-switch {
    position: relative;
    display: inline-flex; align-items: center; gap: 2px;
    padding: 3px; border-radius: 100px;
    border: 1px solid rgba(255,255,255,.18);
    transition: border-color .3s ease, background .3s ease, box-shadow .3s ease;
  }
  .lang-switch:hover {
    border-color: rgba(255,255,255,.5);
    background: rgba(255,255,255,.05);
    box-shadow: 0 0 0 4px rgba(255,255,255,.05);
  }
  /* the filled pill is a real element so it can slide between the two options */
  .lang-thumb {
    position: absolute; top: 3px; left: 3px;
    height: calc(100% - 6px); width: 0;
    border-radius: 100px; background: #fff;
    pointer-events: none;
    transition: transform .48s cubic-bezier(.32, 1.4, .5, 1), width .48s cubic-bezier(.32, 1.4, .5, 1);
  }
  .lang-switch a {
    position: relative; z-index: 1;
    padding: 7px 15px; border-radius: 100px;
    font-size: 12.5px; font-weight: 600; letter-spacing: .06em;
    color: var(--footer-ink-soft);
    transition: color .32s ease;
  }
  .lang-switch a:hover { color: #fff; }
  .lang-switch a.current, .lang-switch a.current:hover { color: #0a1128; }
  @media (prefers-reduced-motion: reduce) { .lang-thumb { transition: none; } }
  .footer-search {
    display: inline-flex; align-items: center; gap: 10px;
    padding: 11px 20px; border-radius: 100px;
    border: 1px solid rgba(255,255,255,.18);
    color: var(--footer-ink); font-size: 14px;
    transition: color .15s ease, background .15s ease, border-color .15s ease;
  }
  .footer-search svg { width: 16px; height: 16px; }
  .footer-search:hover { color: #fff; border-color: rgba(255,255,255,.42); background: rgba(255,255,255,.06); }
  .footer-bottom { display: flex; flex-direction: column; gap: 10px; padding-top: 24px; font-size: 12.5px; color: var(--footer-ink-soft); }
  @media (min-width: 780px) { .footer-bottom { flex-direction: row; justify-content: space-between; } }
  .footer-social { display: flex; gap: 14px; }
  .footer-social a { color: var(--footer-ink-soft); font-size: 12.5px; }
  .footer-social a:hover { color: #fff; }


  /* ============ HEADER SEARCH (collapsed pill -> expanding field) ============
     This filters what is on the page. Site-wide search is a separate destination,
     linked from the footer -- the two are deliberately not the same control. */
  .header-search {
    display: flex; align-items: center;
    height: 40px; border-radius: 100px;
    border: 1px solid var(--line); background: var(--surface);
    transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
  }
  .header-search:hover { border-color: var(--accent); transform: translateY(-1px); }
  .header-search.open { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); transform: none; }
  .search-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 100px;
    border: none; background: transparent; color: var(--ink);
    cursor: pointer; flex-shrink: 0;
    transition: color .18s ease;
  }
  .header-search:hover .search-toggle, .header-search.open .search-toggle { color: var(--accent); }
  .search-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .search-toggle svg { width: 18px; height: 18px; }
  .header-search-field {
    width: 0; min-width: 0; padding: 0; opacity: 0;
    border: none; outline: none; background: transparent;
    height: 38px; color: var(--ink);
    font-family: inherit; font-size: 15px;
    transition: width .34s cubic-bezier(.2,.8,.2,1), opacity .22s ease, padding .34s cubic-bezier(.2,.8,.2,1);
  }
  .header-search-field::placeholder { color: var(--ink-faint); }
  .header-search.open .header-search-field { width: min(210px, 42vw); opacity: 1; padding: 0 16px 0 2px; }
  /* The expanded field must never widen the header past the viewport.
     Mid widths: the nav yields to it. Narrow: it stops being a fixed 210px and
     just takes whatever room is left beside the logo and the two icon buttons. */
  /* 1300px, not 1140: logo(284) + nav(404) + actions with the field open(453)
     plus gaps and page padding needs ~1270px, so the nav has to yield below that. */
  @media (max-width: 1300px) { body.header-search-open nav.main-nav { display: none; } }
  @media (max-width: 700px) {
    body.header-search-open .header-actions { flex: 1 1 auto; min-width: 0; }
    .header-search.open { flex: 1 1 auto; min-width: 0; }
    .header-search.open .header-search-field { width: auto; flex: 1 1 auto; min-width: 0; }
  }
  /* phones: the logo steps aside while searching, or the field is too narrow to type in */
  @media (max-width: 560px) { body.header-search-open .logo-mark { display: none; } }

  /* ============ GRID TOOLBAR ============ */
  .grid-toolbar {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
    padding: 10px 16px; margin: 4px 0 28px;
    background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
  }
  .toolbar-search {
    display: flex; align-items: center; gap: 8px;
    height: 36px; padding: 0 16px 0 2px;
    flex: 1 1 200px; min-width: 170px; max-width: 260px;
    border-right: 1px solid var(--line);
  }
  .toolbar-search svg { width: 16px; height: 16px; color: var(--ink-faint); flex-shrink: 0; }
  .toolbar-search input {
    border: none; outline: none; background: transparent; color: var(--ink);
    font-family: 'Roboto', sans-serif; font-size: 14px; width: 100%; height: 100%;
  }
  .toolbar-search input::placeholder { color: var(--ink-faint); }

  .toolbar-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: 2 1 240px; }
  .tag-chip {
    height: 36px; display: inline-flex; align-items: center;
    font-size: 14px; font-weight: 500; padding: 0 16px; border-radius: 100px;
    border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft);
    cursor: pointer; transition: color .15s ease, background .15s ease, border-color .15s ease;
  }
  .tag-chip:hover { border-color: var(--accent); color: var(--accent); }
  .tag-chip.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

  .toolbar-right { display: flex; align-items: center; gap: 10px; margin-left: auto; }
  /* Icon-only sort. The native <select> sits invisibly on top of the glyph, so it
     keeps its own dropdown, keyboard handling and screen-reader semantics. */
  .sort-control {
    position: relative; flex-shrink: 0;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line); border-radius: 100px;
    background: var(--paper); color: var(--ink-soft);
    transition: color .15s ease, background .15s ease, border-color .15s ease;
  }
  .sort-control:hover { border-color: var(--accent); color: var(--accent); }
  .sort-control:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
  .sort-control.open { border-color: var(--accent); color: var(--accent); }
  /* lights up while a non-default order is active, so the icon still reports state */
  .sort-control.is-sorted { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .sort-trigger {
    position: absolute; inset: -1px;   /* -1px so the border ring is clickable too */
    width: calc(100% + 2px); height: calc(100% + 2px);
    display: inline-flex; align-items: center; justify-content: center;
    border: none; background: transparent; color: inherit;
    cursor: pointer; padding: 0;
  }
  .sort-trigger svg { width: 17px; height: 17px; }
  .sort-trigger:focus-visible { outline: none; }

  /* Custom menu: a native <select> popup is drawn by the OS and can't be themed,
     so the options are our own listbox instead. */
  .sort-menu {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
    margin: 0; padding: 6px; list-style: none;
    min-width: 208px;
    background: var(--surface); border: 1px solid var(--line); border-radius: 14px;
    box-shadow: 0 2px 6px rgba(10,17,40,.06), 0 18px 40px -14px rgba(10,17,40,.28);
    opacity: 0; visibility: hidden; transform: translateY(-6px) scale(.98);
    transform-origin: top right;
    transition: opacity .16s ease, transform .16s cubic-bezier(.2,.8,.2,1), visibility .16s;
  }
  .sort-control.open .sort-menu { opacity: 1; visibility: visible; transform: translateY(0) scale(1); }
  .sort-menu li {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px; border-radius: 9px;
    font-size: 14px; color: var(--ink-soft); white-space: nowrap; cursor: pointer;
    transition: background .13s ease, color .13s ease;
  }
  .sort-menu li::before {
    content: ''; width: 6px; height: 6px; border-radius: 100px;
    background: transparent; flex-shrink: 0;
    transition: background .13s ease;
  }
  .sort-menu li:hover, .sort-menu li.focused { background: var(--accent-soft); color: var(--accent); }
  .sort-menu li[aria-selected="true"] { color: var(--ink); font-weight: 600; }
  .sort-menu li[aria-selected="true"]::before { background: var(--accent); }
  .toolbar-edit {
    display: none; align-items: center; gap: 7px;
    height: 36px;
    font-size: 13px; font-weight: 600; padding: 0 16px; border-radius: 100px;
    border: 1px solid var(--line); background: var(--paper); color: var(--ink);
    cursor: pointer; white-space: nowrap; transition: background .15s ease, color .15s ease, border-color .15s ease;
  }
  .toolbar-edit.show { display: inline-flex; }
  .toolbar-edit svg { width: 15px; height: 15px; }
  .toolbar-edit.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

  .project-card.is-hidden { display: none; }

  .card-resize {
    position: absolute; top: 10px; right: 10px; z-index: 4;
    width: 30px; height: 30px; border-radius: 100px; border: none;
    background: rgba(10,14,26,.55); color: #fff; backdrop-filter: blur(6px);
    display: none; align-items: center; justify-content: center; cursor: pointer;
  }
  .card-resize svg { width: 15px; height: 15px; }
  /* the glyph shows the size the card is at right now: tall cell, wide band, big block */
  .card-resize .ic { display: none; }
  .project-card:not(.wide):not(.large) .card-resize .ic-normal { display: block; }
  .project-card.wide  .card-resize .ic-wide  { display: block; }
  .project-card.large .card-resize .ic-large { display: block; }
  body.edit-mode .card-resize { display: flex; }
  body.edit-mode .project-card { outline: 2px dashed var(--line); outline-offset: 3px; }

  @media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .project-card { transition: none; }
  }
