/* =====================================================================
   cards.css — SHARED STYLES
   ---------------------------------------------------------------------
   Shared styles:
 colors, the project card, the enlarged flip view, the photo
 carousel, and loading/error states.
   Section layouts live in showcase.css and featured.css.
   ===================================================================== */

/*
  COLOR + STYLE VARIABLES
  These are reused everywhere below as var(--name).
  Change a color here and it updates across the whole page.
  --accent is the burnt orange used for buttons, labels, and highlights.
*/
:root {
  color-scheme: light;
  --accent: #c05a2b;
  --accent-light: #e4ae94;
  --accent-bg: #fff5ef;
  --accent-contrast: #ffffff;
  --ink: #1f2933;
  --ink-soft: #5f6366;
  --ink-faint: #7a7f82;
  --line: #e3e6ea;
  --panel: #ffffff;
  --page-bg: #f4f5f7;
  --surface-muted: #f6f7f9;
  --control-bg: #ffffff;
  --control-border: #d5d9de;
  --surface-hover: #f3e9e3;
  --header-bg: rgba(255, 255, 255, 0.92);
  --header-border: #e3e6ea;
  --tag-bg: #f6dfd2;
  --tag-ink: #9b431f;
  --body-copy: #444444;
  --photo-bg: #e9e9e6;
  --stripe-a: #f0f0f0;
  --stripe-b: #e9e9e9;
  --empty-bg: #f9f9f9;
  --error-bg: #fff5ef;
  --error-border: #e4ae94;
  --error-ink: #843b20;
  --page-background:
    radial-gradient(ellipse at 50% -12%, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.5) 28%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(180deg, #fafbfc 0%, var(--page-bg) 60%, #eef0f3 100%);
  /* Brand fonts: used if installed on the visitor's device, else the fallbacks */
  --font-body: "Gotham Book", Gotham, Montserrat, "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
  --font-heading: "Myriad Pro", "Myriad Pro Regular", Myriad, "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
  --font-serif: "Minion Pro", "Minion Pro Regular", Minion, Georgia, "Times New Roman", serif;
  --radius: 14px;
  --card-pad: 22px; /* inner spacing of each card face */
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --accent: #f08a58;
  --accent-light: #96664e;
  --accent-bg: #35271f;
  --accent-contrast: #1b211d;
  --ink: #edf2ee;
  --ink-soft: #c2ccc5;
  --ink-faint: #9ba79f;
  --line: #46514a;
  --panel: #252e29;
  --page-bg: #1a211d;
  --surface-muted: #202824;
  --control-bg: #29322d;
  --control-border: #566259;
  --surface-hover: #39443d;
  --header-bg: rgba(32, 40, 36, 0.92);
  --header-border: #46514a;
  --tag-bg: #49352b;
  --tag-ink: #f2b28b;
  --body-copy: #d9e0db;
  --photo-bg: #151a17;
  --stripe-a: #252d28;
  --stripe-b: #303a33;
  --empty-bg: #222a25;
  --error-bg: #382722;
  --error-border: #83533c;
  --error-ink: #f0b48f;
  --page-background:
    radial-gradient(ellipse at 50% -12%, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 28%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(180deg, #252d29 0%, var(--page-bg) 48%, #151b17 100%);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  background: var(--page-background);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}

body {
  padding: 0;
  overflow-x: clip; /* full-bleed sections use 100vw, which includes the scrollbar */
}

button, input, select, textarea { font-family: inherit; }

h1, h2, h3, .card-title, .site-title, .featured-title { font-family: var(--font-heading); }

.featured-sub, .card-desc { font-family: var(--font-serif); }

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}


/* =========================================================
 CARDS IN THE GRID
 ---------------------------------------------------------
 A grid card only shows its FRONT (photo, tags, title,
 overview, scope). The card is exactly as tall as that
 content — no fixed heights. Clicking it opens the
 enlarged, flipped view described in the next section.
 ========================================================= */

.card {
  display: flex; /* lets the front stretch to the row's height */
  cursor: pointer;
  animation: cardIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.card:nth-child(2) { animation-delay: 0.04s; }
.card:nth-child(3) { animation-delay: 0.08s; }
.card:nth-child(4) { animation-delay: 0.12s; }
.card:nth-child(5) { animation-delay: 0.16s; }
.card:nth-child(6) { animation-delay: 0.2s; }
.card:nth-child(7) { animation-delay: 0.24s; }
.card:nth-child(8) { animation-delay: 0.28s; }
.card:nth-child(9) { animation-delay: 0.32s; }

@keyframes cardIn {
  from { opacity: 0; transform: translateY(16px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.card.is-hidden { display: none !important; }

/* While a card is open in the enlarged view, its spot in the
   grid is kept (so nothing shifts) but made invisible. */
.card.is-open { visibility: hidden; }

.card-inner {
  flex: 1;
  min-width: 0; /* never wider than the card, even with long tags */
  position: relative;
}

.card-face {
  height: 100%;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 4px 14px rgba(16, 24, 40, 0.05);
  padding: var(--card-pad);
  overflow: hidden; /* clips the photo to the card's rounded corners */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  position: relative;
  transition: box-shadow 0.3s ease, transform 0.3s ease, border-color 0.3s ease;
}

.card-face::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s ease;
  z-index: 1;
}

.card:hover .card-face {
  box-shadow: 0 16px 36px rgba(16, 24, 40, 0.14);
  transform: translateY(-3px);
  border-color: var(--accent-light);
}

.card:hover .card-face::before { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .card { animation: none; }
  .card:hover .card-face { transform: none; }
}


/* =========================================================
 ENLARGED FLIP VIEW
 ---------------------------------------------------------
 What happens when you click a card:

   1. A full-screen .card-overlay fades in. Its
      "backdrop-filter: blur()" blurs the whole page behind it.

   2. A copy of the card (.expanded-card) is placed exactly
      on top of the original, using "position: fixed" and the
      original's on-screen position and size.

   3. Its top/left/width/height are then changed to a big
      centered box. Because those four properties have a
      "transition", the browser animates the card growing
      and gliding to the middle of the screen.

   4. At the same time the class "flipped" is added, which
      rotates .card-inner 180° (a 3D flip) to show the back.

 Closing does the same thing in reverse: it flips back to
 the front while shrinking into its original spot, then the
 copy is removed.

 How the flip works inside .expanded-card:
   .card-inner    the part that rotates; "preserve-3d" keeps
                  both faces in 3D space
     .card-front  a copy of the grid card's front
     .card-back   the details, pre-rotated 180° to face away
 "backface-visibility: hidden" makes whichever face is
 turned away invisible.

 The enlarged size is worked out in JavaScript so the back
 fits all of its text (see openCard()).
 ========================================================= */

.card-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(20, 18, 18, 0.35);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  transition: opacity 0.45s ease;
  cursor: pointer;
}

.card-overlay.show { opacity: 1; }

.expanded-card {
  position: fixed;
  z-index: 60;
  perspective: 10000px;
  perspective-origin: center center;
  cursor: pointer;
  transition:
    top 0.30s cubic-bezier(0.45, 0, 0.55, 1),
    left 0.30s cubic-bezier(0.45, 0, 0.55, 1),
    width 0.30s cubic-bezier(0.45, 0, 0.55, 1),
    height 0.30s cubic-bezier(0.45, 0, 0.55, 1);
  will-change: top, left, width, height;
}

/* The enlarged card gets keyboard focus (for screen readers and
   the Escape key) but shouldn't draw a focus outline around it. */
.expanded-card:focus { outline: none; }

.expanded-card .card-inner {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform-origin: center center;
  transition: transform 0.3s cubic-bezier(0.45, 0, 0.55, 1);
  will-change: transform;
}

.expanded-card.flipped .card-inner { transform: rotateY(180deg); }
.expanded-card.flipped .card-front { pointer-events: none; }

.expanded-card .card-face {
  position: absolute;
  inset: 0;
  height: auto;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.28);
}

/* Only the back casts the big shadow, and it sits a hair in
   front of the front face so no edge of the front peeks
   around its corners when flipped. */
.expanded-card .card-front { box-shadow: none; }

.card-back {
  transform: rotateY(180deg);
  background: var(--panel);
  border-color: var(--accent-light);
  padding: 44px;
  overflow: hidden;
  scrollbar-gutter: stable;
}

.back-content {
  --detail-scale: 1;
  transform-origin: top left;
  max-width: 100%;
  display: block;
}

.expanded-card .card-back > * {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.18s ease;
}

.expanded-card.settled .card-back > * {
  opacity: 1;
  visibility: visible;
}

/* =========================================================
 CARD TEXT
 ========================================================= */

.card-title {
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 12px 0;
  line-height: 1.25;
}

.flip-title {
  display: inline;
  border: none;
  background: transparent;
  padding: 0;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}

.flip-title:hover {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.flip-hint {
  display: block;
  margin-top: 5px;
  color: var(--ink-faint);
  font-size: 12px;
  font-weight: 500;
}

.header-tags {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 14px;
  flex-wrap: wrap;
  gap: 8px;
}

.cat-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.cat-tag {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  background: var(--tag-bg);
  color: var(--tag-ink);
  font-size: 11px;
  font-weight: 600;
  padding: 4px 9px;
  border-radius: 4px;
  text-transform: uppercase;
  white-space: nowrap;
}

.maker-tag {
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 600;
}

.card-desc {
  color: var(--body-copy);
  font-size: 15px;
  line-height: 1.6;
  margin: 0 0 14px;
}

.section-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  margin-top: 14px;
  margin-bottom: 6px;
}

.section-text {
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.6;
  white-space: pre-line; /* preserves CSV project line breaks */
}

.scope-text {
  font-size: 16px;
  line-height: 1.55;
}

@media (min-width: 1001px) {
  .project-grid .carousel-container,
  .project-grid .no-photo { aspect-ratio: 5 / 4; }

  .project-grid .card-front > .section-label,
  .project-grid .card-front .scope-text { display: none; }

  .project-grid .card-front .card-desc {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
  }
}


/* =========================================================
 BACK OF CARD (enlarged view)
 ---------------------------------------------------------
 Title and maker across the top, then two columns:
   left:  Materials + Outcome
   right: Fabrication Steps (usually the longest)
 On narrow screens the columns stack into one.
 ========================================================= */

.back-header { margin-bottom: 24px; }

.back-title {
  font-size: calc(34px * var(--detail-scale));
  font-weight: 700;
  color: var(--accent);
  margin: 0 0 4px;
}

.back-meta {
  color: var(--ink-soft);
  font-size: calc(17px * var(--detail-scale));
  font-weight: 600;
  margin: 0 0 6px;
}

.back-hint {
  color: var(--ink-faint);
  font-size: calc(15px * var(--detail-scale));
  margin: 0;
}

.back-close {
  margin-top: 12px;
  padding: 8px 12px;
  border: 1px solid var(--accent-light);
  border-radius: 6px;
  background: var(--accent-bg);
  color: var(--accent);
  font: inherit;
  font-size: calc(16px * var(--detail-scale));
  font-weight: 600;
  cursor: pointer;
}

.back-close:hover {
  background: var(--accent);
  color: var(--accent-contrast);
}

.back-columns {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 28px;
}

.back-section { margin-bottom: 22px; }
.back-section:last-child { margin-bottom: 0; }
.back-section .section-label { margin-top: 0; }
.card-back .section-text {
  font-size: calc(18px * var(--detail-scale));
  line-height: calc(1.6 * var(--detail-scale));
}

.back-empty {
  color: var(--ink-faint);
  font-style: italic;
}

@media (max-width: 700px) {
  .back-columns { grid-template-columns: 1fr; gap: 22px; }
  .card-back { padding: 22px; }
  .back-title { font-size: 22px; }
}


/* =========================================================
 IMAGE CAROUSEL
 ---------------------------------------------------------
 How the photo fits into the card:

   - EDGE TO EDGE: the frame uses negative margins equal to
     the card's padding, so it runs right to the card's edges
     and top, with only the top corners rounded. It reads as
     part of the card instead of a box sitting inside it.

   - NOTHING CROPPED: each photo uses "object-fit: contain",
     so the whole image is always visible.

   - NO GRAY BARS: behind the photo sits a blurred, zoomed-in
     copy of the same photo (.carousel-backdrop). Any space the
     photo doesn't cover is filled with its own soft colors,
     so it blends in smoothly whatever shape the photo is.

 To change the frame's shape, edit aspect-ratio below
 (1 / 1 = square, 4 / 3 = wider, 4 / 5 = taller).
 ========================================================= */

.carousel-container,
.no-photo {
  aspect-ratio: 1 / 1;
  width: calc(100% + 2 * var(--card-pad));
  margin: calc(-1 * var(--card-pad)) calc(-1 * var(--card-pad)) 20px;
  border-radius: var(--radius) var(--radius) 0 0;
}

.carousel-container {
  position: relative;
  overflow: hidden;
  background: var(--photo-bg);
}

/* Blurred copy of the photo that fills the frame behind it */
.carousel-backdrop {
  position: absolute;
  inset: -30px;              /* oversized so blur has no soft edges */
  background-size: cover;
  background-position: center;
  filter: blur(24px) saturate(1.1) brightness(0.92);
  transition: background-image 0.2s;
}

.carousel-slide {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: none;
  transition: transform 0.5s ease;
}

.carousel-slide.active { display: block; }

.card:hover .carousel-slide.active { transform: scale(1.045); }

@media (prefers-reduced-motion: reduce) {
  .card:hover .carousel-slide.active { transform: none; }
}

.carousel-btn {
  position: absolute;
  z-index: 2;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  border: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  cursor: pointer;
  font-weight: bold;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.carousel-btn:hover { background: rgba(0, 0, 0, 0.85); }
.carousel-btn.prev { left: 10px; }
.carousel-btn.next { right: 10px; }

.carousel-dots {
  position: absolute;
  bottom: 10px;
  width: 100%;
  display: flex;
  justify-content: center;
  gap: 6px;
  z-index: 2;
  padding: 0;
  margin: 0;
  list-style: none;
}

.dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  background: rgba(255, 255, 255, 0.5);
  border-radius: 50%;
  cursor: pointer;
}

.dot.active { background: #fff; }


/* =========================================================
 NO PHOTO
 ========================================================= */

.no-photo {
  background: repeating-linear-gradient(45deg, var(--stripe-a), var(--stripe-a) 10px, var(--stripe-b) 10px, var(--stripe-b) 20px);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  padding: 8px;
}


/* =========================================================
 STATES
 ========================================================= */

.loading,
.no-results {
  grid-column: 1 / -1;
  font-size: 15px;
  color: var(--ink-soft);
  padding: 40px 10px;
  text-align: center;
}

.empty-state {
  grid-column: 1 / -1;
  color: var(--ink-soft);
  padding: 40px 10px;
  text-align: center;
}

.no-results {
  background: var(--empty-bg);
  border: 1px dashed var(--line);
  border-radius: 8px;
  display: none;
  width: 100%;
}

.no-results button { margin-top: 10px; }

.error-state {
  grid-column: 1 / -1;
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  color: var(--error-ink);
  border-radius: 8px;
  padding: 16px;
}


/* =========================================================
 REDUCED MOTION
 ---------------------------------------------------------
 Users who've turned on "reduce motion" in their OS get an
 instant flip instead of the rotation animation.
 ========================================================= */

