@font-face {
  font-family: 'Akkurat Mono';
  src: url('./src/type/Akkurat-Mono.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'SF Pro Display Regular';
  src: url('./src/type/SF-Pro-Display-Regular.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'SF Pro Display Regular Italic';
  src: url('./src/type/SF-Pro-Display-RegularItalic.otf') format('opentype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'SF Pro Display Medium';
  src: url('./src/type/SF-Pro-Display-Medium.otf') format('opentype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'SF Pro Display Medium Italic';
  src: url('./src/type/SF-Pro-Display-MediumItalic.otf') format('opentype');
  font-weight: 500 ;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'SF Pro Display Bold';
  src: url('./src/type/SF-Pro-Display-Bold.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'SF Pro Display Bold Italic';
  src: url('./src/type/SF-Pro-Display-BoldItalic.otf') format('opentype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

/*
 * Default (dusty pink) scheme. Every one of these is re-written at runtime as
 * the visitor scrolls through a [data-theme] section - see wireSectionThemes()
 * in script.js - so anything that should follow the active scheme must read
 * from these vars rather than hard-coding a color.
 */
:root {
  --medium-neutral: #DFD3D0;
  --light-neutral: #EAE2DC;
  --dark-neutral: #D1B2AA;
  --pale-neutral: #F7F0EC;
  --type: #180602;
  --subtitle-type: #18060285;
  --accent: #D1B2AA;
  --accent-label: rgba(24, 6, 2, 0.66);

  /*
   * Corner scale, outermost -> innermost: 26 / 16 / 8.
   *
   * The nested-corner rule (inner = outer - gap) only binds where the inner
   * element actually sits in the outer one's corner with a uniform gap. In
   * this layout that is just the image-filling-a-card cases and the lightbox,
   * which are derived below. Sub-bentos sit mid-stack inside a bento - title
   * and intro above, value-add below - so their corners never come near the
   * bento's, and the rule does not apply between those two; they only need to
   * step down for hierarchy. 8px also matches the ~6px corner already baked
   * into the before/after screenshot PNGs, so CSS-rounded imagery and the
   * screenshots finally read the same.
   */
  --image-radius: 8px;
}

* { box-sizing: border-box; }

/* --accent is theme-driven (see wireSectionThemes() in script.js), so an
   inline link's color always matches whichever section it's scrolled into */
a, a:visited {
  color: var(--accent);
}

html { background-color: var(--medium-neutral); padding: 0 2rem;}
body { margin: 0; }

#header {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1.5rem;
}

#header .stack {
  margin-block: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

#scrollCue {
    --jelly-stroke-width: 1px;
  --jelly-stroke: var(--dark-neutral);

}
.cue-wrap {
  position: relative;
  display: grid;
  place-items: center;
  isolation: isolate;
  margin-bottom: 2.5rem;   /* moved off #scrollCue, see note */
}

.sonar {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  transition: opacity 400ms ease;
}

.sonar::before,
.sonar::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 10px solid var(--light-neutral);
  animation: sonar 2.4s cubic-bezier(0.2, 0.6, 0.35, 1) infinite;
}

.sonar::after { animation-delay: -1.2s; }
.sonar.is-done { opacity: 0; }

#scrollCue {
  position: relative;
  z-index: 1;
}

@keyframes sonar {
  0%   { scale: 1;    opacity: 0.5; }
  100% { scale: 2.15; opacity: 0;   }
}

@media (prefers-reduced-motion: reduce) {
  .sonar { display: none; }
}

jelly-card {
  --jelly-fill: var(--light-neutral); 
  --jelly-color-border-default: var(--dark-neutral);
  color: var(--type)
}

corner-card, jelly-icon-button {
  --jelly-fill: var(--light-neutral);
  --jelly-color-border-default: var(--dark-neutral);
  color: var(--type);
}

#nameCard {
  width: min(300px, 50vw);
  aspect-ratio: 1.2 / 1;
  --jelly-corners: 50px 180px 100px 50px;   /* TL TR BR BL */
}

#nameCard::part(card) {
  height: 100%; 
  display: flex;
  align-items: center;
  justify-content: center;
}

#nameCard svg { 
  width: 85%; 
  display: block; 
}

#descCard {
  --jelly-fill: transparent; 
  margin-top: 3rem;
  text-align: center;
  --jelly-color-border-default: var(--dark-neutral);
  color: var(--subtitle-type);
  --jelly-radius: 150px;
  font-family: 'Akkurat Mono', monospace;
}

#caseStudy {
  padding-top: 4rem;
    display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1.5rem;
  min-width: 75%;
}

jelly-card h2 {
  font-family: "ogg", sans-serif;
font-weight: 400;
font-style: normal;
font-size: 2rem;
}

/* .project-bento is a plain div (see its rule below), so it has to be named
   here too - it no longer inherits these through the jelly-card selector */
jelly-card p,
.project-bento p {
  font-family: 'SF Pro Display Regular', sans-serif;
font-size: 1rem;
color: var(--type);
opacity: 0.66;
}

jelly-chip {
  font-family: 'Akkurat Mono', monospace;font-weight: 400;
font-style: normal;
font-size: .8rem;
--jelly-fill: var(--light-neutral);
--jelly-label: var(--subtitle-type);
--jelly-stroke-width: 1px;
--jelly-stroke: var(--dark-neutral);

}

/*
 * ---------- project template: logo + chips, then a bento with subsections
 * Reusable per case study - duplicate the .project block (with its own logo,
 * chips and .project-bento content) for each additional project.
 */

.project {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  /*
   * One source of truth for the section's horizontal inset, consumed by both
   * .project-bento and .project-header below so the logo always lines up with
   * the copy inside the card. It can't be set as --jelly-card-padding-inline
   * here: the bento carries size="large", and the component's own
   * :host([size="large"]) declares that variable directly on the element,
   * which beats anything merely inherited from this ancestor.
   */
  --bento-gutter: 30px;
  --bento-radius: 26px;
  --subbento-radius: 16px;
}

.project + .project {
  margin-top: 8rem;
}

.project-header {
  width: min(1400px, 100%);
  padding-inline: var(--bento-gutter);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin: 0 0 2rem;
}

.project-header {
  align-items: flex-end;
}

.project-logo {
  width: clamp(72px, 20%, 160px);
  display: block;
}

.project-logo.showgirl-logo {
  width: clamp(3rem, 26%, 16rem);
  display: block;
}

.project-logo-placeholder {
  width: clamp(72px, 20%, 160px);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px dashed var(--dark-neutral);
  border-radius: var(--image-radius);
  background: var(--light-neutral);
  color: var(--subtitle-type);
  font-family: 'Akkurat Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
}

.project-chips {
  display: flex;
  gap: .5rem;
}

/*
 * A plain panel rather than a jelly-card. A jelly body samples its outline at
 * a fixed 240 points spread evenly by arc length, which is tuned for buttons
 * and normal cards; at this one's ~7900px perimeter a 26px corner receives
 * only ~1.25 of those points, so the bezier drawn through them cuts across
 * the corner instead of following it. Verified against a stock library card
 * with no project CSS: tall renders wonky, short renders clean. The sub-cards
 * inside are far shorter, land well above that threshold, and stay jelly.
 *
 * Values below mirror what jelly-card size="large" was painting: fill, the
 * 1px surface border, --jelly-radius 26px and its padding.
 */
.project-bento {
  width: min(1400px, 100%);
  background: var(--light-neutral);
  border: 1px solid var(--dark-neutral);
  color: var(--type);
  /*
   * One uniform gap on all four sides. The 1px border is a real box now (the
   * jelly one was painted on canvas and took no layout space), so discount it
   * and --bento-gutter stays the true panel-edge -> content distance that
   * .project-header aligns against.
   */
  padding: calc(var(--bento-gutter) - 1px);
  border-radius: var(--bento-radius);
  font: 400 16.5px/1.55 'SF Pro Display Regular', sans-serif;
}

.project-bento > :first-child { margin-top: 0; }
.project-bento > :last-child { margin-bottom: 0; }

.project-about-title {
  margin: 0 0 1rem;
  font-family: 'SF Pro Display Medium', sans-serif;
  font-weight: 500;
  font-size: 2rem;
  line-height: 1.15;
  color: var(--type);
}

.project-intro {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  margin: 0;
}

.project-desc {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
}

.project-cta {
  display: block;
  flex: 0 0 auto;
  width: fit-content;
  margin: 0;
  --jelly-fill: var(--accent);
  --jelly-label: var(--accent-label);
}

@media (max-width: 640px) {
  .project-intro {
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }
}

/* the button shadow root redeclares its own font shorthand, so retarget
   the exposed part rather than the (ineffective) host font-family */
.project-cta::part(button) {
  font-family: 'SF Pro Display Medium', sans-serif;
  font-weight: 500;
}

/*
 * Also a plain panel, for the same sampling reason as .project-bento above -
 * and these carried no squish, so no interaction is lost by dropping the
 * component. The grid can live directly on the element now instead of having
 * to reach the shadow root's .card through ::part.
 */
.reveal-card {
  margin-top: 2.5rem;
  background: var(--pale-neutral);
  border: 1px solid var(--dark-neutral);
  border-radius: var(--subbento-radius);
  padding: 2rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 340px);
  align-items: center;
  gap: 2.5rem;
}

.reveal-media {
  margin: 0;
  aspect-ratio: 1416 / 720;
  cursor: pointer;
  --jelly-fill: transparent;
  --jelly-color-border-default: transparent;
  /* matches .reveal-media-placeholder / .collage-card so every image
     nested in a sub-bento uses the same radius */
  --jelly-radius: var(--image-radius);
  --jelly-card-padding-block: 0;
  --jelly-card-padding-inline: 0;
}

.reveal-media::part(card) {
  position: absolute;
  inset: 0;
  height: 100%;
  padding: 0;
}

.reveal-media .shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transition: opacity 550ms cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}

.reveal-media .shot.is-active { opacity: 1; }

.reveal-side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
}

.reveal-title,
.value-add-title {
  margin: 0;
  font-family: 'SF Pro Display Medium', sans-serif;
  font-weight: 500;
  font-size: 1.75rem;
  line-height: 1.15;
  color: var(--type);
}

.reveal-toggle {
  width: 100%;
  max-width: 240px;
  font-family: 'Akkurat Mono', monospace;
  font-weight: 500;
  --jelly-track: var(--dark-neutral);
  /* pale-neutral, not light-neutral: matches the sub-bento fill, not the
     bento's own - the active chip should read as the same recessed surface */
  --jelly-pill: var(--pale-neutral);
  --jelly-label: var(--subtitle-type);
  --jelly-label-on: var(--type);
}

.reveal-body {
  margin: 0;
}

.value-add {
  margin-top: 2.5rem;
  padding-inline: 0.5rem;
}

.value-add-title {
  font-size: 1.35rem;
  margin-bottom: 0.75rem;
}

.value-add ul {
  margin: 0;
  padding-left: 1.15rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-family: 'SF Pro Display Regular', sans-serif;
  color: var(--type);
  opacity: 0.66;
}

.value-add li::marker { color: var(--dark-neutral); }

.reveal-media-placeholder {
  margin: 0;
  aspect-ratio: 1416 / 720;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px dashed var(--dark-neutral);
  border-radius: var(--image-radius);
  background: var(--light-neutral);
  color: var(--subtitle-type);
  font-family: 'Akkurat Mono', monospace;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
}

/* three plain, flat, unrotated cards cascading top-left -> mid-right ->
   bottom-left, each slightly overlapping the previous - standing in for a
   single flat screenshot. The wide one is sized like the scripted logo. */
.reveal-collage {
  position: relative;
  aspect-ratio: 1;
}

.collage-card {
  position: absolute;
  cursor: pointer;
  /* matches .reveal-media / .reveal-media-placeholder */
  --jelly-radius: var(--image-radius);
  --jelly-fill: var(--light-neutral);
  --jelly-color-border-default: var(--dark-neutral);
}

.collage-card::part(card) {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.collage-placeholder {
  font-family: 'Akkurat Mono', monospace;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--subtitle-type);
  text-align: center;
  padding: 0 1rem;
}

/*
 * A real (flat, un-rounded) photo dropped into any reveal/collage slot -
 * unlike the before/after .shot screenshots, these don't have rounded
 * corners baked into the file, so border-radius does it here instead.
 * Reuse this class for every future placeholder image. 20px is the shared
 * inner radius, matching .reveal-media, .collage-card and the placeholder
 * boxes - one step in from the 24px sub-bento that contains them.
 */
.reveal-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--image-radius);
  cursor: pointer;
}

.collage-card--top-left {
  width: 50%;
  aspect-ratio: 1;
  top: 0;
  left: 0;
  z-index: 1;
}

.collage-card--mid-right {
  width: 56%;
  aspect-ratio: 16 / 9;
  top: 27%;
  left: 44%;
  z-index: 2;
}

.collage-card--bottom-left {
  width: 50%;
  aspect-ratio: 1;
  top: calc(50% + 5px);
  left: 13%;
  z-index: 3;
}

@media (max-width: 900px) {
  .project {
    --bento-gutter: 20px;
  }

  /* padding and radius both derive from --bento-gutter above, so the uniform
     gap and the nested-corner rule hold at this breakpoint automatically */

  /* imagery on top, then (if present) the toggle, title and body */
  .reveal-card {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.25rem;
    padding: 1.5rem;
    margin-top: 1.75rem;
  }
}

@media (max-width: 480px) {
  /*
   * Horizontal insets nest html -> #caseStudy -> bento -> sub-bento, and they
   * had drifted to four different widths (16 / 24 / 20 / 18.4px) that ate 157px
   * of a 390px viewport. Now every level is the same 1rem step and the
   * redundant one is gone: html already owns the outer gutter, so #caseStudy
   * contributes none. .project-header keeps reading the same variable as the
   * bento's inner padding, so the logo still lines up with the copy below it.
   */
  html { padding: 0 1rem; }

  #caseStudy {
    padding-inline: 0;
    padding-top: 2.5rem;
  }

  .project { --bento-gutter: 1rem; }

  .reveal-card {
    padding: 1rem;
    gap: 1rem;
  }

  .value-add { padding-inline: 0; }

  /* logo holds the left, chips stack into right-justified rows beside it */
  .project-header {
    gap: 0.75rem;
    margin-bottom: 1.25rem;
  }

  .project-logo,
  .project-logo-placeholder {
    flex: 0 0 auto;
    width: clamp(104px, 44%, 160px);
  }

  .project-logo.showgirl-logo {
    flex: 0 0 auto;
    width: clamp(124px, 50%, 16rem);
  }

  .project-chips {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.35rem;
  }

  jelly-chip {
    height: 28px;
    font-size: 0.7rem;
  }

  /* the chip's inner padding is hardcoded at 17px, so trim it through the
     exposed part to fit more chips per row */
  jelly-chip::part(main) { padding-inline: 11px; }

  #lightbox {
    --jelly-dialog-padding: 16px;
  }

  .lightbox-img {
    max-height: min(58vh, 640px);
  }
}

/* ---------- lightbox ---------- */

#lightbox {
  --jelly-dialog-width: min(1300px, 94vw);
  --jelly-dialog-padding: 20px;
  --jelly-color-background-surface: var(--pale-neutral);
  --jelly-shadow-overlay: none;
  /*
   * Here the nested-corner rule really does bind: the image spans the dialog's
   * full content width flush against the top, so its corners sit exactly one
   * padding in from the dialog's. Derived from the same two values, so it
   * stays correct when the padding drops to 16px on mobile.
   */
  --jelly-dialog-radius: calc(var(--image-radius) + var(--jelly-dialog-padding));
}

.lightbox-media {
  margin: 0 0 1.25rem;
  display: flex;
  justify-content: center;
}

.lightbox-img {
  max-width: 100%;
  max-height: min(78vh, 900px);
  border-radius: var(--image-radius);
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

/* .lightbox-img / .lightbox-placeholder both set an explicit display, which
   (being author-origin) beats the UA [hidden]{display:none} rule at equal
   specificity - same fix as #lightboxToggle[hidden] below */
.lightbox-img[hidden],
.lightbox-placeholder[hidden] {
  display: none;
}

.lightbox-toggle {
  display: flex;
  margin: 0 auto;
}

/* jelly-segmented's own :host{display:inline-flex} is author-origin, so it
   beats the UA [hidden]{display:none} rule on specificity ties - same class
   of fix as the font-weight override above, just for display this time */
#lightboxToggle[hidden] {
  display: none;
}

.lightbox-placeholder {
  width: min(600px, 100%);
  aspect-ratio: 3 / 2;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px dashed var(--dark-neutral);
  border-radius: var(--image-radius);
  background: var(--light-neutral);
  color: var(--subtitle-type);
  font-family: 'Akkurat Mono', monospace;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
}

.lightbox-counter {
  margin: 0.75rem 0 0;
  text-align: center;
  font-family: 'Akkurat Mono', monospace;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--subtitle-type);
}

/* ---------- closing section: full-screen CTA, default scheme only ---------- */

#footer {
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.footer-cta {
  --jelly-fill: var(--accent);
  --jelly-label: var(--accent-label);
}

/* same fix as .project-cta: the button shadow root redeclares its own font
   shorthand, so retarget the exposed part rather than the host font-family */
.footer-cta::part(button) {
  font-family: 'SF Pro Display Medium', sans-serif;
  font-weight: 500;
  font-size: 1.15rem;
}

