
:root{
  --navy:#0A1C42;
  --navy-secondary:#15284F;
  --muted-blue:#4F566B;
  --red:#C51825;
  --bg-pale-blue:#EDF2F8;
  --bg-near-white:#F6F8FB;
  --text-primary:#17191D;
  --text-secondary:#697386;
  --border:#DBDCE0;
  --white:#FFFFFF;
  --footer-dark:#071632;

  --color-surface:var(--white);
  --color-surface-raised:var(--bg-near-white);
  --color-surface-pale:var(--bg-pale-blue);
  --color-ink:var(--text-primary);
  --color-ink-muted:var(--text-secondary);
  --color-accent:var(--navy);        /* structural interactive: borders, focus rings, CTA fill */
  --color-accent-strong:var(--navy-secondary); /* hover state for accent fills */
  --color-red:var(--red);            /* small accent ONLY — underlines, hover, tiny rules. Never a fill. */
  --color-border:var(--border);

  --nav-bg:var(--white);
  --nav-border:var(--border);
  --nav-ink:var(--text-primary);
  --nav-ink-muted:var(--text-secondary);
  --nav-accent:var(--navy);
  --nav-accent-strong:var(--navy-secondary);
  --nav-accent-ink:var(--white);

  --footer-bg:var(--footer-dark);
  --footer-border:#1B2C50;
  --footer-ink:#EDF1F8;
  --footer-ink-muted:#9FB0CC;

  --font-heading:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --font-body:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
}
/* Dark mode: re-valued, not reinvented — every rule below that reads var(--color-*)/var(--nav-*)
   is correct in both palettes with no further changes. System preference is the default; an
   explicit choice recorded via /static/theme-init.js always wins once set (same mechanism the
   rest of the site already uses). Navy reads as ink-on-dark rather than as a fill in dark mode
   (a navy fill would nearly disappear against a near-black page), so --nav-accent/-color-accent
   move to a lighter blue there, with --nav-accent-ink flipping to a dark ink so CTA text stays
   readable on that lighter fill. */
@media(prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --color-surface:#0A0A0A;
    --color-surface-raised:#151515;
    --color-surface-pale:#101826;
    --color-ink:#F5F1E8;
    --color-ink-muted:#9A9690;
    --color-accent:#6FA8FF;
    --color-accent-strong:#8FBBFF;
    --color-red:#FF8A80;
    --color-border:#2A2A2A;
    --nav-bg:var(--color-surface);
    --nav-border:var(--color-border);
    --nav-ink:var(--color-ink);
    --nav-ink-muted:var(--color-ink-muted);
    --nav-accent:#6FA8FF;
    --nav-accent-strong:#8FBBFF;
    --nav-accent-ink:#07142B;
    --footer-bg:#050B18;
    --footer-border:#16223B;
    --footer-ink:#EDF1F8;
    --footer-ink-muted:#9FB0CC;
  }
}
:root[data-theme="dark"]{
  --color-surface:#0A0A0A;
  --color-surface-raised:#151515;
  --color-surface-pale:#101826;
  --color-ink:#F5F1E8;
  --color-ink-muted:#9A9690;
  --color-accent:#6FA8FF;
  --color-accent-strong:#8FBBFF;
  --color-red:#FF8A80;
  --color-border:#2A2A2A;
  --nav-bg:var(--color-surface);
  --nav-border:var(--color-border);
  --nav-ink:var(--color-ink);
  --nav-ink-muted:var(--color-ink-muted);
  --nav-accent:#6FA8FF;
  --nav-accent-strong:#8FBBFF;
  --nav-accent-ink:#07142B;
  --footer-bg:#050B18;
  --footer-border:#16223B;
  --footer-ink:#EDF1F8;
  --footer-ink-muted:#9FB0CC;
}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:300;font-display:swap;src:url(/static/fonts/ibm-plex-mono-light.woff2) format('woff2');}
/* Smooth light/dark handoff on every element whose color comes from a token above, rather than
   listing each selector individually. Reduced-motion visitors get an instant switch instead. */
*,*::before,*::after{transition:background-color .25s ease,border-color .25s ease,color .25s ease,fill .25s ease,stroke .25s ease}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none}}

/* ── Button tooltips (public site) ──
   Same component/behavior as BRAND_TOKENS' .tip-anchor/.tip-bubble — duplicated here (rather than
   shared) because this file intentionally does not import BRAND_TOKENS, to keep the public
   palette fully independent of the login page's Onyx & Brass one. Fixed navy/white chip
   regardless of --color-*: a dark floating chip reads clearly against either page theme, so it
   never needs re-valuing under prefers-color-scheme/[data-theme]. */
.tip-anchor{position:relative}
.tip-bubble{
  position:absolute;z-index:80;left:50%;bottom:calc(100% + 9px);
  width:max-content;max-width:220px;
  --tip-dy:6px;--tip-scale:.94;--tip-ox:center;--tip-oy:bottom;
  transform:translate(var(--tip-x,-50%),var(--tip-dy)) scale(var(--tip-scale));
  transform-origin:var(--tip-ox) var(--tip-oy);
  background:var(--navy);color:var(--white);border:1px solid rgba(255,255,255,.12);
  font:400 .75rem/1.4 var(--font-body);letter-spacing:.01em;text-transform:none;text-align:left;
  padding:6px 10px;border-radius:7px;box-shadow:0 10px 28px -10px rgba(10,28,66,.5);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .15s ease,transform .15s ease,visibility 0s linear .15s;
}
.tip-bubble.tip-below{bottom:auto;top:calc(100% + var(--tip-below-gap,9px));--tip-oy:top;--tip-dy:-6px}
.tip-bubble.tip-left{left:0;--tip-x:0;--tip-ox:left}
.tip-bubble.tip-right{left:auto;right:0;--tip-x:0;--tip-ox:right}
.pnav .tip-bubble{--tip-below-gap:18px}
.tip-bubble.tip-visible{
  --tip-dy:0px;--tip-scale:1;opacity:1;visibility:visible;
  transition:opacity .15s ease,transform .15s ease,visibility 0s;
}
@media(prefers-reduced-motion:reduce){.tip-bubble{transition:opacity .01s linear,visibility 0s}}
@media(hover:none){.tip-bubble{display:none}}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{margin:0;background:var(--color-surface);color:var(--color-ink);font:300 16px/1.6 var(--font-body);letter-spacing:.03em;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a{color:var(--color-ink)}
:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px;border-radius:3px}
img,svg{max-width:100%}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link{
  position:absolute;left:12px;top:-48px;z-index:100;
  background:var(--color-ink);color:var(--color-surface);
  padding:11px 18px;border-radius:8px;font:600 14px/1 var(--font-body);text-decoration:none;
  transition:top .15s ease;
}
.skip-link:focus{top:12px}

.wrap{max-width:900px;margin:0 auto;padding:0 clamp(18px,5vw,28px)}
.wrap-narrow{max-width:700px;margin:0 auto;padding:0 clamp(18px,5vw,28px)}
/* A page without its own .hero title band (Contact/Book) still needs clearance under the sticky
   nav — same value the inline style="padding-top:2.2rem" used to set before the strict
   style-src 'self' CSP made that a silently-dropped, broken declaration. */
.pt-page{padding-top:2.2rem}
/* Disclaimer note directly above a section's closing CTA row. */
.mt-note{margin-top:1.4rem}

/* One fast, simple fade — never an orchestrated reveal sequence (brief's own constraint). */
.fade-in{animation:brand-fade .35s ease-out both}
@keyframes brand-fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.fade-in{animation:none}}

/* Small uppercase kicker labels (.eyebrow, .card .tag) read as text, not as a border/divider/
   hover affordance, so per accent-discipline they don't take --color-accent — and at this size
   accent-on-surface measures ~2.99:1 anyway, below AA. ink-muted-on-surface is 5.35:1. */
.eyebrow{font-family:var(--font-body);font-weight:400;text-transform:uppercase;letter-spacing:.18em;font-size:.72rem;color:var(--color-ink-muted);margin:0 0 .9rem}
/* System-sans headings, bold weight for hierarchy (no display serif on this palette — see the
   note on PUBLIC_TOKENS above for why no new font file was added). */
h1,h2,h3{font-family:var(--font-heading);font-weight:700;color:var(--color-ink);letter-spacing:-.01em;text-wrap:balance;margin:0 0 .6em}
h1{font-size:clamp(2.1rem,5.2vw,3.4rem);line-height:1.08}
h2{font-size:clamp(1.5rem,3.2vw,2.1rem);line-height:1.16}
h3{font-size:1.32rem;line-height:1.3}
/* Taglines stay in the body/UI weight, not the heading weight — a visual step down from h1/h2. */
.dek{color:var(--color-ink-muted);font-weight:400;font-size:clamp(1.05rem,2vw,1.3rem);line-height:1.4;margin:0 0 1.4rem;max-width:38em}
p{margin:0 0 1.1em;max-width:38em}
.muted{color:var(--color-ink-muted)}
.center{text-align:center}
.sm{font-size:12.5px}

/* ── Hero ──
   White surface, ink text, marked out by weight/size alone rather than an inverted dark block —
   the nav is the one deliberately dark element on the page (see PUBLIC_NAV_CSS). The .hero-scoped
   overrides below are kept even though most just restate the base value, so a future section that
   nests inside .hero has an explicit override point to change without touching the base rule. */
.hero{background:var(--color-surface);color:var(--color-ink);padding:clamp(3.2rem,9vh,5.5rem) 0 clamp(2.6rem,7vh,4rem)}
/* Home only (.hero-landing — see home.ts): the landing/above-the-fold section. Deliberately NOT
   a 100vh-centered block (the previous version) — that read as mostly empty space above the
   fold on a real laptop screen. Tight top padding pulls the headline close under the nav; an
   asymmetric two-column grid (copy + one large image) fills the width instead of stacking
   everything in a narrow centered column, so the section reads as full without needing height. */
.hero-landing{padding:clamp(1.6rem,4vh,2.6rem) 0 clamp(2.8rem,6vh,4rem)}
.hero-landing .wrap{max-width:1180px}
.hero h1{color:var(--color-ink)}
.hero .dek{color:var(--color-ink-muted)}
.hero .eyebrow{color:var(--color-ink-muted)}

/* ── Split layout: copy + one large image ──
   Used by the hero and by any other section that pairs a block of copy with one photo (e.g. the
   Home eyewear teaser) — a generic asymmetric two-column composition, not hero-specific. */
.split{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,64px);align-items:center}
.split-copy{max-width:34em}
.split-copy p{max-width:30em}

/* Editorial photo treatment: natural aspect ratio, restrained radius, no drop shadow — a thin
   accent border is the only separation from the page (same border language as .card). */
.media-frame{margin:0;aspect-ratio:4/5;border-radius:18px;overflow:hidden;border:1px solid var(--color-border)}
.media-frame img{width:100%;height:100%;object-fit:cover;display:block}
/* Honest placeholder for the day real photography is confirmed — same labeled-placeholder
   convention as about.ts's office/team photos, not a stock-photo stand-in. Swap the inner markup
   for a plain <img> when a real photo exists; .media-frame's own box is unaffected. */
.media-placeholder{
  width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  background:var(--color-surface-raised);color:var(--color-ink-muted);
}
.media-placeholder svg{width:56px;height:56px;opacity:.5}
.media-placeholder span{font-family:var(--font-body);font-weight:400;font-size:.68rem;text-transform:uppercase;letter-spacing:.18em;text-align:center;padding:0 1.5em}

@media(max-width:860px){
  .split{grid-template-columns:1fr;gap:28px}
  .media-frame{aspect-ratio:16/10}
}

/* ── CTA buttons — one obvious next action per page ──
   Button system: primary (.cta) = solid navy fill / white text, hover moves to --navy-secondary
   (18.9:1, still AAA). Secondary (.cta-ghost) = white fill / navy border+text, hover fills navy
   with white text — never red: red is reserved strictly for small accents (underlines, hover
   link color, tiny rules), never a button background. Existing markup already combines both
   classes on some secondary actions (see home.ts) — .cta-ghost's rules below win via source
   order/specificity where both are present, exactly as before. */
.cta-row{display:flex;flex-wrap:wrap;gap:12px;margin-top:1.6rem}
.cta{
  display:inline-flex;align-items:center;gap:8px;padding:13px 24px;border-radius:8px;
  background:var(--color-accent);color:var(--white);font:600 15px/1 var(--font-body);text-decoration:none;
  text-transform:uppercase;letter-spacing:.1em;
  border:1px solid var(--color-accent);cursor:pointer;
  transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),
    color .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);
}
/* Subtle scale-up + a soft shadow that reads as lift, never a shift in position (transform/
   box-shadow only — no layout property changes, so this stays off the compositor's repaint path). */
.cta:hover{background:var(--color-accent-strong);border-color:var(--color-accent-strong);transform:scale(1.02);box-shadow:0 6px 18px -8px rgba(10,28,66,.35)}
.cta:active{transform:scale(.98);box-shadow:none;transition-duration:.08s}
.cta-ghost{background:var(--color-surface);color:var(--color-accent);border:1px solid var(--color-accent)}
.cta-ghost:hover{background:var(--color-accent);color:var(--white);border-color:var(--color-accent)}
.hero .cta-ghost{color:var(--color-accent);border-color:var(--color-accent)}
.hero .cta-ghost:hover{background:var(--color-accent);color:var(--white);border-color:var(--color-accent)}

/* ── Sections / cards ──
   Cards sit on --color-surface-raised (bg-near-white), a step off the page's pure-white
   --color-surface, with a neutral --color-border hairline — the site's "~8% neutral gray" budget.
   Dark mode re-values both tokens (see PUBLIC_TOKENS) rather than reinventing this rule. */
section.block{padding:clamp(2.6rem,7vh,4.2rem) 0}
.section-line{border-top:1px solid var(--color-border)}
.grid-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;margin-top:1.6rem}
.card{
  background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:12px;padding:22px 22px 20px;
  transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-color .25s cubic-bezier(.4,0,.2,1);
}
/* Only clickable cards lift on hover — a card that's just a static content block (most of
   .grid-cards' uses) has no affordance to signal, so the lift is opt-in via a wrapping <a>/
   [href] rather than applying to every .card unconditionally. */
a.card:hover,.card:has(> a):hover,.card[href]:hover{
  transform:translateY(-4px);box-shadow:0 14px 28px -16px rgba(10,28,66,.28);border-color:var(--color-accent)
}
.card h3{margin-bottom:.4em}
.card .tag{font-family:var(--font-body);font-weight:400;font-size:.68rem;text-transform:uppercase;letter-spacing:.18em;color:var(--color-ink-muted);margin-bottom:.5em;display:block}

/* ── Trust strip (home.ts, directly under the hero) ──
   Deliberately not cards: a thin-divided line of short claims, so it reads as a credibility
   footnote to the hero rather than a second competing section. */
.trust-strip{border-top:1px solid var(--color-border);border-bottom:1px solid var(--color-border)}
.trust-strip .wrap{display:flex;flex-wrap:wrap;padding:1rem 0}
.trust-item{
  flex:1 1 210px;display:flex;align-items:center;gap:9px;
  padding:.6rem clamp(4px,2.4vw,22px);border-left:1px solid var(--color-border);
  font-family:var(--font-mono);font-size:.76rem;letter-spacing:.02em;color:var(--color-ink);
}
.trust-item:first-child{border-left:none}
.trust-item svg{flex:none;width:15px;height:15px;color:var(--color-ink-muted)}
@media(max-width:680px){
  .trust-item{flex:1 1 100%;border-left:none;border-top:1px solid var(--color-border);padding:.7rem 2px}
  .trust-item:first-child{border-top:none}
}

/* ── Editorial service list ──
   An alternative to .grid-cards/.card for a denser, typography-led presentation: a plain
   divided list rather than boxed cards, so a 4-6 item service list doesn't read as a grid of
   floating SaaS tiles. Used on the Services page and the Home services teaser. */
.service-list{border-top:1px solid var(--color-border);margin-top:1.6rem}
.service-row{display:grid;grid-template-columns:minmax(150px,270px) 1fr;gap:8px 28px;padding:1.5rem 0;border-bottom:1px solid var(--color-border)}
.service-row h3{margin:0}
.service-row p{margin:0 0 .5em;max-width:42em}
.service-row p:last-child{margin-bottom:0}
@media(max-width:680px){.service-row{grid-template-columns:1fr;gap:6px}}

/* ── Proof bar (home.ts, right after the hero) ──
   Google is visually dominant (bold stars + score) per the brief; Yelp is a smaller secondary
   link beside it. Sits on the pale-blue surface so it reads as a distinct strip without a full
   border treatment; --text-primary/--text-secondary on --bg-pale-blue both keep the same AA
   contrast ratios documented above PUBLIC_TOKENS (those tokens don't change on this background). */
.proof-bar{background:var(--color-surface-pale);border-bottom:1px solid var(--color-border)}
.proof-bar-inner{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;padding:14px 0}
.proof-primary{
  display:inline-flex;align-items:baseline;flex-wrap:wrap;gap:8px;text-decoration:none;
  font-family:var(--font-body);color:var(--color-ink);
}
.proof-primary:hover .proof-copy{color:var(--color-accent)}
.proof-stars{color:var(--color-accent);font-size:1rem;letter-spacing:.05em}
.proof-score{font-weight:700;font-size:1.15rem}
.proof-copy{font-size:.92rem;color:var(--color-ink-muted);transition:color .15s}
.proof-secondary{
  font-family:var(--font-body);font-size:.85rem;color:var(--color-ink-muted);text-decoration:none;
  border-left:1px solid var(--color-border);padding-left:22px;
}
.proof-secondary:hover{color:var(--color-accent)}
@media(max-width:560px){.proof-secondary{border-left:none;padding-left:0}}

/* ── Testimonial cards ("Families come back", home.ts) ── reuses .card/.grid-cards for the
   shell, just adds quote typography. */
.review-quote{font-size:1.02rem;line-height:1.5;margin:0 0 .8em}
.review-quote::before,.review-quote::after{content:none}
.review-attr{margin:0}

/* ── Doctor spotlight rating line (about.ts) — small red-accented line under her bio, on the
   navy .doctor-card fill, so it uses the light text tokens the rest of .doctor-copy already
   established rather than the page's default ink tokens. */
.doctor-rating{color:rgba(255,255,255,.92);font-size:.88rem;margin-top:.6em}
.doctor-rating span[aria-hidden]{color:var(--color-red);font-weight:600}

/* ── Appointment CTA band (home.ts, before the footer) ──
   A quiet, centered close to the page — a heavier top border marks it as a distinct final beat,
   not another .section-line subsection. Stays on the white page surface; the footer just below it
   is the page's one deliberately dark section (see .site-foot). */
.cta-band{border-top:1px solid var(--color-border);padding:clamp(3rem,7vh,4.4rem) 0;text-align:center}
.cta-band .wrap{max-width:620px}
.cta-band .cta-row{justify-content:center}

/* ── Placeholder content flag ──
   No warning/amber token exists in this palette; mapped to ink-muted text + accent border
   (dashed, to keep it visually distinct from a card) rather than inventing a new color. */
.pending{
  display:inline-flex;align-items:center;gap:6px;font-family:var(--font-mono);font-size:.7rem;
  letter-spacing:.04em;color:var(--color-ink-muted);background:var(--color-surface);border:1px dashed var(--color-accent);border-radius:6px;
  padding:3px 9px;margin:.3em 0;
}

/* ── Mono labels: hours, phone numbers, addresses (brief's explicit spec) ── */
.mono-label{font-family:var(--font-mono);letter-spacing:.02em}
.hours-table{width:100%;border-collapse:collapse;margin-top:.6rem;font-family:var(--font-mono);font-size:.92rem}
.hours-table td{padding:6px 0;border-bottom:1px solid var(--color-border)}
.hours-table td:first-child{color:var(--color-ink-muted);width:40%}
.hours-table tr:last-child td{border-bottom:none}
/* The one deliberate small-red touch on this pairing: a red underline (never a fill) marks the
   phone number as tappable, echoing the "subtle red underline/accent on hover" rule for text
   links elsewhere on the page. */
.phone-link{font-family:var(--font-mono);color:var(--color-ink);text-decoration:none;border-bottom:1px solid var(--color-red)}
.phone-link:hover{color:var(--color-accent)}

/* ── Staff / services list ──
   The placeholder photo box is a small fixed-size swatch (64px), not a page-scale fill; ink-muted
   fill + surface text/icon measures the same compliant 5.35:1 used everywhere else this pair
   appears. */
.staff-card{display:flex;gap:16px;align-items:flex-start}
.staff-photo{
  flex:none;width:64px;height:64px;border-radius:10px;background:var(--color-ink-muted);
  display:flex;align-items:center;justify-content:center;font-family:var(--font-mono);
  font-size:.6rem;color:var(--color-surface);text-align:center;line-height:1.3;padding:4px;
}

/* ── Doctor spotlight panel (about.ts) ──
   The one dark panel on an otherwise white/pale-blue page: navy fill, white type, a small red
   accent under the name (the site's "small rule" use of red, never a fill) — the optometrist is
   the practice's one deliberately spotlighted person, so she gets a visually distinct treatment
   from the plain .staff-card roster below her. Portrait uses the same .media-frame/
   .media-placeholder convention as the hero/eyewear teasers elsewhere on the site. */
.doctor-card{
  display:flex;gap:24px;align-items:flex-start;flex-wrap:wrap;
  background:var(--color-accent);border-color:var(--color-accent);color:var(--white);
}
.doctor-portrait{width:min(220px,100%);flex:none;aspect-ratio:1/1;border-color:rgba(255,255,255,.25)}
.doctor-portrait .media-placeholder{background:rgba(255,255,255,.08);color:rgba(255,255,255,.75)}
.doctor-copy{flex:1 1 260px;min-width:0}
.doctor-copy .eyebrow{color:rgba(255,255,255,.65)}
.doctor-copy h3{
  color:var(--white);display:inline-block;border-bottom:2px solid var(--color-red);padding-bottom:.2em;
}
.doctor-copy .muted{color:rgba(255,255,255,.72)}
.doctor-copy p:not(.muted):not(.eyebrow){color:rgba(255,255,255,.92)}

/* ── PLACEHOLDER: "Our Team" preview grid (about.ts) — a featured, photo-forward card variant
   distinct from .staff-card above (which is the confirmed-bio row layout). Swap nothing here
   directly; it renders only until real staff are saved via /settings/content/staff. Same
   ink-muted/surface swatch pairing as .staff-photo above, for consistency. ── */
.team-card{text-align:center}
.team-avatar{
  width:100%;aspect-ratio:1/1;border-radius:10px;background:var(--color-ink-muted);
  display:flex;align-items:center;justify-content:center;overflow:hidden;margin-bottom:14px;
}
.team-avatar img{width:100%;height:100%;object-fit:cover;display:block}
.team-card h3{margin-bottom:.2em}
.team-card p{margin-bottom:0}

/* ── PLACEHOLDER: "Our Office" gallery (about.ts) — neutral photo placeholders sized to the
   same .grid-cards rhythm as the team grid above. Swap each .office-photo's src for a real
   photo; the figure/figcaption structure and alt text are already shaped for that. ── */
.office-figure{margin:0;background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:12px;overflow:hidden}
.office-photo{width:100%;aspect-ratio:4/3;background:var(--color-ink-muted);display:block;object-fit:cover}
.office-figure figcaption{
  padding:10px 14px 14px;font-family:var(--font-body);font-weight:400;font-size:.7rem;text-transform:uppercase;
  letter-spacing:.18em;color:var(--color-ink-muted);
}

/* ── Footer ──
   Deliberately dark (--footer-dark #071632) against the otherwise white/pale-blue page, per the
   brand brief's ~2% "dark anchor" close — its own token set (--footer-*) rather than the shared
   --color-*/--nav-* roles, since it's the one section that stays dark regardless of light/dark
   mode (matching the fixed-dark nav-bar pattern this site already uses elsewhere). Contrast:
   --footer-ink on --footer-dark ~17.9:1, --footer-ink-muted on --footer-dark ~7.2:1 (both AAA). */
.site-foot{background:var(--footer-bg);color:var(--footer-ink-muted);padding:2.6rem 0 3rem;margin-top:3rem;border-top:1px solid var(--footer-border)}
.site-foot .wrap{display:flex;flex-wrap:wrap;gap:24px;justify-content:space-between;align-items:flex-start}
.site-foot a{color:var(--footer-ink-muted);text-decoration:none}
.site-foot a:hover{color:var(--footer-ink)}
.foot-brand{font-family:var(--font-heading);font-weight:700;color:var(--footer-ink);font-size:1.1rem;margin-bottom:.3em}
.foot-nap{font-family:var(--font-mono);font-size:.82rem;line-height:1.8;color:var(--footer-ink-muted)}
.foot-nap .phone-link{color:var(--footer-ink);border-bottom-color:var(--color-red)}
.foot-links{display:flex;flex-direction:column;gap:6px;font-size:.85rem}
.foot-copy{max-width:900px;margin:1.6rem auto 0;padding:0 clamp(18px,5vw,28px);font-size:.78rem;color:var(--footer-ink-muted)}

/* ── Contact/Book two-column form (kept for structural parity with the existing SHOP_CSS
   .co/.co-form/.co-summary shapes, so web/fitting.ts's markup didn't need a rewrite) ── */
.co-h{font-family:var(--font-heading);font-weight:500;font-size:1.8rem;letter-spacing:-.02em;margin:0 0 1.2rem}
.co{display:grid;grid-template-columns:1.3fr 1fr;gap:36px;align-items:start}
.co-form{display:flex;flex-direction:column;gap:15px}
.co-form label{display:flex;flex-direction:column;gap:6px;font-size:13.5px;color:var(--color-ink-muted)}
.co-form input,.co-form select,.co-form textarea{
  padding:12px 13px;border:1px solid var(--color-border);border-radius:8px;font:inherit;
  background:var(--color-surface);color:var(--color-ink);
  transition:border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);
}
/* Animated focus ring: border shifts to the accent color and a soft halo grows in, rather than
   the plain default outline just appearing — still layered under :focus-visible's own outline. */
.co-form input:focus,.co-form select:focus,.co-form textarea:focus{
  border-color:var(--color-accent);box-shadow:0 0 0 4px rgba(10,28,66,.12);outline:none
}
.co-form textarea{resize:vertical}
.co-form .opt{color:var(--color-ink-muted);font-weight:400}
.co-form .consent{flex-direction:row;align-items:center;gap:10px;color:var(--color-ink);font-size:14px}
.co-form .consent input{width:auto;padding:0}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* Form validation error — the one legitimate small-text use of --color-red outside a hover state
   (5.95:1 on white, passes AA — see the contrast note above PUBLIC_TOKENS). Still not a fill. */
.co-error{color:var(--color-red);font-size:14px}
.co-summary{background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:12px;padding:20px}
.co-brand{font-weight:600}
.co-model{color:var(--color-ink-muted);font-size:13.5px;margin-bottom:14px}
.co-line{display:flex;justify-content:space-between;gap:10px;font-size:14px;padding:6px 0;color:var(--color-ink-muted)}
.co-line span:first-child{flex:none}
.pd-note{color:var(--color-ink-muted);font-size:13px;margin-top:14px}
.back{color:var(--color-ink-muted);font-size:14px;display:inline-block;margin-bottom:16px;text-decoration:none}
.back:hover{color:var(--color-ink)}
.ok{max-width:460px;margin:0 auto;text-align:center}
/* Success glyph: navy fill / white glyph (21:1) — the same primary pairing as .cta, not the old
   generic gray-fill placeholder. */
.ok-check{width:56px;height:56px;border-radius:50%;background:var(--color-accent);color:var(--white);border:2px solid var(--color-accent);font-size:28px;display:flex;align-items:center;justify-content:center;margin:0 auto 16px}
@media(max-width:760px){.co{grid-template-columns:1fr;gap:22px}}
