/* ============================================================
   ACCESSIBILITY PANEL  —  assets/css/a11y.css

   Two things live in here:

   1. The floating button and the panel it opens (built by assets/js/a11y.js).
   2. The rules the saved preferences switch on, keyed off classes that the
      boot script in index.html's <head> writes onto <html> BEFORE first
      paint. That ordering matters: a visitor who has asked for larger text
      should never watch the page reflow into it after load.

   Preference classes, all set on <html>:
      .pref-text-1 / .pref-text-2   type scale
      .pref-contrast                raised contrast
      .pref-links                   underline every link
      .pref-readable                one typeface, no display serif
      .pref-reduce                  motion off  (rules in index.html)
   Tier classes .perf-full / .perf-lite / .perf-still are set by the same
   script; the rules that respond to those sit next to the CSS they modify.

   The panel deliberately does NOT ship a "dark mode" toggle. The site has
   one palette, built and contrast-checked against it; a generated inversion
   would undo that rather than help.
   ============================================================ */

/* ---------- type scale ----------
   Everything on the page is sized in rem or clamp(), so moving the root size
   carries the whole layout with it — including the clamp() ceilings, which
   is why this is a root font-size change rather than a transform or a zoom.
   The two steps are ~112% and ~125%; past that the fixed-height hero panels
   start to lose copy off the bottom. */
.pref-text-1{font-size:112.5%}
.pref-text-2{font-size:125%}

/* The hero plates are absolutely positioned inside a viewport-height stage,
   so enlarged type has nowhere to go and can overrun the bottom edge. Let
   them scroll internally at the largest step rather than clip. */
.pref-text-2 .plate{max-height:72vh;overflow-y:auto;overscroll-behavior:contain}

/* ---------- raised contrast ----------
   NOTE the html. prefix on the two blocks that redefine custom properties.
   :root and .pref-contrast are both specificity (0,1,0), and index.html's
   inline <style> — where :root is declared — comes after this file in the
   head, so a bare .pref-contrast{--dust:...} loses the tie on source order
   and silently does nothing. html.pref-contrast is (0,1,1) and wins. This
   was caught by the headings staying serif with "plainer type" switched on.
   The palette already passes AA everywhere it is used — this is for people
   who need more than the minimum, so it lifts the muted greys to full
   strength and firms up the hairline borders rather than repainting the
   site. */
html.pref-contrast{
  --dust:#EFE7D6;
  --focus:#FFD79A;
}
.pref-contrast body{color:#FFFDF8}
.pref-contrast :where(.lede,.walk__lede,.svc__intro,.traps__intro,.contact__intro,
  .gal .work__intro,.after p,.feat__blurb,.walk__point p){color:rgba(255,253,248,.95)}
.pref-contrast :where(.feat__label,.feat__cap,.feat__src__out,.feat__src__note,
  .cue,.trap__meta,.traps__note,.formnote,.field span,.where__meta,.foot,
  .walk__facts h3,.walk__facts dd,.gal__tab,.proj__meta,.trap__latin){
  color:rgba(255,253,248,.92)}
.pref-contrast .work :where(.eyebrow,.work__intro,.proj__body p,.proj__meta,
  .proj__long p,.proj__long li,.proj__status--done){color:#171C11}
.pref-contrast .svc__card li{color:#171C11}
.pref-contrast :where(.feat__item,.walk__facts,.svc__cta,.trap__frame,.gal__item,
  .where__map){border-color:rgba(242,237,227,.55)}
.pref-contrast .field input,
.pref-contrast .field select,
.pref-contrast .field textarea{border-color:rgba(242,237,227,.8)}
.pref-contrast .proj__item{border-bottom-color:rgba(27,33,21,.5)}
.pref-contrast .mast.is-solid{background:#000}
/* the hero gradients are what keep the plates legible over the photographs —
   deepen them rather than trusting the underlying frame */
.pref-contrast .layer--tiger::after{background:linear-gradient(105deg,rgba(11,13,10,.9) 0%,rgba(11,13,10,.6) 55%,rgba(11,13,10,.3) 100%)}
.pref-contrast .layer--walk::after{background:linear-gradient(95deg,rgba(11,13,10,.9) 0%,rgba(11,13,10,.6) 55%,rgba(11,13,10,.3) 100%)}
.pref-contrast :focus-visible{outline-width:3px}

/* ---------- underline links ----------
   WCAG 1.4.1: colour alone should not be what marks a link. Most of the
   site's links already carry a border-bottom; this catches the ones that do
   not — the nav, the cards, the footer wordmark. */
.pref-links :where(.mast__nav a,.mast__panel a,.feat__item,.proj__long a,
  .where__meta a,.foot a,.link,.svc__btn,.feat__src a){
  text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.pref-links .feat__item{text-decoration-color:rgba(242,237,227,.6)}

/* ---------- readable typeface ----------
   Drops the display serif and the mono label face, and relaxes the tracking
   on the uppercase runs, which are the hardest thing on this page to read
   with a reading difficulty. */
html.pref-readable{
  --display:"Karla",system-ui,sans-serif;
  --label:system-ui,-apple-system,"Segoe UI",sans-serif;
}
.pref-readable :where(.eyebrow,.feat__label,.feat__go,.feat__cap,.feat__flag,
  .trap__meta,.trap__stamp,.traps__note,.walk__point h3,.walk__note,.proj__status,
  .proj__meta,.gal__tab,.formnote,.field span,.where__meta,.foot,.cue,.link,
  .svc__btn,.submit,.feat__src__out,.feat__src__note,.walk__facts h3,
  .mast__nav a,.lb__cap){letter-spacing:.04em}
.pref-readable :where(h1,h2,h3,.mast__word){letter-spacing:0}
.pref-readable body{font-weight:400}
.pref-readable :where(p,li,dd,dt){line-height:1.75}

/* ============================================================
   THE BUTTON
   Bottom LEFT on purpose: cms.js puts its login button bottom right, and two
   floating circles in the same corner would sit on top of each other.
   ============================================================ */
.a11y-fab{position:fixed;left:clamp(.75rem,2vw,1.25rem);bottom:clamp(.75rem,2vw,1.25rem);
  z-index:130;width:52px;height:52px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(11,13,10,.88);color:#F2EDE3;
  border:1px solid rgba(242,237,227,.4);cursor:pointer;
  box-shadow:0 2px 14px rgba(0,0,0,.45);
  transition:background .2s,border-color .2s,transform .2s}
.a11y-fab:hover,.a11y-fab:focus-visible{background:rgba(11,13,10,.98);
  border-color:#F2EDE3;transform:translateY(-2px)}
.a11y-fab svg{width:26px;height:26px;display:block;fill:currentColor}
.a11y-fab[aria-expanded="true"]{border-color:#E0A85C}

/* a soft ground behind the mark so it survives sitting over pale photography */
@media (prefers-reduced-motion:reduce){.a11y-fab{transition:none}}
.pref-reduce .a11y-fab{transition:none}

/* ---------- the panel ---------- */
.a11y-panel{position:fixed;z-index:131;
  left:clamp(.75rem,2vw,1.25rem);bottom:calc(52px + clamp(1.5rem,4vw,2.25rem));
  width:min(21rem,calc(100vw - 1.5rem));max-height:calc(100vh - 6.5rem);
  overflow-y:auto;overscroll-behavior:contain;
  background:#12160F;color:#F2EDE3;
  border:1px solid rgba(242,237,227,.28);border-radius:6px;
  box-shadow:0 10px 40px rgba(0,0,0,.6);
  padding:1.1rem 1.15rem 1.25rem;
  font-family:"Karla",system-ui,sans-serif;font-weight:300}
.a11y-panel[hidden]{display:none}

.a11y-panel h2{font-family:"Karla",system-ui,sans-serif;
  font-size:.78rem;font-weight:500;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(242,237,227,.75);margin:0 0 .7rem;line-height:1.3}

.a11y-group{margin:0 0 .8rem;border:0;padding:0;min-inline-size:0}
.a11y-group:last-of-type{margin-bottom:.6rem}
.a11y-group legend{font-size:.72rem;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(242,237,227,.62);
  padding:0;margin:0 0 .4rem}

/* Each control is a real checkbox or radio, styled but never replaced — the
   native element keeps the keyboard behaviour, the announcement and the
   state for free. */
.a11y-opt{display:flex;align-items:flex-start;gap:.65rem;
  min-height:44px;padding:.25rem .4rem;margin:0 -.4rem;
  border-radius:3px;cursor:pointer;font-size:.96rem;line-height:1.35;
  transition:background .15s}
.a11y-opt:hover{background:rgba(242,237,227,.06)}
.a11y-opt input{flex:none;width:1.15rem;height:1.15rem;margin:.15rem 0 0;
  accent-color:#E0A85C;cursor:pointer}
.a11y-opt span{flex:1}
.a11y-opt small{display:block;font-size:.78rem;line-height:1.35;
  color:rgba(242,237,227,.6);margin-top:.05rem}
.a11y-opt input:focus-visible{outline:2px solid #E0A85C;outline-offset:2px}

.a11y-seg{display:flex;gap:.35rem}
.a11y-seg label{flex:1;position:relative;display:flex;align-items:center;
  justify-content:center;min-height:44px;padding:.4rem .3rem;
  border:1px solid rgba(242,237,227,.28);border-radius:3px;cursor:pointer;
  font-size:.88rem;text-align:center;transition:background .15s,border-color .15s}
.a11y-seg input{position:absolute;opacity:0;width:1px;height:1px;margin:0}
.a11y-seg label:hover{background:rgba(242,237,227,.07)}
.a11y-seg input:checked+span{font-weight:500}
.a11y-seg label:has(input:checked){background:#F2EDE3;color:#12160F;border-color:#F2EDE3}
.a11y-seg label:has(input:focus-visible){outline:2px solid #E0A85C;outline-offset:2px}
/* :has() is well supported now but this has to degrade honestly where it is
   not — the checked control still reads as checked to a screen reader, and
   this class is mirrored on by the script for the visual state. */
.a11y-seg label.is-on{background:#F2EDE3;color:#12160F;border-color:#F2EDE3}

.a11y-foot{display:flex;align-items:center;justify-content:space-between;
  gap:.75rem;padding-top:.7rem;margin-top:.2rem;
  border-top:1px solid rgba(242,237,227,.16)}
.a11y-reset{background:none;border:0;padding:.5rem .1rem;min-height:44px;
  color:rgba(242,237,227,.75);font:inherit;font-size:.86rem;
  text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.a11y-reset:hover,.a11y-reset:focus-visible{color:#F2EDE3}
.a11y-close{background:none;border:1px solid rgba(242,237,227,.35);
  border-radius:3px;color:#F2EDE3;font:inherit;font-size:.86rem;
  min-height:44px;padding:.5rem 1rem;cursor:pointer;transition:background .15s}
.a11y-close:hover,.a11y-close:focus-visible{background:rgba(242,237,227,.1)}

.a11y-note{margin:.6rem 0 0;font-size:.77rem;line-height:1.45;
  color:rgba(242,237,227,.55)}

/* Announcements for the toggles. Visually hidden, not display:none — the
   latter is not read out. */
.a11y-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* On a small screen the panel is a sheet across the bottom instead of a
   floating card — a 21rem card next to a 52px button leaves almost no room
   for the finger that opened it. */
@media (max-width:560px){
  .a11y-panel{left:0;right:0;bottom:0;width:100%;
    max-height:min(80vh,32rem);border-radius:10px 10px 0 0;
    border-left:0;border-right:0;border-bottom:0;
    padding:1.1rem 1.15rem calc(1.25rem + env(safe-area-inset-bottom,0px))}
}

/* The panel must stay usable while the site is in edit mode, and must never
   be counted as page content — see §10: everything it injects carries
   data-cms-ui so the CMS path keys skip it. */
