/* ============================================================================
   Portfolio — public gallery styles, ported from UIPrototype/Portfolio.dc.html.
   FONTS: the prototype uses Bodoni Moda (display serif) + Hanken Grotesk (sans).
   Those OFL fonts are not yet vendored (gated pending sign-off), so --serif/--sans
   fall back to a system stack. To adopt the real fonts, drop the woff2 files in
   wwwroot/fonts/, add @font-face rules, and set the two variables below.
   ============================================================================ */
:root {
  --serif: "Bodoni Moda", Georgia, "Times New Roman", serif;
  --sans: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --gold: #d8b56b;
  --gold-bright: #ecd39a;
  --ink: #0b0b0d;
  --paper: #f2f0ec;
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--gold); text-decoration: none; }
a:hover { color: var(--gold-bright); }
button { font-family: inherit; }
::selection { background: var(--gold); color: #17140d; }
.serif { font-family: var(--serif); }

input::placeholder, textarea::placeholder { color: #5c5c63; }
input:focus, textarea:focus { outline: none; }

/* ----- blur-up frames ----- */
.frame .full { opacity: 0; transition: opacity .9s ease, transform 3.5s ease; }
.frame .full.on { opacity: 1; }
.frame:hover .full.on { transform: scale(1.055); }
.frame .ph { filter: blur(18px); transform: scale(1.12); }
.frame .cap { opacity: 0; transform: translateY(10px); transition: opacity .45s ease, transform .45s ease; }
.frame:hover .cap { opacity: 1; transform: none; }
.frame .dl { opacity: 0; transform: translateY(-5px); transition: opacity .3s ease, transform .3s ease; }
.frame:hover .dl { opacity: 1; transform: none; }
.frame:hover { z-index: 3; }
.frame::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 0 1px rgba(255,255,255,0); transition: box-shadow .35s ease; pointer-events: none; }
.frame:hover::after { box-shadow: inset 0 0 0 1px rgba(216,181,107,0.55); }

/* ----- chips / buttons / lightbox anim ----- */
.chip { transition: background .25s ease, color .25s ease, border-color .25s ease, transform .2s ease; }
.chip:hover { transform: translateY(-1px); }
.arrowbtn { transition: background .25s ease, border-color .25s ease; }
.arrowbtn:hover { background: rgba(216,181,107,0.16); border-color: rgba(216,181,107,0.5); }
.loclink { transition: color .2s ease; }
.loclink:hover { color: var(--gold-bright) !important; }

.lb-img { opacity: 0; }
.lb-img.on { animation: lbIn .5s cubic-bezier(.2,.7,.2,1) both; }
/* Centered by margins, not translate — the spin animation owns transform. The .15s fadeIn delay
   keeps it invisible on fast loads so cached images don't flash a spinner. */
.lb-spin { position: absolute; left: 50%; top: 50%; width: 34px; height: 34px; margin: -17px 0 0 -17px;
           border-radius: 50%; border: 2px solid rgba(255,255,255,0.12); border-top-color: #d8b56b;
           animation: spin .8s linear infinite, fadeIn .3s ease .15s both; }
@keyframes spin { to { transform: rotate(360deg); } }
.lb-back { animation: fadeIn .35s ease both; }
.lb-panel { animation: panelIn .55s cubic-bezier(.2,.7,.2,1) both; }
/* The row must not wrap: a wrapping flex line sizes to its content, so the panel would grow past
   the viewport instead of being capped by .lb-body — its overflow-y:auto then never engages and the
   detail panel gets clipped by the fixed backdrop with nothing to scroll. nowrap + overflow:hidden
   caps the line at the container height so .lb-panel scrolls internally. (The stacked layout below
   re-enables overflow-y on .lb-body itself.) */
.lb-body { flex-wrap: nowrap; overflow: hidden; }
/* Freeze the grid behind the lightbox so the wheel scrolls the panel, not the page underneath. */
body.lb-open { overflow: hidden; }
.rel .full { opacity: 0; transition: opacity .6s ease; }
.rel .full.on { opacity: 1; }
.rel:hover { transform: translateY(-3px); }

@keyframes lbIn { from { opacity: 0; transform: scale(.955); } to { opacity: 1; transform: scale(1); } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes panelIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes shake { 10%,90% { transform: translateX(-2px); } 20%,80% { transform: translateX(4px); } 30%,50%,70% { transform: translateX(-7px); } 40%,60% { transform: translateX(7px); } }
.shake { animation: shake .5s; }

/* ----- nav ----- */
.navscroll { scrollbar-width: none; }
.navscroll::-webkit-scrollbar { display: none; }
.navtoggle { display: none; }

@media (max-width: 820px) { .aboutgrid { grid-template-columns: 1fr !important; } }
@media (max-width: 760px) {
  .topbar { flex-wrap: wrap; row-gap: 12px; padding-left: 5vw !important; padding-right: 5vw !important; }
  .brand { order: 1; }
  .navtoggle { display: flex; order: 2; margin-left: auto; }
  .navscroll { order: 3; width: 100%; flex-direction: column; align-items: stretch !important; gap: 2px !important; overflow: hidden; max-height: 0; transition: max-height .38s ease; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.07); border-radius: 14px; }
  .navscroll.open { max-height: 360px; padding: 6px 0; }
  .navscroll .navdiv { display: none; }
  .navscroll button { text-align: left; width: 100%; padding: 13px 16px !important; font-size: 15px !important; border-radius: 0 !important; }
  .navscroll .privbtn { margin: 8px 10px 6px !important; width: auto; background: rgba(216,181,107,0.1) !important; border-color: rgba(216,181,107,0.3) !important; color: #e7cf97 !important; }
}
@media (min-width: 761px) { .navscroll { max-height: none !important; } }

@media (max-width: 640px) {
  .lb-topbar { padding: 12px 16px !important; }
  .lb-title { font-size: 16px !important; }
  .lb-body { flex-direction: column !important; flex-wrap: nowrap !important; overflow-y: auto; }
  .lb-stage { flex: 0 0 auto !important; height: 54vh !important; padding: 6px !important; }
  .lb-stage img { max-height: 54vh !important; }
  .lb-arrow { width: 40px !important; height: 40px !important; }
  .lb-panel { max-width: none !important; min-width: 0 !important; border-left: none !important; border-top: 1px solid rgba(255,255,255,0.07) !important; }
  .lb-hint { display: none; }
  .heading { font-size: 30px !important; }
}

/* ----- filter drawer (right slide-out) + FAB ----- */
.filterbackdrop { position: fixed; inset: 0; z-index: 70; background: rgba(4,4,6,0.55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); animation: fadeIn .3s ease both; }
.filterside { position: fixed; top: 0; bottom: 0; width: 340px; max-width: 88vw; z-index: 75; background: rgba(13,13,16,0.97); backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px); overflow-y: auto; padding: 24px 24px 44px; transition: transform .42s cubic-bezier(.2,.7,.2,1); right: 0; border-left: 1px solid rgba(255,255,255,0.08); transform: translateX(103%); box-shadow: -30px 0 90px rgba(0,0,0,0.55); }
.filterside.open { transform: none; }
.filterfab { position: fixed; right: 20px; bottom: 20px; z-index: 72; display: flex; align-items: center; gap: 9px; background: var(--gold); color: #17140d; border: none; border-radius: 100px; padding: 14px 20px; font-size: 13.5px; font-weight: 600; letter-spacing: .02em; cursor: pointer; box-shadow: 0 14px 44px rgba(216,181,107,0.3); font-family: inherit; transition: transform .2s ease; }
.filterfab:hover { transform: translateY(-2px); }
.filterfab .badge { background: #17140d; color: #e7cf97; border-radius: 100px; min-width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; padding: 0 6px; font-variant-numeric: tabular-nums; }

/* ----- loading indicator (dark) ----- */
.loading-progress { position: relative; display: block; width: 8rem; height: 8rem; margin: 20vh auto 1rem; }
.loading-progress circle { fill: none; stroke: rgba(255,255,255,0.1); stroke-width: 0.4rem; transform-origin: 50% 50%; transform: rotate(-90deg); }
.loading-progress circle:last-child { stroke: var(--gold); stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; transition: stroke-dasharray 0.05s ease-in-out; }
.loading-progress-text { position: absolute; text-align: center; font-weight: 500; inset: calc(20vh + 3.25rem) 0 auto 0; color: #7d7d84; font-family: var(--sans); }
.loading-progress-text:after { content: var(--blazor-load-percentage-text, "Loading"); }

#blazor-error-ui { background: #1a1418; color: #e7cf97; border-top: 1px solid rgba(216,181,107,0.3); bottom: 0; display: none; left: 0; padding: 0.6rem 1.25rem 0.7rem 1.25rem; position: fixed; width: 100%; z-index: 1000; box-shadow: 0 -1px 20px rgba(0,0,0,0.5); }
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; }
