/* Reset + typographic base shared by the public site and admin. */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:84px}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{animation:none!important;transition:none!important}}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--body);font-size:var(--fs-body);line-height:1.55;-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{font-family:var(--display);text-wrap:balance;margin:0;line-height:1.15;color:var(--ink)}
h1{font-size:var(--fs-d1);font-weight:700;letter-spacing:-.02em;line-height:1.05}
h2{font-size:var(--fs-d3);font-weight:700;letter-spacing:-.015em}
h3{font-size:var(--fs-xl);font-weight:700}
h4{font-size:var(--fs-lg);font-weight:700}
p{margin:0}
a{color:var(--action);text-decoration:none}
a:hover{text-decoration:underline}
img,svg,video{max-width:100%;height:auto;display:block}
button,input,select,textarea{font:inherit;color:inherit}
:focus-visible{outline:3px solid var(--orange);outline-offset:2px;border-radius:4px}
.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: invisible until it takes keyboard focus, then a visible button at the top
   left. .sr-only alone would stay clipped to 1px even while focused, so a keyboard user
   would tab onto a link they cannot see. */
.skip-link{position:absolute;left:var(--s4);top:var(--s2);z-index:2000;padding:var(--s2) var(--s4);border-radius:var(--r-sm);background:var(--navy);color:var(--on-navy);font-family:var(--display);font-weight:700;text-decoration:none;transform:translateY(-200%)}
.skip-link:focus{transform:none}
.wrap{max-width:var(--max);margin-inline:auto;padding-inline:clamp(16px,4vw,40px)}
.prose{max-width:var(--measure)}
.prose p+p,.prose ul+p,.prose p+ul{margin-top:.9em}
.prose h2{margin:1.6em 0 .6em;font-size:var(--fs-3xl)}
.prose > :first-child{margin-top:0}
.prose h3{margin:1.3em 0 .4em}
.prose ul,.prose ol{padding-left:1.3em;margin:0}
.prose li{margin:.3em 0}
.lede{font-size:var(--fs-xl);color:var(--ink-2)}
.muted{color:var(--ink-3)}
/* Small explanatory paragraph under a block, public and admin alike. Named footnote, not
   note: public.css already owns `.calc-box .note`, and a bare `.note` here would give those
   calculator notes a margin they never had. */
.footnote{margin-top:var(--s3);font-size:var(--fs-md);color:var(--ink-3)}
.eyebrow{font-family:var(--display);font-size:var(--fs-sm);font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--orange-text)}
.num{font-variant-numeric:tabular-nums;font-family:var(--mono);font-size:.92em}
.pill{display:inline-block;font-family:var(--display);font-size:var(--fs-sm);font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:var(--s1) var(--s3);border-radius:var(--r-pill);white-space:nowrap;background:var(--surface-2);color:var(--ink-2)}
.pill.ok{background:var(--ok-bg);color:var(--ok)}.pill.warn{background:var(--warn-bg);color:var(--warn)}.pill.bad{background:var(--bad-bg);color:var(--bad)}.pill.navy{background:var(--navy);color:var(--on-navy)}
/* Buttons: pills, three tones. The primary tone is navy; orange is reserved. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:var(--display);font-weight:700;font-size:.92rem;padding:12px 22px;border-radius:var(--r-pill);border:1.5px solid transparent;cursor:pointer;white-space:nowrap;text-decoration:none;line-height:1.1;min-height:44px;transition:background .15s,color .15s,border-color .15s,transform .05s}
.btn:hover{text-decoration:none}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--navy);color:var(--on-navy)}.btn-primary:hover{background:var(--navy-2)}
.btn-ghost{background:transparent;border-color:var(--line-2);color:var(--navy)}.btn-ghost:hover{background:var(--surface-2)}
.btn-orange{background:var(--orange);color:var(--navy)}.btn-orange:hover{background:var(--orange-deep)}
.btn-light{background:var(--surface);color:var(--navy);border-color:var(--surface)}.btn-light:hover{background:var(--surface-2)}
.btn-onnavy{background:transparent;border-color:rgba(255,255,255,.35);color:var(--white)}.btn-onnavy:hover{background:rgba(255,255,255,.08)}
.btn-sm{padding:8px 14px;font-size:.82rem;min-height:36px}
.btn-danger{background:var(--bad-bg);color:var(--bad);border-color:transparent}
.btn-secondary{background:var(--surface-2);color:var(--ink);border-color:var(--line)}
.btn-block{width:100%}
/* Light/dark switch (shared/_theme_toggle), used by the public header, the
   admin top bar and the sign-in page, which is why it lives in this shared
   file. The icon shows the mode a click switches TO: moon while light, sun
   while dark, driven by aria-pressed, which theme_controller.js keeps equal
   to the theme actually showing. */
.theme-toggle{display:inline-grid;place-items:center;flex:none;width:44px;height:44px;border:1.5px solid var(--line-2);border-radius:var(--r-pill);background:none;color:var(--ink-2);cursor:pointer}
/* `hidden` loses to any display rule on the button; without this line it
   would show with JavaScript off, where it cannot do anything. */
.theme-toggle[hidden]{display:none}
.theme-toggle:hover,.theme-toggle:focus-visible{background:var(--surface-2);color:var(--ink)}
.theme-toggle[aria-pressed=true] .theme-toggle__moon,.theme-toggle[aria-pressed=false] .theme-toggle__sun{display:none}
/* Forms */
.field{display:grid;gap:var(--s2);margin-bottom:var(--s4);align-content:start}
.field label,.field > .lbl{font-family:var(--display);font-weight:600;font-size:var(--fs-base);color:var(--ink)}
.field input:not([type=checkbox]):not([type=radio]),.field select,.field textarea{width:100%;padding:var(--s3) var(--s4);border:1.5px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface);color:var(--ink);font-family:inherit}
.field input:not([type=checkbox]):not([type=radio]),.field select{height:46px}
.field textarea{min-height:96px;padding-block:12px;line-height:1.5;resize:vertical}
.field select{appearance:none;text-overflow:ellipsis;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2366748F' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;background-size:16px;padding-right:40px}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--action);outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--action) 18%,transparent)}
.field .hint{font-size:var(--fs-md);color:var(--ink-3);line-height:1.4;margin-top:-1px}
.field .error{font-size:var(--fs-md);color:var(--bad)}
.field.invalid input,.field.invalid select,.field.invalid textarea{border-color:var(--bad)}
.field-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:0 var(--s4);align-items:start}
.check{display:flex;gap:var(--s3);align-items:flex-start;font-size:var(--fs-base);color:var(--ink-2)}
.check input{width:20px;height:20px;margin-top:var(--s1);flex:none;accent-color:var(--navy)}
.form-errors{background:var(--bad-bg);color:var(--bad);border-radius:var(--r-sm);padding:12px 16px;margin-bottom:var(--s4);font-size:var(--fs-base)}
.form-errors ul{margin:var(--s2) 0 0;padding-left:var(--s4)}
/* Flash */
.flash{padding:12px 16px;border-radius:var(--r-sm);font-size:var(--fs-base);margin-bottom:var(--s4);border:1px solid transparent}
.flash-notice{background:var(--ok-bg);color:var(--ok)}.flash-alert{background:var(--bad-bg);color:var(--bad)}
/* Cards & tables */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s5) 24px}
.tbl{overflow-x:auto;border:1px solid var(--line);border-radius:var(--r);background:var(--surface)}
table.data{border-collapse:collapse;width:100%;font-size:var(--fs-base)}
table.data th,table.data td{padding:var(--s3) var(--s4);text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
table.data th{font-family:var(--display);font-size:var(--fs-sm);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);background:var(--surface-2);white-space:nowrap}
table.data tr:last-child td{border-bottom:0}
table.data td.r,table.data th.r{text-align:right;font-variant-numeric:tabular-nums}
.empty{padding:var(--s6);text-align:center;color:var(--ink-3);border:1.5px dashed var(--line-2);border-radius:var(--r)}
.callout{border-left:4px solid var(--orange);background:var(--surface);border-radius:0 var(--r) var(--r) 0;padding:16px var(--s5);color:var(--ink-2)}
.callout b{color:var(--ink)}
/* Blocking busy overlay for mutating submits (conventions §4). The submit
   button is NEVER disabled — the Stimulus controller blocks the second
   submit event instead (global CLAUDE.md hard rule). */
.busy-overlay{position:fixed;inset:0;background:rgba(8,33,71,.55);display:grid;place-items:center;z-index:1000;color:var(--white);font-family:var(--display);text-align:center;padding:24px}
.busy-overlay .spinner{width:44px;height:44px;border:4px solid rgba(255,255,255,.3);border-top-color:var(--white);border-radius:50%;animation:spin .9s linear infinite;margin:0 auto 16px}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---- Photo grid and lightbox (public galleries AND the admin archive) ----
   In base.css, not public.css, because the admin layout loads tokens + fonts +
   base + admin only. The first version of the upload archive used .photo-grid
   from public.css, the rule was absent from the admin bundle, and every
   thumbnail rendered at full page width. If you move these rules, move them
   somewhere both layouts include. */
.photo-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s4);max-width:none;margin:0}
@media (max-width:1000px){.photo-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:620px){.photo-grid{grid-template-columns:1fr}}
/* A denser variant for the archive, which is a contact sheet rather than a
   gallery anyone reads. */
.photo-grid--dense{grid-template-columns:repeat(auto-fill,minmax(13rem,1fr))}

.photo-item{margin:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);overflow:hidden;display:flex;flex-direction:column}
.photo-item img{display:block;width:100%;height:200px;object-fit:cover;background:var(--surface-2)}
.photo-item .photo-zoom{cursor:zoom-in;transition:transform .3s ease}
.photo-item:hover .photo-zoom{transform:scale(1.04)}
.photo-item figcaption{padding:var(--s3) 12px;font-size:var(--fs-md);color:var(--ink-2);display:grid;gap:2px}
.photo-item figcaption small{color:var(--ink-3);font-size:var(--fs-sm);font-family:var(--mono)}

.lightbox{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;padding:4vh 5vw;background:var(--scrim);animation:lightbox-in .18s ease}
@keyframes lightbox-in{from{opacity:0}to{opacity:1}}
.lightbox-stage{margin:0;display:flex;flex-direction:column;align-items:center;gap:var(--s4);max-width:100%}
.lightbox-stage img{max-width:88vw;max-height:80vh;object-fit:contain;border-radius:var(--r-sm)}
.lightbox-stage figcaption{color:var(--on-scrim);font-size:var(--fs-base);text-align:center;max-width:62ch}
.lightbox-close,.lightbox-nav{position:absolute;display:inline-flex;align-items:center;justify-content:center;border:0;cursor:pointer;color:var(--white);background:rgba(255,255,255,.14);border-radius:var(--r-pill);transition:background .15s ease}
.lightbox-close:hover,.lightbox-nav:hover,.lightbox-close:focus-visible,.lightbox-nav:focus-visible{background:rgba(255,255,255,.3)}
.lightbox-close{top:18px;right:20px;width:46px;height:46px;font-size:var(--fs-4xl);line-height:1}
.lightbox-nav{top:50%;transform:translateY(-50%);width:52px;height:52px;font-size:var(--fs-5xl);line-height:1}
.lightbox-prev{left:18px}
.lightbox-next{right:18px}
.lightbox-count{position:absolute;bottom:18px;left:50%;transform:translateX(-50%);color:var(--on-scrim-2);font-family:var(--mono);font-size:var(--fs-md)}
@media (max-width:620px){
  .lightbox-nav{width:44px;height:44px;font-size:var(--fs-4xl)}
  .lightbox-prev{left:8px}.lightbox-next{right:8px}
  .lightbox-stage img{max-width:94vw}
}
