/* ============================================================
   Advogados Dias — style.css
   Palette: warm paper white, ink black, deep forest accent.
   Type: Fraunces (display serif) + Inter (body).
   ============================================================ */

/* ---------- Fonts (self-hosted) ---------- */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/fraunces-v38-latin-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/fraunces-v38-latin-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/fraunces-v38-latin-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter-v20-latin-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter-v20-latin-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter-v20-latin-600.woff2') format('woff2');
}

/* ---------- Tokens ---------- */
:root {
  --paper: #faf9f6;
  --paper-2: #f2f0ea;
  --ink: #141517;
  --ink-soft: #4c4f52;
  --muted: #7b7e82;
  --hairline: #e5e3dc;
  --forest: #1d3a2e;
  --forest-deep: #142a21;
  /* --forest sits at 17% lightness — near-black, and its hue is invisible
     on anything small. This is the same hue lifted to 32%, for marks that
     have to actually read as green at a few pixels across. */
  --forest-bright: #2d7658;
  --sage: #dce6da;
  --sand: #ece5d6;
  --serif: 'Fraunces', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --radius-lg: 28px;
  --radius-md: 18px;
  --container: 1280px;
  --ease: cubic-bezier(.22, .61, .21, 1);
}

/* ---------- Reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* The palette is light by design — paper, sage, forest. Declaring that
   explicitly is what stops Chrome's automatic dark theme (on by default on
   many Android builds) from inverting the page: without it the UA assumes
   the site has no opinion and re-colours text to near-white, which left the
   hero copy invisible on its own pale wash. This is an opt-out, not a dark
   theme; building a real one would mean a second palette throughout. */
html { color-scheme: light; scroll-behavior: smooth; }

body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.container {
  width: min(var(--container), 100% - 4rem);
  margin-inline: auto;
}

/* ---------- Type ---------- */
.display {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.7rem, 3vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  max-width: 18em;
}

.section { padding: clamp(3.5rem, 6.5vw, 6rem) 0; }

.section-head {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  margin-bottom: clamp(2rem, 4vw, 3.5rem);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--hairline);
}
.section-num {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1rem;
  color: var(--forest);
}
.section-label {
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .85rem 1.7rem;
  border-radius: 999px;
  font-weight: 500;
  font-size: .95rem;
  line-height: 1;
  transition: transform .35s var(--ease), background .35s var(--ease),
              color .35s var(--ease), border-color .35s var(--ease);
  will-change: transform;
}
.btn:hover { transform: translateY(-2px); }
.btn-dark {
  background: var(--ink);
  color: var(--paper);
}
.btn-dark:hover { background: var(--forest); }
.btn-ghost {
  border: 1px solid var(--ink);
  background: transparent;
}
.btn-ghost:hover { background: var(--ink); color: var(--paper); }
.btn-sm { padding: .6rem 1.15rem; font-size: .85rem; }
.btn-wide { width: 100%; padding-block: 1rem; }

/* ---------- Header / nav (floating pill) ---------- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  pointer-events: none; /* children re-enable */
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hairline);
  transition: background .4s, border-color .4s, backdrop-filter .4s;
}
/* Over the hero the pill carries its own surface — no bar behind it. */
.site-header.at-top {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
.brand, .nav-menu, .nav-toggle {
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
/* No header animations on first paint — prevents the load flash */
body.preload .site-header,
body.preload .brand,
body.preload .nav-menu,
body.preload .nav-toggle { transition: none !important; }

/* Anchor jumps land below the fixed header */
section[id] { scroll-margin-top: 80px; }

.nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 72px;
  /* No gap: the hamburger's wrapper sits after the pill and is zero-width
     on desktop, so any gap would hold the pill off the container edge.
     Separation from the logo comes from .brand's padding instead. */
  gap: 0;
}

/* Logo hard left, pill hard right — both flush with the container edges,
   so the header lines up with every section below it. The auto margin does
   the pushing; neither element is a sized spacer. */
.brand {
  flex: 0 0 auto;
  margin-right: auto;
  padding-right: 1.5rem;
  display: inline-flex;
  align-items: center;
  pointer-events: auto;
}
.brand-logo { height: 30px; width: auto; transition: filter .3s; }
.nav-right { flex: 0 0 auto; display: flex; justify-content: flex-end; }

/* The floating pill */
.nav-menu {
  pointer-events: auto;
  flex: 0 1 auto;
  display: flex;
  align-items: center;
  gap: .1rem;
  background: var(--paper);
  border: 1px solid color-mix(in srgb, var(--hairline) 60%, transparent);
  border-radius: 999px;
  padding: .3rem;
  box-shadow: 0 10px 34px -12px rgba(20, 21, 23, .28);
}
.nav-menu > a {
  font-size: .8rem;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
  padding: .48rem .85rem;
  border-radius: 999px;
  transition: color .25s, background .3s var(--ease);
}
.nav-menu > a:hover { color: var(--ink); }
.nav-menu > a.active {
  background: var(--ink);
  color: var(--paper);
}
.nav-menu > a sup {
  font-family: var(--serif);
  font-style: italic;
  margin-right: .3em;
  color: var(--forest);
}
.nav-menu > a.active sup { color: var(--sage); }

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--muted);
  padding: 0 .8rem 0 .6rem;
  border-left: 1px solid var(--hairline);
  margin-left: .25rem;
}
.lang-switch a { transition: color .25s; }
.lang-switch a:hover { color: var(--ink); }
.lang-switch a.active { color: var(--ink); text-decoration: underline; text-underline-offset: 4px; }

.nav-toggle { display: none; pointer-events: auto; }

/* ---------- Hero (the design's own wash) ----------
   Earlier passes rebuilt this as fourteen CSS gradient columns. That got to
   about 0.6% mean error, but it could never be the artwork: flat columns
   cannot carry the mottling inside each one, and crisp edges had to be
   traded off against gradient banding. The design PDF embeds the wash as a
   4096px image, so that is what ships now — exact by construction, 25 KB as
   WebP because a smooth gradient compresses to almost nothing.
   Stretched to 100% 100% rather than cover: cover would crop about 170px
   off the sides at desktop and lose the full left-to-right span, which is
   the whole point of the composition. Nothing pans it, for the same reason.
   The colour drift is a second copy of the same image, hue-shifted and
   cross-faded by opacity alone — no repaint, and it passes through zero, so
   the resting look is the reference untouched. */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #e5f4d0;
  padding-top: 72px;

  /* --hero-shift : how far round the hue wheel the alternate wash pulls.
     --hero-tint  : how strongly it mixes in at the peak of the drift.
     --hero-amp / -scl / -glow : how far the bloom travels, swells and fades.
     --hero-speed : 1 runs the base durations below; .25 is four times faster. */
  --hero-shift: -14deg;
  --hero-tint: .6;
  --hero-wave: 4.5%;
  --hero-amp: 3%;
  --hero-scl: 1.12;
  --hero-glow: .84;
  --hero-speed: .25;
}

.hero-bg { position: absolute; inset: 0; }
.hero-lay { position: absolute; inset: 0; will-change: transform, opacity; }

.hero-wash { position: absolute; inset: 0; }

/* Each slice is a window onto the same image: the background is scaled to
   fourteen times the slice's own width, and background-position picks which
   fourteenth shows through. Sprite arithmetic — position i/13 lands slice i,
   because a percentage position aligns that fraction of the overflow, not of
   the image. Slices stand 10% proud top and bottom so the wave has somewhere
   to travel without opening a gap — that headroom has to grow whenever
   --hero-wave does, or the slices pull past their own edges. */
.hero-wash i {
  position: absolute;
  top: -10%;
  height: 120%;
  width: 7.142857%;                       /* 100/14 */
  left: calc(var(--i) * 7.142857%);
  background-image: url('../img/hero/hero-wash.jpg');
  background-image: image-set(url('../img/hero/hero-wash.webp') type('image/webp'),
                              url('../img/hero/hero-wash.jpg') type('image/jpeg'));
  background-size: 1400% 100%;
  background-position: calc(var(--i) * 100% / 13) center;
  background-repeat: no-repeat;
  will-change: transform;
  animation: heroWave calc(44s * var(--hero-speed)) ease-in-out infinite;
  /* Each column lags its neighbour, so the rise travels left to right. The
     lag scales with --hero-speed too, or changing speed would reshape the
     wave instead of just retiming it. Thirteen lags come to about half a
     period: a long swell rather than a ripple. */
  animation-delay: calc(var(--i) * -1.7s * var(--hero-speed));
}

/* The colour drift, now per slice so it rides along with the wave. Inherits
   the parent's whole background, so it is the same window, hue-shifted.
   Only opacity animates — the filter rasterises once. */
.hero-wash i::after {
  content: '';
  position: absolute;
  inset: 0;
  background: inherit;
  filter: hue-rotate(var(--hero-shift)) saturate(1.08);
  opacity: 0;
  will-change: opacity;
  animation: heroTint calc(30s * var(--hero-speed)) ease-in-out infinite;
  animation-delay: calc(var(--i) * -0.9s * var(--hero-speed));
}

/* Bloom of light over the wash, and the pointer-following highlight. */
.hero-bloom {
  background:
    radial-gradient(46% 46% at 10% 94%, rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, 0) 72%),
    radial-gradient(40% 32% at 44% 2%, rgba(255, 255, 246, .34) 0%, rgba(255, 255, 255, 0) 74%);
  filter: blur(26px);
}

.hero-spot {
  position: absolute;
  top: 0;
  left: 0;
  width: 54vmax;
  height: 54vmax;
  margin: -27vmax 0 0 -27vmax;
  background: radial-gradient(closest-side circle,
              rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, 0) 100%);
  filter: blur(22px);
  opacity: 0;
  pointer-events: none;
  transform: translate3d(var(--hero-sx, 50vw), var(--hero-sy, 50vh), 0);
  transition: transform .4s cubic-bezier(.22, .61, .21, 1), opacity .6s var(--ease);
  will-change: transform, opacity;
}
.hero.pointer-in .hero-spot { opacity: 1; }

/* Through zero at the trough, so the reference look is what sits at rest. */
@keyframes heroTint {
  0%, 100% { opacity: 0; }
  50%      { opacity: var(--hero-tint); }
}
/* The travel is a percentage of the slice, and a slice is 120% of the hero,
   so +/-4.5% here lands +/-5.4% of the hero — inside the 10% of slack above
   and below, with room to spare. */
@keyframes heroWave {
  0%, 100% { transform: translate3d(0, calc(-1 * var(--hero-wave)), 0); }
  50%      { transform: translate3d(0, var(--hero-wave), 0); }
}
@keyframes heroSwell {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(calc(-1.4 * var(--hero-amp)), calc(-1 * var(--hero-amp)), 0)
                        scale(var(--hero-scl)); }
}
@keyframes heroGlow {
  0%, 100% { opacity: var(--hero-glow); }
  50%      { opacity: 1; }
}

/* Out-of-phase durations, so the combined pattern takes minutes to repeat. */
.hero-bloom { animation: heroSwell calc(34s * var(--hero-speed)) ease-in-out infinite,
                         heroGlow  calc(22s * var(--hero-speed)) ease-in-out infinite; }


.hero-content {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Narrow measure, centred in the container, text ranged left. */
.hero-copy { width: 100%; max-width: 29em; }

.hero-kicker {
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: 1.1rem;
}

.hero-sub {
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  line-height: 1.55;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--ink);
}

.hero-link {
  display: inline-block;
  margin-top: 1.6rem;
  padding-bottom: .3rem;
  font-size: .95rem;
  font-weight: 500;
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
  transition: border-color .3s, transform .3s var(--ease);
}
.hero-link:hover { border-color: var(--forest); color: var(--forest); transform: translateX(4px); }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- About ---------- */
/* Stats lead the section, ruled off from the body copy underneath. */
.stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  padding-bottom: clamp(.9rem, 1.6vw, 1.25rem);
  border-bottom: 1px solid var(--hairline);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
  text-align: center;
}
.stat-num {
  display: block;
  font-family: var(--serif);
  font-size: clamp(2rem, 3.4vw, 2.9rem);
  line-height: 1;
  color: var(--forest);
}
.stat-label {
  display: block;
  margin-top: .5rem;
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}

.about-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 3.5vw, 3.5rem);
  font-size: .95rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

/* ---------- Areas (services tiles) ---------- */
.areas { background: var(--paper); }
.areas-title { margin-bottom: clamp(2.5rem, 5vw, 4rem); }

/* Staggered 3-column grid: cards step diagonally down the page */
.areas-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
.areas-grid .area-tile:nth-child(1) { grid-column: 2; grid-row: 1; }
.areas-grid .area-tile:nth-child(2) { grid-column: 3; grid-row: 1; }
.areas-grid .area-tile:nth-child(3) { grid-column: 1; grid-row: 2; }
.areas-grid .area-tile:nth-child(4) { grid-column: 2; grid-row: 2; }

.area-tile {
  aspect-ratio: 1 / 1.02;
  border-radius: var(--radius-lg);
  padding: clamp(1.4rem, 2.2vw, 2rem);
  display: flex;
  flex-direction: column;
  transition: transform .5s var(--ease);
}
.area-tile:hover { transform: translateY(-4px); }

/* Flat blocks in the two theme surfaces */
.areas-grid .area-tile:nth-child(1),
.areas-grid .area-tile:nth-child(4) { background: var(--paper-2); }
.areas-grid .area-tile:nth-child(2),
.areas-grid .area-tile:nth-child(3) { background: var(--sage); }

.area-glyph { width: clamp(58px, 5vw, 76px); }
.area-glyph svg { width: 100%; height: auto; }
.area-glyph path, .area-glyph circle {
  stroke: var(--ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}

.area-divider {
  position: relative;
  height: 1px;
  background: var(--ink);
  margin-top: auto;
  margin-bottom: clamp(1rem, 1.8vw, 1.4rem);
  opacity: .85;
}
.area-divider::before,
.area-divider::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 7px;
  height: 7px;
  background: var(--ink);
  transform: translateY(-50%) rotate(45deg);
}
.area-divider::before { left: 0; }
.area-divider::after { right: 0; }

.area-tile h3 {
  font-weight: 500;
  font-size: clamp(1.1rem, 1.5vw, 1.3rem);
  letter-spacing: -0.01em;
  margin-bottom: .45rem;
}
.area-tile p {
  font-size: .88rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* ---------- Team (editorial carousel cards) ---------- */
.team { background: var(--paper-2); overflow: hidden; }

.team-header { display: flex; align-items: flex-end; gap: 2rem; }

/* The firm is four people and stays four people, so every card is on
   screen at once — four up, folding to two and then one. */
.team-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
  margin-top: clamp(2rem, 4vw, 3rem);
  align-items: stretch;
}

.team-card {
  background: var(--paper);
  border-radius: var(--radius-md);
  padding: clamp(1.15rem, 1.6vw, 1.5rem);
  display: flex;
  flex-direction: column;
  text-align: left;
}

.team-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: clamp(1.2rem, 2.2vw, 1.8rem);
}
.team-photo {
  display: block;
  width: 76px;
  height: 84px;
  border-radius: 10px;
  overflow: hidden;
  flex: none;
}
.team-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(100%);
  transition: filter .6s var(--ease);
}
.team-card:hover .team-photo img { filter: grayscale(0%); }

.team-counter {
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--ink-soft);
  white-space: nowrap;
}
/* The dot picks up the accent green as the card is hovered — focus-within
   covers keyboard users reaching the card's email link. */
.team-dot { transition: color .3s var(--ease); }
.team-card:hover .team-dot,
.team-card:focus-within .team-dot { color: var(--forest-bright); }

.team-name {
  font-family: var(--sans);
  font-weight: 500;
  font-size: clamp(1.3rem, 1.9vw, 1.62rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin-bottom: clamp(.9rem, 1.5vw, 1.2rem);
}

/* One grid for the whole list, with the rows dissolved into it, so every
   label and value lines up. The column is 100px because the labels have
   to clear "LICENCIATURA" — a single word that cannot wrap and so ran
   into the value beside it at the old 76px. Letting the column size
   itself instead would fix that too, but English's longer "MASTER'S
   DEGREE" would then widen it past the other cards; a set width keeps
   all four aligned, as in the design. */
.team-specs {
  border-top: 1px solid var(--hairline);
  padding-top: 1.1rem;
  display: grid;
  grid-template-columns: 100px minmax(0, 1fr);
  column-gap: .65rem;
  row-gap: .75rem;
  align-items: baseline;
  align-content: start;
  flex: 1;
}
.team-specs > div { display: contents; }
.team-specs dt {
  font-size: .65rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  /* Safety net only: should a label ever outgrow the column, it breaks
     rather than running into the value. Nothing hits this today. */
  overflow-wrap: anywhere;
}
.team-specs dd { font-size: .86rem; line-height: 1.45; }

.team-links {
  border-top: 1px solid var(--hairline);
  margin-top: 1.2rem;
  padding-top: 1rem;
  display: flex;
  gap: 1.6rem;
}
.team-links .mail {
  font-size: .78rem;
  font-weight: 500;
  word-break: break-all;
}

/* Column count is handled in the responsive ladder at the foot of the file,
   so all four breakpoints stay readable in one place. */

/* ---------- Office (arrow-driven gallery) ---------- */
.office-head { display: grid; grid-template-columns: 1.2fr .8fr; gap: 2rem; align-items: end; }
.office-sub { color: var(--ink-soft); max-width: 30em; }

.gallery-nav {
  display: flex;
  gap: .6rem;
  justify-content: flex-end;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.gallery-arrow {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid var(--ink);
  display: grid;
  place-items: center;
  font-size: 1.05rem;
  transition: background .3s, color .3s;
}
.gallery-arrow:hover { background: var(--ink); color: var(--paper); }
.gallery-arrow:focus-visible { outline: 2px solid var(--forest); outline-offset: 3px; }

/* A plain horizontal scroller — the page's vertical scroll is left alone. */
.office-track {
  display: flex;
  gap: clamp(1rem, 2.4vw, 2.4rem);
  padding-inline: max(1.5rem, (100vw - var(--container)) / 2);
  /* Snap to the container edge, not the viewport edge, so a stepped-to
     photo lines up with the heading above it. */
  scroll-padding-inline: max(1.5rem, (100vw - var(--container)) / 2);
  overflow-x: auto;
  /* main.js animates scrollLeft frame by frame, so the smooth inherited
     from html would fight it. */
  scroll-behavior: auto;
  /* Proximity, not mandatory: mandatory snapping re-targets a programmatic
     scroll that lands between two snap points, which made the arrows
     overshoot past photos. main.js suspends this entirely while it glides. */
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.office-track::-webkit-scrollbar { display: none; }
.office-track:focus-visible { outline: 2px solid var(--forest); outline-offset: 4px; }

.office-frame {
  flex: none;
  height: min(64vh, 580px);
  overflow: hidden;
  scroll-snap-align: start;
}
/* Rhythm of frame formats, like the reference */
.office-frame:nth-child(3n + 1) { aspect-ratio: 3 / 2; }
.office-frame:nth-child(3n + 2) { aspect-ratio: 4 / 5; }
.office-frame:nth-child(3n)     { aspect-ratio: 1 / 1; }

/* Wider than its frame on purpose: the overhang is the slack main.js
   slides the photo through as the strip moves, so the crop travels
   faster than the frame does. */
.office-frame img {
  width: 128%;
  max-width: none;
  height: 100%;
  object-fit: cover;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .office-frame img { width: 100%; transform: none !important; }
}

/* Frame height moves with the ladder below. */

/* ---------- Contacts ---------- */
.contacts { background: var(--paper); }
.contacts-grid {
  display: grid;
  grid-template-columns: .8fr 1.2fr;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}
.contacts-sub { margin-top: 1rem; color: var(--ink-soft); }

.contact-list { margin-top: 2.2rem; display: grid; gap: 1.5rem; }
.contact-list dt {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}
.contact-list dd { margin-top: .3rem; font-size: .95rem; line-height: 1.55; }

.contacts-map {
  aspect-ratio: 1.7 / 1;
  overflow: hidden;
  background: var(--paper-2);
}
/* Holds either the styled #map canvas or the fallback iframe. */
.contacts-map > * { width: 100%; height: 100%; border: 0; display: block; }

/* Fallback embed only, when no API key is set. Tuned so the landscape
   fill lands on #faf8f4 — the section's own --paper #faf9f6, within
   2/255 — with everything else stepping down in neutral greys. The trace
   of sepia is what keeps the greys warm rather than clinical. */
.contacts-map iframe {
  filter: grayscale(1) brightness(.86) sepia(.06) contrast(1.14) brightness(1.1);
}

/* ---------- Email addresses (assembled by main.js) ---------- */
/* Until the script runs the two halves render as "user [at] domain", so
   the harvestable "user@domain" string never exists in the source. */
.mail { word-break: break-word; }
.mail-u::after { content: ' [at] '; }
a.mail { text-decoration: underline; text-underline-offset: 3px; transition: color .25s; }
a.mail:hover { color: var(--forest); }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--sage);
  color: var(--ink);
  padding: clamp(2.5rem, 5vw, 4rem) 0;
}
.footer-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  align-items: flex-end;
  justify-content: space-between;
}
.footer-tagline { font-size: .85rem; color: var(--ink-soft); }
.footer-copy { font-size: .8rem; color: var(--ink-soft); }

/* ---------- Reveal animations ---------- */
.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  /* The wash stays exactly as designed; it just stops moving and drifting. */
  .hero-lay, .hero-wash i, .hero-wash i::after { animation: none !important; }
  .hero-wash i { transform: none !important; }
}

/* ---------- Responsive ----------
   Four breakpoints, each with one reason to exist:

     1180  the nav pill runs out of room, and four team cards get too narrow
     1000  two-column layouts stop earning their keep and stack
      760  the hero wash switches from full-span to a crop, so the fourteen
            columns do not compress into slivers; gallery frames shorten
      560  phone: everything to a single column

   They are in descending order so the cascade reads top to bottom, and the
   narrower ones win where they overlap. */

/* --- 1180: nav collapses, team halves --- */
@media (max-width: 1180px) {
  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    gap: 6px;
    padding: .6rem;
  }
  .nav-toggle span {
    width: 24px;
    height: 2px;
    background: var(--ink);
    transition: transform .35s var(--ease), opacity .35s;
  }
  .nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(4px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

  .nav-menu {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.2rem;
    background: var(--paper);
    border: 0;
    border-bottom: 1px solid var(--hairline);
    border-radius: 0;
    box-shadow: none;
    padding: calc(76px + 1rem) 1.5rem 2rem;
    transform: translateY(-12px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .35s var(--ease), transform .35s var(--ease);
  }
  .nav-menu.open { opacity: 1; transform: none; pointer-events: auto; }
  .nav-menu > a { font-size: 1.05rem; padding: 0; border-radius: 0; }
  .nav-menu > a.active { background: none; color: var(--forest); }
  .lang-switch { border-left: 0; margin-left: 0; padding: 0; }

  /* Four across would leave ~220px a card, too little beside a 100px
     label column. Two is roomier than the design but reads better. */
  .team-grid { grid-template-columns: repeat(2, 1fr); }
}

/* --- 1000: two-column layouts stack --- */
@media (max-width: 1000px) {
  .hero-content { justify-content: flex-start; }
  .hero-copy { max-width: none; }

  .about-cols { grid-template-columns: 1fr; gap: 1.2rem; }

  /* Unwind the diagonal stagger into a plain 2-up. */
  .areas-grid { grid-template-columns: repeat(2, 1fr); }
  .areas-grid .area-tile:nth-child(1),
  .areas-grid .area-tile:nth-child(2),
  .areas-grid .area-tile:nth-child(3),
  .areas-grid .area-tile:nth-child(4) { grid-column: auto; grid-row: auto; }

  .office-head { grid-template-columns: 1fr; align-items: start; }
  .contacts-grid { grid-template-columns: 1fr; }
}

/* --- 760: crop the hero rather than squeeze it --- */
@media (max-width: 760px) {
  /* All fourteen across a phone would leave each about 25px wide, reading as
     stripes rather than a wash. Because the wash is sliced, the fix is to
     show fewer slices at full width rather than to crop the image: columns
     8-11 at a quarter each. That stretch carries the most interest — the
     cream-to-green transition and the deep pool — and each column keeps its
     own gradient and its own place in the wave. */
  .hero-wash i { display: none; }
  .hero-wash i:nth-child(n + 8):nth-child(-n + 11) {
    display: block;
    width: 25%;
    left: calc((var(--i) - 7) * 25%);
  }

  .office-frame { height: min(48vh, 420px); }
}

/* --- 560: single column --- */
@media (max-width: 560px) {
  .areas-grid { grid-template-columns: 1fr; }
  .area-tile { aspect-ratio: auto; min-height: 260px; }
  /* Stacked, the desktop cream-sage-sage-cream order would put the two sage
     tiles back to back; the stagger is what separates them. Alternate. */
  .areas-grid .area-tile:nth-child(odd)  { background: var(--paper-2); }
  .areas-grid .area-tile:nth-child(even) { background: var(--sage); }

  .team-grid { grid-template-columns: 1fr; }
  .stats { grid-template-columns: 1fr; gap: 2rem; }
}
