/* ══════════════════════════════════════════════════════════════════════════
   COMPONENTS — accordion, pixel reveal, blog, FAQ, detail pages
   ══════════════════════════════════════════════════════════════════════════ */

/* ── IMAGE ACCORDION ──────────────────────────────────────────────────────
   Adapted from Bencho's image accordion (MIT, bencho.dev/licence).

   Kept, because they are the ideas worth copying:
   · The row is a FIXED width. Nothing grows — every pixel the open panel
     gains, the others have paid for between them. That is what makes it read
     as one object with parts rather than three cards in a line, and it is why
     this is flex-grow rather than widths worked out by hand.
   · The swell CARRIES into the neighbours on a gaussian falloff, so it reads
     as a force arriving somewhere rather than a switch being thrown.
   · Pointing is stable because the panel you point at is the one that GROWS:
     its edges move away from the cursor, never across it, so it cannot shrink
     out from under you and hand the hover to a neighbour.

   Changed, deliberately: Bencho drives this with a spring tuned to overshoot.
   This site's motion law is two curves and no bounce — a rebound here would
   be the only thing on the page that rings. Same arithmetic, this site's ease.
   ─────────────────────────────────────────────────────────────────────────── */
.acc{display:flex;flex-direction:row;align-items:stretch;gap:2px;overflow:hidden;
  height:clamp(400px,50vw,560px);user-select:none;touch-action:pan-y;background:var(--line)}

/* ── THE PANEL IS A SIBLING, NEVER AN OVERLAY ─────────────────────────────
   The portrait and the panel sit side by side and share the cell's width.
   Nothing is ever laid over a face. That costs a second animated layout
   property (the panel's flex-basis alongside the cell's flex-grow) and there
   is no way around it: a panel that occupies its own space has to be given
   that space, and space is layout.

   So the smoothness is bought elsewhere — `contain` stops each cell's
   relayout escaping into the row, `will-change` is applied only while the
   pointer is actually in the row, and the padding no longer animates (it is
   fixed and clipped, which was the third layout property and the cheapest
   one to lose). ─────────────────────────────────────────────────────────── */
.acc__cell{position:relative;flex-basis:0;flex-shrink:1;min-width:0;overflow:hidden;
  flex-grow:1;display:flex;background:var(--oc-navy-900);
  contain:layout paint;
  transition:flex-grow .7s var(--ease-authority)}

.acc__media{position:relative;flex:1 1 auto;min-width:0;overflow:hidden}
.acc__media img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 14%;
  -webkit-user-drag:none;filter:grayscale(1) contrast(1.04) brightness(.8);
  transition:filter .7s var(--ease-authority)}
.acc__cell[data-open] .acc__media img{filter:grayscale(1) contrast(1.02) brightness(1)}
.acc__media::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:var(--oc-navy-700);mix-blend-mode:color;opacity:.9}
.acc__media::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(180deg,rgba(10,16,24,.12),rgba(10,16,24,.78));
  transition:opacity .6s var(--ease-authority)}
.acc__cell[data-open] .acc__media::after{opacity:.5}

.acc__spine{position:absolute;left:0;right:0;bottom:0;z-index:3;padding:22px 20px;
  display:grid;gap:5px;transition:opacity .3s var(--ease-authority)}
.acc__spine b{font-family:var(--serif);font-size:clamp(1rem,1.4vw,1.25rem);font-weight:600;
  color:#fff;line-height:1.15;display:block}
.acc__spine span{font-size:.75rem;color:rgba(255,255,255,.7)}
.acc__cell[data-open] .acc__spine{opacity:0}

/* ── A CLOSED PANEL MUST BE ZERO WIDE ─────────────────────────────────────
   flex-basis:0 does not make an element zero wide if it still carries
   padding: the padding is added to the basis, so a closed panel rendered as a
   68px navy bar between every portrait. The padding moved to a fixed-width
   inner, which also removes the last reflow from the animation — the text is
   laid out at its final width from the start and the open is pure geometry. */
.acc{--acc-panel-w:clamp(255px,29vw,400px)}
.acc__panel{flex:0 0 0%;min-width:0;overflow:hidden;padding:0;background:var(--oc-navy-800);
  transition:flex-basis .7s var(--ease-authority)}
.acc__cell[data-open] .acc__panel{flex-basis:var(--acc-panel-w)}
.acc__panel__in{width:var(--acc-panel-w);height:100%;box-sizing:border-box;
  padding:clamp(22px,3vw,34px);display:grid;align-content:center;gap:15px}
.acc__panel__in > *{opacity:0;transform:translateY(7px);
  transition:opacity .4s var(--ease-authority),transform .48s var(--ease-authority)}
.acc__cell[data-open] .acc__panel__in > *{opacity:1;transform:none;transition-delay:.22s}
.acc__cell[data-open] .acc__panel__in > *:nth-child(2){transition-delay:.29s}
.acc__cell[data-open] .acc__panel__in > *:nth-child(3){transition-delay:.36s}
.acc__panel h3{font-family:var(--serif);font-size:clamp(1.1rem,1.5vw,1.4rem);font-weight:600;
  color:#fff;line-height:1.18;text-wrap:balance}
.acc__panel ul{margin:0;padding:0;list-style:none;display:grid;gap:10px}
.acc__panel li{font-size:.8125rem;line-height:1.45;color:rgba(255,255,255,.86);
  padding-left:15px;position:relative}
.acc__panel li::before{content:"";position:absolute;left:0;top:.62em;width:7px;height:1px;
  background:var(--oc-blue-300)}
/* The phone card carries a different payload from the desktop panel: the
   credentials belong on the profile page, and what a card has to do here is
   identify the person and offer the two things a reader actually wants next.
   Both sets are emitted; the breakpoint decides which is live. */
.acc__short,.acc__acts{display:none}
.acc__more{display:inline-flex;align-items:center;gap:9px;font-size:.75rem;font-weight:600;
  color:#fff;padding-bottom:5px;border-bottom:1px solid rgba(255,255,255,.45);justify-self:start;
  white-space:nowrap;transition:border-color .3s var(--ease-authority),gap .3s var(--ease-authority)}
.acc__more:hover{border-color:#fff;gap:13px}
.acc__more svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2}

@media(max-width:940px){
  .acc{flex-direction:column;height:auto;gap:1px}
  /* flex-basis:0 in a column container is a HEIGHT basis: with the row's
     height:auto there was nothing to grow into, so every cell measured 0 and
     clipped its portrait away. Content sets the height here. */
  .acc__cell{flex:0 0 auto!important;flex-direction:column;min-height:0;contain:none}
  .acc__media{flex:0 0 auto;height:clamp(300px,82vw,392px)}
  /* The tile is the closed state, carrying the name and the role the way the
     desktop cell does before it is opened. Nothing is expanded on arrival:
     three portraits read as a roster, three opened dossiers read as a wall. */
  .acc__cell{cursor:pointer}
  .acc__spine{display:grid;padding:20px 22px;opacity:1!important}
  .acc__spine b{display:block;font-size:1.15rem;line-height:1.2}
  .acc__spine span{font-size:.6875rem;letter-spacing:.2em;text-transform:uppercase;
    color:rgba(255,255,255,.78)}
  /* 0fr → 1fr animates to whatever the content measures, so a partner with a
     long credential list is never clipped by a max-height guessed here. The
     vertical padding has to travel with it: a grid item stretched to a 0px
     row still adds its own padding, which would leave a navy stripe under
     every closed tile — the stripes the accordion was asked to lose. */
  .acc__panel{flex:0 0 auto!important;display:grid;grid-template-rows:0fr;
    transition:grid-template-rows .52s var(--ease-authority)}
  .acc__cell[data-open] .acc__panel{grid-template-rows:1fr}
  .acc__panel__in{width:100%;min-height:0;overflow:hidden;display:grid;gap:0;
    padding:0 22px;transition:padding .52s var(--ease-authority)}
  .acc__cell[data-open] .acc__panel__in{padding:22px 22px 26px}
  .acc__panel__in > *{opacity:1!important;transform:none!important;transition-delay:0s!important}
  /* Scoped to the panel: the practice-area cards reuse .acc__more for their
     own link, and hiding it unscoped left every area card on a phone with no
     link in it at all — the card looked fine and did nothing when tapped. */
  .acc__panel h3,.acc__panel .acc__more{display:none}
  .acc__short{display:block;order:1;margin:0 0 16px;font-size:.9375rem;line-height:1.55;
    color:rgba(255,255,255,.72)}
  .acc__panel ul{display:grid;order:2}
  .acc__acts{display:flex;order:3;gap:9px;margin-top:20px;flex-wrap:wrap}
  .acc__acts .btn{flex:1 1 auto;min-width:0}
  .acc__act2{border:1px solid rgba(255,255,255,.34);color:#fff}
  .acc__act2:hover{border-color:#fff;background:rgba(255,255,255,.08)}
  /* The chevron is the only thing that says these open. */
  .acc__spine::after{content:"";position:absolute;right:22px;bottom:26px;width:11px;height:11px;
    border-right:1.6px solid rgba(255,255,255,.75);border-bottom:1.6px solid rgba(255,255,255,.75);
    transform:rotate(45deg);transition:transform .4s var(--ease-authority)}
  .acc__cell[data-open] .acc__spine::after{transform:rotate(225deg)}
}
@media (prefers-reduced-motion:reduce){
  .acc__cell,.acc__panel,.acc__media img{transition:none}
}

/* ── PIXEL IMAGE ──────────────────────────────────────────────────────────
   After magicui's PixelImage: the picture arrives as a grid of cells in
   shuffled order rather than as one fade, and de-saturates as it lands.
   Built on background-position so it is one decoded image, not rows×cols
   of them. ─────────────────────────────────────────────────────────────── */
.px{position:relative;overflow:hidden;background:transparent;
  display:grid;grid-template-columns:repeat(var(--px-cols,6),1fr);
  grid-template-rows:repeat(var(--px-rows,4),1fr)}
.px__c{background-image:var(--px-src);background-size:calc(var(--px-cols,6)*100%) calc(var(--px-rows,4)*100%);
  opacity:0;transform:scale(1.06);filter:grayscale(1);
  transition:opacity .5s var(--ease-authority),transform .7s var(--ease-authority),
             filter .9s var(--ease-authority)}
.px.in .px__c{opacity:1;transform:none}
.px:hover .px__c,.post:hover .px__c{filter:grayscale(0) contrast(1.02)}

/* Without JS the cells never get their delays or their .in class, so the
   image would never appear. Show it whole instead. */
html:not(.js) .px__c{opacity:1;transform:none}

/* ── BLOG ─────────────────────────────────────────────────────────────────*/
/* ── POST CARD ────────────────────────────────────────────────────────────
   Every card is the same width and the same shape: a fixed image ratio on
   top, then the body. The body is the row that stretches, so the draft badge
   sits on the same line across the whole rail however long a title runs —
   which is the difference between a row of cards and a ragged shelf. ─────── */
.post{background:var(--bg);display:grid;grid-template-rows:auto 1fr;
  border:1px solid var(--line);
  transition:border-color .3s var(--ease-authority),transform .45s var(--ease-authority)}
.post:hover{border-color:var(--line-strong);transform:translateY(-3px)}
.post .px{aspect-ratio:3/2;width:100%}
.post__b{padding:24px clamp(18px,2vw,28px) 30px;display:grid;gap:10px}
.post__k{font-size:.6875rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--accent-fg)}
.post__t{font-family:var(--serif);font-size:1.1875rem;font-weight:600;line-height:1.28;
  letter-spacing:-.015em;color:var(--fg-strong);text-wrap:pretty}
.post__d{font-size:.8125rem;color:var(--fg-subtle);align-self:end;padding-top:6px}
.draft{display:inline-block;font-size:.6875rem;font-weight:600;letter-spacing:.06em;
  padding:3px 8px;border:1px solid var(--line-strong);color:var(--fg-muted)}

/* ── FAQ ──────────────────────────────────────────────────────────────────*/
/* Heading on the left, questions on the right — the same two-column
   arrangement the figures use, so the page keeps one reading habit. The
   heading is sticky: at six questions the reader loses it otherwise. */
.faqgrid{display:grid;gap:clamp(32px,5vw,64px)}
@media(min-width:960px){.faqgrid{grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  gap:clamp(40px,6vw,96px);align-items:start}
  .faqgrid__head{position:sticky;top:130px}}
.faqgrid__head{display:grid;gap:18px;align-content:start}
.faqgrid__head .more{margin-top:6px}
.faq{border-top:1px solid var(--line);min-width:0}
.faq__i{border-bottom:1px solid var(--line)}
.faq__q{width:100%;display:flex;align-items:flex-start;gap:20px;text-align:left;
  padding:24px 0;font-family:var(--serif);font-size:clamp(1.05rem,1.6vw,1.3rem);font-weight:500;
  letter-spacing:-.015em;color:var(--fg-strong);line-height:1.3;
  transition:color .25s var(--ease-authority)}
.faq__q:hover{color:var(--accent-fg)}
.faq__q i{margin-left:auto;flex:none;width:15px;height:15px;position:relative;margin-top:.35em}
.faq__q i::before,.faq__q i::after{content:"";position:absolute;inset:50% 0 auto 0;height:1.5px;
  background:currentColor;transition:transform .42s var(--ease-authority)}
.faq__q i::after{transform:rotate(90deg)}
.faq__i[data-open] .faq__q i::after{transform:rotate(0)}
.faq__a{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .45s var(--ease-authority)}
.faq__i[data-open] .faq__a{grid-template-rows:1fr}
.faq__a>div{overflow:hidden}
.faq__a p{padding-bottom:26px;max-width:66ch;color:var(--fg-muted);font-size:.9375rem;line-height:1.7}

/* ── DETAIL PAGES ─────────────────────────────────────────────────────────*/
.crumb{display:flex;align-items:center;gap:10px;font-size:.8125rem;color:var(--fg-subtle);
  padding-top:clamp(100px,12vh,150px)}
.crumb a:hover{color:var(--accent-fg)}
.crumb svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2}
.dhero{display:grid;gap:26px;padding-block:clamp(28px,4vw,52px) clamp(40px,6vw,72px);
  border-bottom:1px solid var(--line)}
.dhero h1{max-width:18ch}
.dhero p{max-width:60ch}
.dbody{display:grid;gap:clamp(36px,5vw,64px);padding-block:clamp(48px,7vw,88px)}
@media(min-width:960px){.dbody{grid-template-columns:minmax(0,1fr) minmax(0,26rem);
  gap:clamp(40px,6vw,96px);align-items:start}}
.dblock + .dblock{margin-top:clamp(36px,5vw,56px)}
.dblock h2{font-family:var(--serif);font-size:clamp(1.3rem,2vw,1.7rem);font-weight:600;
  letter-spacing:-.02em;padding-bottom:14px;border-bottom:1px solid var(--line)}
.dlist{margin:22px 0 0;padding:0;list-style:none;display:grid;gap:0}
.dlist li{padding:15px 0 15px 30px;border-bottom:1px solid var(--line-soft);position:relative;
  font-size:1rem;line-height:1.6}
.dlist li::before{content:"";position:absolute;left:0;top:1.5em;width:14px;height:1px;
  background:var(--accent)}
.dlist--num{counter-reset:step}
.dlist--num li{counter-increment:step;padding-left:46px}
.dlist--num li::before{content:counter(step,decimal-leading-zero);width:auto;height:auto;top:15px;
  background:none;font-family:var(--sans);font-size:.75rem;font-weight:600;color:var(--accent-fg);
  letter-spacing:.04em}
.aside{position:sticky;top:120px;display:grid;gap:22px;padding:clamp(24px,3vw,32px);
  border:1px solid var(--line);background:var(--bg-sunken)}
.aside h3{font-family:var(--sans);font-size:.75rem;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--fg-subtle)}
.aside ul{margin:0;padding:0;list-style:none;display:grid;gap:11px;font-size:.9375rem}
.aside a:not(.btn){color:var(--fg);transition:color .22s var(--ease-authority)}
.aside a:not(.btn):hover{color:var(--accent-fg)}
.aside a[aria-current]{color:var(--accent-fg);font-weight:600}

.pcard{display:grid;gap:20px}
.pcard .px{aspect-ratio:1/1}
.pgrid{display:grid;gap:1px;background:var(--line);border:1px solid var(--line)}
@media(min-width:760px){.pgrid{grid-template-columns:repeat(3,1fr)}}
.pgrid > *{background:var(--bg);padding:clamp(20px,2.4vw,28px)}

.more{display:inline-flex;align-items:center;gap:10px;font-family:var(--sans);font-size:.75rem;
  font-weight:600;letter-spacing:.04em;color:var(--accent-fg);padding-bottom:5px;
  border-bottom:1px solid currentColor;justify-self:start;
  transition:gap .3s var(--ease-authority)}
.more:hover{gap:14px}
.more svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2}

@media (prefers-reduced-motion:reduce){
  .acc__cell{transition:none}
  .px__c{opacity:1!important;transform:none!important}
  .acc__panel{opacity:1!important;transform:none!important}
}

/* ── ÁREA HERO — the photograph carries the title, not the body copy ──────── */
.ahero{position:relative;overflow:hidden;background:var(--oc-navy-950);isolation:isolate;
  min-height:clamp(420px,52vh,620px);display:grid;align-content:end}
.ahero img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;
  filter:grayscale(1) contrast(1.04) brightness(.72)}
.ahero::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:var(--oc-navy-700);mix-blend-mode:color;opacity:.92}
.ahero__scrim{position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(180deg,rgba(10,16,24,.62) 0%,rgba(10,16,24,.28) 34%,rgba(10,16,24,.9) 100%)}
.ahero__in{position:relative;z-index:3;padding-block:clamp(120px,15vh,170px) clamp(38px,6vh,66px);
  display:grid;gap:20px}
.ahero__in h1{color:#fff;max-width:16ch}
.ahero__in p{color:rgba(255,255,255,.88);max-width:54ch}
.crumb--on-img{padding-top:0;color:rgba(255,255,255,.72)}
.crumb--on-img a{color:rgba(255,255,255,.72)}
.crumb--on-img a:hover{color:#fff}
.crumb--on-img span{color:#fff}

.dtext{margin-top:20px;font-size:1.0625rem;line-height:1.72;color:var(--fg-muted);max-width:62ch}
.dbody{padding-block:clamp(48px,7vw,88px)}

/* ── PROSE — blog posts and legal documents ──────────────────────────────── */
.prose{min-width:0}
.prose .dtext{margin-top:0;margin-bottom:1.4em}
.prose .dtext:last-child{margin-bottom:0}
.prose .dblock + .dblock{margin-top:clamp(32px,4vw,48px)}
.prose .dblock h2{margin-bottom:20px}
.prose .dblock .dtext{margin-top:0}
.ahero--post .ahero__in h1{max-width:22ch}

/* ── A PICTURE THAT BELONGS TO ITS BAND ───────────────────────────────────
   A rectangle of grey photograph dropped on a navy field reads as a hole in
   the page. Three things fix it, and all three are needed: the navy duotone
   so it is the same hue as the band, a soft mask so it has no hard edge to
   argue with, and enough size that it is a surface rather than a stamp. ──── */
.px--blend{--px-fade:18%}
.px--blend .px__c{filter:grayscale(1) contrast(1.06) brightness(.88)
  sepia(.32) hue-rotate(178deg) saturate(2.2)}
.px--blend{
  -webkit-mask-image:linear-gradient(90deg,transparent 0%,#000 34%);
  mask-image:linear-gradient(90deg,transparent 0%,#000 34%)}
.px--blend::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,var(--plate) 0%,rgba(34,63,101,.18) 46%,rgba(34,63,101,.05) 100%)}
@media(max-width:940px){
  /* Stacked, the picture sits above the copy — so it is the BOTTOM edge that
     has to dissolve into the band, not the top. */
  .px--blend{-webkit-mask-image:linear-gradient(180deg,#000 0%,#000 55%,transparent 100%);
    mask-image:linear-gradient(180deg,#000 0%,#000 55%,transparent 100%)}
  .px--blend::after{background:linear-gradient(180deg,rgba(34,63,101,.05) 0%,
    rgba(34,63,101,.25) 62%,var(--plate) 100%)}
}
/* ── CONTACT: A FULL-HEIGHT SPLIT ─────────────────────────────────────────
   The picture is the section's right half, edge to edge, top to bottom —
   not a framed rectangle floating on the band with a rule beside it. It has
   no border and no seam; the mask does the joining, fading the left edge into
   the navy so there is nothing for the eye to catch on. ──────────────────── */
.contact{position:relative;overflow:hidden}
.contact__fig{position:absolute;inset:0 0 0 auto;width:min(52%,860px);z-index:0}
.contact__fig .px{position:absolute;inset:0}
.contact__txt{position:relative;z-index:1;max-width:min(46%,54ch)}
@media(max-width:940px){
  /* The figure is the first thing in the stack, so the section's own top
     padding would show as a navy band above the photo. Drop it and let the
     image meet the section edge; the text below carries the padding instead. */
  .contact{display:flex;flex-direction:column;padding-block-start:0}
  .contact__fig{position:relative;inset:auto;width:auto;height:min(46vw,340px);
    order:-1;margin:0 calc(var(--rail) * -1) clamp(30px,7vw,44px)}
  .contact__txt{max-width:none}
}

/* ── HORIZONTAL RAIL ──────────────────────────────────────────────────────
   Native overflow scrolling with snap points, not a JS carousel. It gets
   touch, trackpad, shift-wheel, keyboard and screen-reader behaviour for
   free, it cannot desync from its own state, and if the script fails the
   posts are still a scrollable row rather than a dead widget. The buttons
   only call scrollBy — they are a convenience over the scroller, never the
   thing that moves it. ──────────────────────────────────────────────────── */
.rail{position:relative}
.rail__track{min-width:0;max-width:100%;display:grid;grid-auto-flow:column;grid-auto-columns:clamp(280px,25vw,350px);
  gap:18px;align-items:stretch;overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;scroll-padding-inline:0;
  padding-bottom:2px;scrollbar-width:none}
.rail__track::-webkit-scrollbar{display:none}
.rail__track > *{scroll-snap-align:start}
/* The row bleeds to both edges so it reads as continuing past the page. */
@media(min-width:1100px){
  .rail{margin-inline:calc(var(--rail) * -1)}
  .rail__track{padding-inline:var(--rail)}
  .rail__nav{padding-inline:var(--rail)}
}
.rail__nav{display:flex;gap:8px;justify-content:flex-end;margin-top:20px}
.rail__btn{display:grid;place-items:center;width:44px;height:44px;border:1px solid var(--line);
  color:var(--fg);transition:border-color .22s var(--ease-authority),
  color .22s var(--ease-authority),opacity .22s var(--ease-authority)}
.rail__btn:hover:not(:disabled){border-color:var(--accent);color:var(--accent-fg)}
.rail__btn:disabled{opacity:.3;cursor:default}
.rail__btn svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.post__l{font-size:.8438rem;line-height:1.55;color:var(--fg-muted);margin-top:2px}
/* 1fr on the badge row pushes it to the floor of every card. */
.post__b{padding:22px clamp(18px,2vw,26px) 24px;display:grid;gap:9px;
  grid-template-rows:auto auto 1fr auto;align-content:stretch}
