/* ═══════════════════════════════════════════════════════════════
   GREAT WALL OF PORTFOLIOS
   Depends on shared.css tokens and reviews.css.
   ═══════════════════════════════════════════════════════════════ */

.gw-hero { padding: 130px 0 20px; position: relative; overflow: hidden; }
.gw-hero::before {
  content: ''; position: absolute; top: -160px; left: 50%; transform: translateX(-50%);
  width: 1000px; height: 760px; pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(124,92,255,.15) 0%, transparent 66%);
}
.gw-hero::after {
  content: ''; position: absolute; bottom: -80px; right: -100px;
  width: 520px; height: 520px; pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(255, 180, 84,.08) 0%, transparent 64%);
}
.gw-hero-inner { position: relative; z-index: 1; text-align: center; max-width: 720px; margin: 0 auto; }
.gw-title {
  font-family: var(--font-display); font-size: clamp(38px, 6vw, 64px);
  font-weight: 900; color: var(--text-0); letter-spacing: -.03em;
  line-height: 1.02; margin-bottom: 16px;
}
.gw-sub { font-size: 16px; color: var(--text-2); line-height: 1.7; margin-bottom: 12px; }
.gw-cap {
  font-family: var(--font-caption); font-style: italic; font-weight: 700;
  font-size: 13px; color: var(--text-3); line-height: 1.9;
}
.gw-stats { display: flex; justify-content: center; gap: 40px; margin-top: 34px; flex-wrap: wrap; }
.gw-stat-num {
  font-family: var(--font-display); font-size: 30px; font-weight: 900;
  background: var(--grad); -webkit-background-clip: text;
  -webkit-text-fill-color: transparent; background-clip: text; line-height: 1;
}
.gw-stat-lbl { font-size: 11.5px; color: var(--text-3); margin-top: 5px; font-weight: 600; }

/* ── FEATURED ROTATOR ─────────────────────────────────── */
.gw-feature {
  position: relative; border-radius: var(--r-xl); overflow: hidden;
  border: 1px solid var(--border-1); background: var(--bg-1);
  box-shadow: 0 40px 90px rgba(var(--shadow-rgb), .6), 0 0 80px rgba(124,92,255,.07);
  margin-bottom: 18px;
}
.gw-stage { position: relative; aspect-ratio: 21/9; min-height: 300px; }
@media (max-width: 760px) { .gw-stage { aspect-ratio: 4/3; min-height: 340px; } }

.gw-slide {
  position: absolute; inset: 0; opacity: 0; pointer-events: none;
  transition: opacity .8s ease, transform .8s cubic-bezier(.22,.68,0,1);
  transform: scale(1.04);
  display: grid; grid-template-columns: 1.05fr .95fr; align-items: center;
  gap: 40px; padding: 44px 48px;
}
.gw-slide.active { opacity: 1; pointer-events: auto; transform: scale(1); }
@media (max-width: 760px) {
  .gw-slide { grid-template-columns: 1fr; gap: 20px; padding: 26px 22px; align-content: center; }
  .gw-slide .gw-slide-art { display: none; }
}

.gw-slide-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: 100px; margin-bottom: 16px;
  font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
}
.gw-slide-name {
  font-family: var(--font-display); font-size: clamp(24px, 3.4vw, 38px);
  font-weight: 900; color: var(--text-0); letter-spacing: -.025em;
  line-height: 1.08; margin-bottom: 10px;
}
.gw-slide-role { font-size: 14px; color: var(--text-2); margin-bottom: 14px; }
.gw-slide-quote {
  font-family: var(--font-caption); font-style: italic; font-weight: 700;
  font-size: 13px; color: var(--text-3); line-height: 1.9; margin-bottom: 22px;
  max-width: 420px;
}
.gw-slide-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.gw-slide-url {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--violet-ink);
  margin-top: 16px; display: block; word-break: break-all;
}

/* Mini artboard on the right of each slide */
.gw-slide-art {
  position: relative; border-radius: 12px; overflow: hidden;
  aspect-ratio: 4/3; border: 1px solid var(--border-1);
  box-shadow: 0 18px 44px rgba(var(--shadow-rgb), .5);
}
.gw-art-bar {
  height: 26px; display: flex; align-items: center; gap: 5px; padding: 0 10px;
  background: rgba(var(--fg-rgb), .05); border-bottom: 1px solid rgba(var(--fg-rgb), .06);
}
.gw-art-bar i { width: 6px; height: 6px; border-radius: 50%; background: rgba(var(--fg-rgb), .18); }
.gw-art-url {
  flex: 1; height: 10px; margin-left: 6px; border-radius: 3px;
  background: rgba(var(--fg-rgb), .08);
}
.gw-art-body { padding: 14px; display: flex; flex-direction: column; gap: 8px; height: calc(100% - 26px); }
.gw-art-hero { height: 38%; border-radius: 6px; }
.gw-art-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; height: 24%; }
.gw-art-row i { border-radius: 5px; background: rgba(var(--fg-rgb), .07); display: block; }
.gw-art-line { height: 6px; border-radius: 3px; background: rgba(var(--fg-rgb), .09); }
.gw-art-line.short { width: 58%; }

/* Rotator controls */
.gw-dots { display: flex; gap: 7px; justify-content: center; padding: 0 0 20px; }
.gw-dot {
  width: 7px; height: 7px; border-radius: 100px; border: none; padding: 0;
  background: var(--bg-4); cursor: pointer; transition: all .25s;
}
.gw-dot.active { width: 26px; background: var(--violet); }
.gw-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  width: 38px; height: 38px; border-radius: 50%;
  background: rgba(26,28,34,.9); border: 1px solid var(--border-1);
  color: var(--text-1); cursor: pointer; display: grid; place-items: center;
  transition: all .15s; backdrop-filter: blur(8px);
}
.gw-arrow:hover { background: var(--bg-3); color: var(--text-0); border-color: var(--border-2); }
.gw-arrow.prev { left: 14px; }
.gw-arrow.next { right: 14px; }
.gw-arrow svg { width: 15px; height: 15px; }
@media (max-width: 600px) { .gw-arrow { display: none; } }

/* ── PORTFOLIO GRID ───────────────────────────────────── */
.gw-filter { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 26px; }
.gw-chip {
  padding: 8px 16px; border-radius: 100px;
  background: var(--bg-2); border: 1px solid var(--border-1);
  font-family: var(--font-body); font-size: 12.5px; font-weight: 600;
  color: var(--text-2); cursor: pointer; transition: all .13s;
}
.gw-chip:hover { color: var(--text-0); border-color: var(--border-2); }
.gw-chip.active { background: var(--violet); border-color: var(--violet-ink); color: #fff; }

.gw-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 940px) { .gw-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .gw-grid { grid-template-columns: 1fr; } }

/* Each card carries the accent of the profession it belongs to.
   src/great-wall.js sets --gw-accent per card from its ACCENTS table.
   A page of identical near-black rectangles reads as a list however
   good the work inside them is. */
.gw-card {
  --gw-a: var(--gw-accent, #7C5CFF);
  border-radius: var(--r-lg); overflow: hidden; position: relative;
  border: 1px solid var(--border-1);
  background: var(--bg-2);
  background:
    linear-gradient(165deg,
      color-mix(in srgb, var(--gw-a) 11%, var(--bg-2)),
      var(--bg-2) 62%);
  transition: transform .2s, border-color .2s, box-shadow .2s, background .2s;
  text-decoration: none; display: block;
  animation: gw-rise .4s ease backwards;
}
@keyframes gw-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.gw-card::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, var(--gw-a), transparent 76%);
  opacity: .6; z-index: 2; pointer-events: none; transition: opacity .2s;
}
.gw-card:hover::before { opacity: 1; }

.gw-card:hover {
  transform: translateY(-5px) scale(1.014);
  border-color: color-mix(in srgb, var(--gw-a) 55%, transparent);
  box-shadow: 0 18px 40px rgba(var(--shadow-rgb), .45); text-decoration: none;
}
.gw-card-art { aspect-ratio: 16/10; position: relative; overflow: hidden; }
.gw-card-art .gw-art-body { padding: 12px; }
.gw-card-body { padding: 16px 18px 18px; }
.gw-card-badge {
  display: inline-block; padding: 3px 9px; border-radius: 100px;
  font-size: 9.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .07em; margin-bottom: 8px;
  /* --chip is the profession's accent, set inline per card.
     --ink-mix is the theme's: 100% on dark, which leaves the accent
     exactly as it was, and less than that on light, where a colour
     picked to glow on near-black has to be taken down to read on
     paper. One declaration, any accent, including the ones chosen at
     runtime. */
  background: color-mix(in srgb, var(--chip, var(--violet)) 13%, transparent);
  color: color-mix(in srgb, var(--chip, var(--violet)) var(--ink-mix), var(--ink-with));
}
.gw-card-name { font-family: var(--font-display); font-size: 15.5px; font-weight: 800; color: var(--text-0); }
.gw-card-meta {
  font-family: var(--font-caption); font-style: italic; font-weight: 700;
  font-size: 11px; color: var(--text-3); margin-top: 3px;
}
.gw-card-foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-1);
}
.gw-card-url { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gw-card-likes { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-2); flex-shrink: 0; }
.gw-card-likes svg { width: 12px; height: 12px; color: var(--danger); }
.gw-live {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  display: flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 100px; font-size: 9.5px; font-weight: 800;
  background: rgba(11,12,15,.8); border: 1px solid rgba(74,222,128,.35);
  color: var(--success); backdrop-filter: blur(6px);
}
.gw-live i { width: 5px; height: 5px; border-radius: 50%; background: var(--success); }

/* ── HOMEPAGE HIGHLIGHT STRIP ─────────────────────────── */
.gw-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
@media (max-width: 940px) { .gw-strip { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .gw-strip { grid-template-columns: 1fr; } }

.gw-empty {
  grid-column: 1 / -1; text-align: center; padding: 60px 20px;
  font-family: var(--font-caption); font-style: italic; font-weight: 700;
  font-size: 13px; color: var(--text-3); line-height: 1.9;
}

/* ═══════════════════════════════════════════════════════════════
   PORTFOLIO PREVIEWS
   Eight distinct miniature layouts — one per profession — plus the
   person marks that make each tile read as somebody's work rather
   than an empty template.
   ═══════════════════════════════════════════════════════════════ */

/* ── FRAME ──────────────────────────────────────────────── */
.gw-preview {
  position: relative; width: 100%; height: 100%;
  border-radius: 9px; overflow: hidden;
  display: flex; flex-direction: column;
  border: 1px solid rgba(var(--fg-rgb), .07);
}
.gw-chrome {
  height: 20px; flex-shrink: 0;
  display: flex; align-items: center; gap: 4px; padding: 0 8px;
  background: rgba(var(--fg-rgb), .05);
  border-bottom: 1px solid rgba(var(--fg-rgb), .06);
}
.gw-chrome i { width: 4.5px; height: 4.5px; border-radius: 50%; background: rgba(var(--fg-rgb), .2); }
.gw-chrome i:nth-child(1) { background: rgba(255,95,87,.55); }
.gw-chrome i:nth-child(2) { background: rgba(254,188,46,.55); }
.gw-chrome i:nth-child(3) { background: rgba(40,200,64,.5); }
.gw-chrome-url {
  flex: 1; margin-left: 5px;
  font-family: var(--font-mono); font-size: 6.5px; color: rgba(var(--fg-rgb), .32);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gw-preview-body { flex: 1; padding: 10px; min-height: 0; display: flex; }
.gw-preview.large .gw-chrome { height: 26px; }
.gw-preview.large .gw-chrome-url { font-size: 8.5px; }
.gw-preview.large .gw-preview-body { padding: 14px; }

/* Byline — a person's name on their own work. */
.gw-byline {
  position: absolute; left: 8px; bottom: 8px; z-index: 2;
  display: flex; align-items: center; gap: 6px;
  padding: 3px 9px 3px 3px; border-radius: 100px;
  background: rgba(11,12,15,.72); backdrop-filter: blur(8px);
  border: 1px solid rgba(var(--fg-rgb), .08);
}
.gw-byline-av {
  width: 16px; height: 16px; border-radius: 50%;
  display: grid; place-items: center; flex-shrink: 0;
  font-size: 6.5px; font-weight: 800; color: #fff;
}
.gw-byline-name {
  font-size: 8px; font-weight: 700; color: rgba(var(--fg-rgb), .82);
  white-space: nowrap; max-width: 108px; overflow: hidden; text-overflow: ellipsis;
}
.gw-preview.large .gw-byline { left: 12px; bottom: 12px; padding: 4px 12px 4px 4px; }
.gw-preview.large .gw-byline-av { width: 21px; height: 21px; font-size: 8px; }
.gw-preview.large .gw-byline-name { font-size: 10.5px; max-width: 150px; }

.gl { width: 100%; display: flex; flex-direction: column; gap: 6px; min-height: 0; }
.gl-line { height: 4px; border-radius: 2px; background: rgba(var(--fg-rgb), .1); }
.gl-line.w70 { width: 70%; }

/* ── DEVELOPER — terminal with a blinking caret ─────────── */
.gl-term {
  flex: 1; border-radius: 5px; padding: 8px;
  background: rgba(var(--shadow-rgb), .32); border: 1px solid rgba(124,92,255,.16);
  display: flex; flex-direction: column; gap: 5px; justify-content: center;
}
.gl-code { display: flex; gap: 4px; align-items: center; }
.gl-code.in { padding-left: 10px; }
.gl-code .tk { height: 4px; border-radius: 2px; display: block; background: rgba(var(--fg-rgb), .13); width: 38px; }
.gl-code .tk.kw  { width: 20px; background: rgba(124,92,255,.8); }
.gl-code .tk.kw.sm { width: 13px; }
.gl-code .tk.str { width: 34px; background: rgba(255,180,84,.55); }
.gl-code .tk.fn  { width: 26px; background: rgba(74,222,128,.5); }
.gl-caret {
  width: 4px; height: 9px; background: rgba(124,92,255,.9); border-radius: 1px;
  animation: gl-blink 1.1s step-end infinite;
}
@keyframes gl-blink { 0%,100% { opacity: 1; } 50% { opacity: 0; } }
.gl-chips { display: flex; gap: 4px; flex-shrink: 0; }
.gl-chips i {
  height: 9px; flex: 1; border-radius: 100px;
  background: rgba(124,92,255,.2); border: 1px solid rgba(124,92,255,.22);
}

/* ── DESIGNER — overlapping shapes + swatches ───────────── */
.gl-dsg { position: relative; }
.gl-shapes { position: relative; flex: 1; min-height: 40px; }
.sh-circle {
  position: absolute; left: 4px; top: 4px; width: 38px; height: 38px;
  border-radius: 50%; background: rgba(255, 180, 84,.42);
  border: 1px solid rgba(255, 180, 84,.5);
}
.sh-square {
  position: absolute; left: 28px; top: 20px; width: 30px; height: 30px;
  border-radius: 6px; background: rgba(255,180,84,.28);
  border: 1px solid rgba(255,180,84,.36);
}
.gl-swatches { display: flex; gap: 4px; flex-shrink: 0; }
.gl-swatches i { width: 11px; height: 11px; border-radius: 3px; display: block; }
.gl-swatches i:nth-child(1) { background: #FFB454; }
.gl-swatches i:nth-child(2) { background: #7C5CFF; }
.gl-swatches i:nth-child(3) { background: #FFB454; }
.gl-swatches i:nth-child(4) { background: rgba(var(--fg-rgb), .24); }

/* ── PHOTOGRAPHER — a gallery grid ──────────────────────── */
.gl-photos {
  flex: 1; display: grid; gap: 4px; min-height: 0;
  grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 1fr);
}
.gl-photos i { border-radius: 3px; display: block; }
.gl-photos .p1 { grid-column: span 2; grid-row: span 2;
  background: linear-gradient(145deg, rgba(232,200,122,.5), rgba(232,200,122,.14)); }
.gl-photos .p2 { background: linear-gradient(145deg, rgba(var(--fg-rgb), .2), rgba(var(--fg-rgb), .05)); }
.gl-photos .p3 { background: linear-gradient(145deg, rgba(232,200,122,.3), rgba(232,200,122,.08)); }
.gl-photos .p4, .gl-photos .p5 { display: none; }

/* ── DOCTOR — clinical CV with a pulse trace ────────────── */
.gl-cv { display: flex; gap: 8px; align-items: center; flex: 1; min-height: 0; }
.gl-portrait {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center;
  background: rgba(43,181,160,.16); border: 1px solid rgba(43,181,160,.3);
}
.gl-portrait.sm { width: 22px; height: 22px; }
.gl-cred { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.gl-cred i { height: 4px; border-radius: 2px; background: rgba(var(--fg-rgb), .15); display: block; }
.gl-cred i.short { width: 62%; background: rgba(43,181,160,.35); }
.gl-pulse { width: 100%; height: 20px; flex-shrink: 0; display: block; }

/* ── WRITER — pull-quote and prose ──────────────────────── */
.gl-wri { position: relative; }
.gl-quote {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 34px; line-height: .7; height: 20px; flex-shrink: 0;
}
.gl-prose { flex: 1; display: flex; flex-direction: column; gap: 5px; justify-content: center; }
.gl-prose i { height: 4px; border-radius: 2px; background: rgba(var(--fg-rgb), .13); display: block; }
.gl-prose i.w60 { width: 60%; }
.gl-byline { display: flex; align-items: center; gap: 5px; flex-shrink: 0; }
.gl-byline span { height: 4px; width: 44px; border-radius: 2px; display: block; }

/* ── STUDENT — A4 resume, two columns ───────────────────── */
.gl-sheet {
  flex: 1; display: flex; gap: 8px; padding: 8px; min-height: 0;
  background: rgba(var(--fg-rgb), .05); border: 1px solid rgba(74,127,232,.2);
  border-radius: 5px;
}
.gl-col-l {
  flex: 0 0 34%; display: flex; flex-direction: column; gap: 5px; align-items: center;
  border-right: 1px solid rgba(74,127,232,.18); padding-right: 7px;
}
.gl-col-r { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.gl-col-l i, .gl-col-r i { height: 4px; border-radius: 2px; background: rgba(var(--fg-rgb), .14); display: block; width: 100%; }
.gl-col-l i.short { width: 70%; }
.gl-col-r i.head { height: 6px; width: 58%; }
.gl-col-r i.w80 { width: 80%; }
.gl-col-r i.w60 { width: 60%; }

/* ── CREATOR — video thumbnail with a play button ───────── */
.gl-video {
  flex: 1; border-radius: 5px; min-height: 0;
  display: grid; place-items: center;
  border: 1px solid rgba(255,92,92,.22);
}
.gl-play {
  width: 0; height: 0; margin-left: 3px;
  border-left: 13px solid rgba(var(--fg-rgb), .85);
  border-top: 8px solid transparent; border-bottom: 8px solid transparent;
  filter: drop-shadow(0 2px 6px rgba(var(--shadow-rgb), .5));
}
.gl-stats { display: flex; gap: 4px; flex-shrink: 0; }
.gl-stats i {
  height: 9px; flex: 1; border-radius: 3px;
  background: rgba(255,92,92,.2); border: 1px solid rgba(255,92,92,.2);
}

/* ── BUSINESS — service grid and a team row ─────────────── */
.gl-services {
  flex: 1; display: grid; gap: 4px; min-height: 0;
  grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
}
.gl-services i {
  border-radius: 4px; display: block;
  background: rgba(255,180,84,.14); border: 1px solid rgba(255,180,84,.18);
}
.gl-team { display: flex; align-items: center; gap: 3px; flex-shrink: 0; }
.gl-team-line {
  flex: 1; height: 4px; border-radius: 2px; margin-left: 4px;
  background: rgba(var(--fg-rgb), .12);
}
.gw-person-glyph { display: block; flex-shrink: 0; }

/* ── CARD SHELL ─────────────────────────────────────────── */
.gw-card-art {
  aspect-ratio: 16/10; position: relative; overflow: hidden;
  padding: 9px; background: var(--bg-3);
}
.gw-card-art .gw-preview { transition: transform .28s cubic-bezier(.22,.68,0,1); }
.gw-card:hover .gw-card-art .gw-preview { transform: scale(1.045); }

/* Hover invitation — makes the tile read as openable. */
.gw-peek {
  position: absolute; inset: 9px; z-index: 3; border-radius: 9px;
  background: linear-gradient(0deg, rgba(11,12,15,.88), rgba(11,12,15,.25) 55%, transparent);
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 16px;
  opacity: 0; transition: opacity .22s;
}
.gw-peek span {
  font-size: 12px; font-weight: 700; color: #fff;
  background: var(--violet); padding: 7px 15px; border-radius: 100px;
  box-shadow: 0 6px 20px rgba(124,92,255,.5);
  transform: translateY(6px); transition: transform .22s;
}
.gw-card:hover .gw-peek { opacity: 1; }
.gw-card:hover .gw-peek span { transform: translateY(0); }

/* ── CARD BODY — the person, first ──────────────────────── */
.gw-person { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.gw-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 800; color: #fff;
  box-shadow: 0 0 0 2px var(--bg-2), 0 0 0 3px rgba(var(--fg-rgb), .08);
}
.gw-person-text { flex: 1; min-width: 0; }
.gw-card-name {
  font-family: var(--font-display); font-size: 14.5px; font-weight: 800;
  color: var(--text-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gw-card-meta {
  font-family: var(--font-caption); font-style: italic; font-weight: 700;
  font-size: 10.5px; color: var(--text-3); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gw-card-badge { flex-shrink: 0; margin-bottom: 0; align-self: flex-start; }

.gw-live i { width: 5px; height: 5px; border-radius: 50%; background: var(--success); display: block; }

/* ── FEATURED SLIDE ─────────────────────────────────────── */
.gw-slide-art { padding: 0; border: none; box-shadow: 0 18px 44px rgba(var(--shadow-rgb), .5); }
.gw-slide.active .gw-preview { animation: gw-lift .7s cubic-bezier(.22,.68,0,1) both; }
@keyframes gw-lift {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .gl-caret { animation: none; }
  .gw-slide.active .gw-preview { animation: none; }
  .gw-card:hover .gw-card-art .gw-preview { transform: none; }
}

@media (max-width: 600px) {
  .gw-card-name { font-size: 13.5px; }
  .gw-avatar { width: 30px; height: 30px; font-size: 11px; }
}

/* ═══════════════════════════════════════════════════════════════
   PROFESSION LAYOUT CONTAINERS
   great-wall.js generates a distinct miniature layout per profession,
   but six of the eight container classes had no CSS — .gl-dev,
   .gl-pho, .gl-med, .gl-stu, .gl-cre and .gl-biz. Their children
   collapsed to nothing, so those previews rendered as empty boxes.

   These rules give each layout its structure. Every one is built from
   the profession's own accent, and the ones showing people use the
   personGlyph figure so a human is visible on the card.
   ═══════════════════════════════════════════════════════════════ */

/* Shared frame for every layout */
.gl {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column; gap: 7px;
  padding: 10px 11px;
}

/* ── DEVELOPER — terminal, syntax tokens, live caret ────── */
.gl-dev { justify-content: flex-start; }
.gl-dev .gl-term {
  flex: 1; min-height: 0;
  background: rgba(var(--shadow-rgb), .34);
  border: 1px solid rgba(var(--fg-rgb), .07);
  border-radius: 6px; padding: 9px 10px;
  display: flex; flex-direction: column; gap: 6px;
}
.gl-dev .gl-code { display: flex; align-items: center; gap: 5px; }
.gl-dev .gl-code.in { padding-left: 12px; }
.gl-dev .tk { height: 5px; border-radius: 2px; display: block; background: rgba(var(--fg-rgb), .14); }
.gl-dev .tk.kw  { width: 26px; background: #7C5CFF; opacity: .85; }
.gl-dev .tk.kw.sm { width: 14px; }
.gl-dev .tk.str { width: 42px; background: rgba(74,222,128,.55); }
.gl-dev .tk.fn  { width: 32px; background: rgba(255,180,84,.6); }
.gl-dev .gl-code .tk:not(.kw):not(.str):not(.fn) { width: 38px; }
.gl-caret {
  width: 5px; height: 10px; border-radius: 1px;
  background: #7C5CFF; display: block;
  animation: gl-blink 1.1s steps(1) infinite;
}
@keyframes gl-blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
.gl-dev .gl-chips { display: flex; gap: 5px; flex-shrink: 0; }
.gl-dev .gl-chips i {
  height: 11px; flex: 1; border-radius: 100px; display: block;
  background: rgba(124,92,255,.24);
  border: 1px solid rgba(124,92,255,.3);
}

/* ── PHOTOGRAPHER — a gallery wall ──────────────────────── */
.gl-pho { padding: 8px 9px; }
.gl-pho .gl-photos {
  flex: 1; min-height: 0;
  display: grid; gap: 5px;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
}
.gl-pho .gl-photos i { display: block; border-radius: 4px; }
.gl-pho .p1 {
  grid-column: span 2; grid-row: span 2;
  background: linear-gradient(145deg, rgba(232,200,122,.5), rgba(232,200,122,.13));
}
.gl-pho .p2 { background: linear-gradient(145deg, rgba(var(--fg-rgb), .2), rgba(var(--fg-rgb), .05)); }
.gl-pho .p3 { background: linear-gradient(145deg, rgba(232,200,122,.32), rgba(232,200,122,.08)); }
.gl-pho .p4,
.gl-pho .p5 { display: none; }   /* the 2x3 grid is full at three tiles */

/* ── MEDICAL — portrait, credentials, pulse trace ───────── */
.gl-med { gap: 9px; }
.gl-med .gl-cv { display: flex; align-items: center; gap: 9px; flex-shrink: 0; }
.gl-med .gl-portrait {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center;
  background: rgba(43,181,160,.16);
  border: 1px solid rgba(43,181,160,.34);
}
.gl-med .gl-cred { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.gl-med .gl-cred i { height: 5px; border-radius: 2px; display: block; background: rgba(var(--fg-rgb), .16); }
.gl-med .gl-cred i:first-child { width: 70%; background: rgba(43,181,160,.55); height: 6px; }
.gl-med .gl-cred i.short { width: 46%; }
.gl-med .gl-pulse {
  width: 100%; height: 26px; display: block; margin-top: auto;
  stroke-linejoin: round; stroke-linecap: round;
}

/* ── STUDENT — A4 resume, two columns ───────────────────── */
.gl-stu { padding: 9px 10px; }
.gl-stu .gl-sheet {
  flex: 1; min-height: 0;
  background: rgba(var(--fg-rgb), .05);
  border: 1px solid rgba(74,127,232,.24);
  border-radius: 5px; padding: 9px;
  display: flex; gap: 9px;
}
.gl-stu .gl-col-l {
  flex: 0 0 34%;
  border-right: 1px solid rgba(74,127,232,.2);
  padding-right: 8px;
  display: flex; flex-direction: column; gap: 5px; align-items: flex-start;
}
.gl-stu .gl-col-r { flex: 1; display: flex; flex-direction: column; gap: 5px; }
.gl-stu .gl-portrait.sm {
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; margin-bottom: 2px;
  background: rgba(74,127,232,.18);
  border: 1px solid rgba(74,127,232,.36);
}
.gl-stu i { height: 4.5px; border-radius: 2px; display: block; width: 100%; background: rgba(var(--fg-rgb), .14); }
.gl-stu .gl-col-l i.short { width: 62%; }
.gl-stu .gl-col-r i.head { height: 7px; width: 58%; }
.gl-stu .gl-col-r i.w80 { width: 80%; }
.gl-stu .gl-col-r i.w60 { width: 60%; }

/* ── CREATOR — video thumbnail with a play button ───────── */
.gl-cre { gap: 8px; }
.gl-cre .gl-video {
  flex: 1; min-height: 0; border-radius: 6px;
  display: grid; place-items: center; position: relative;
  border: 1px solid rgba(255,92,92,.22);
}
.gl-cre .gl-play {
  width: 0; height: 0; display: block;
  border-left: 15px solid rgba(var(--fg-rgb), .9);
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  margin-left: 4px;
  filter: drop-shadow(0 2px 6px rgba(var(--shadow-rgb), .5));
}
.gl-cre .gl-stats { display: flex; gap: 5px; flex-shrink: 0; }
.gl-cre .gl-stats i {
  flex: 1; height: 12px; border-radius: 3px; display: block;
  background: rgba(255,92,92,.2);
  border: 1px solid rgba(255,92,92,.26);
}

/* ── BUSINESS — service grid and a team row ─────────────── */
.gl-biz { gap: 9px; }
.gl-biz .gl-services {
  flex: 1; min-height: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
}
.gl-biz .gl-services i {
  display: block; border-radius: 5px;
  background: rgba(255,180,84,.14);
  border: 1px solid rgba(255,180,84,.22);
}
.gl-biz .gl-team {
  display: flex; align-items: center; gap: 5px; flex-shrink: 0;
}
.gl-biz .gl-team .gw-person-glyph { flex-shrink: 0; }
.gl-biz .gl-team-line {
  flex: 1; height: 5px; border-radius: 2px; display: block;
  background: rgba(var(--fg-rgb), .13); margin-left: 3px;
}

/* ── Shared human figure ────────────────────────────────── */
.gw-person-glyph { display: block; }

/* Card previews are smaller than the featured slide, so scale down. */
.gw-card-art .gl { padding: 8px 9px; gap: 5px; }
.gw-card-art .gl-dev .gl-term { padding: 7px 8px; gap: 5px; }
.gw-card-art .gl-med .gl-portrait { width: 24px; height: 24px; }
.gw-card-art .gl-med .gl-pulse { height: 20px; }
.gw-card-art .gl-cre .gl-play { border-left-width: 12px; border-top-width: 7px; border-bottom-width: 7px; }
.gw-card-art .gl-biz .gl-team-line { height: 4px; }

@media (prefers-reduced-motion: reduce) {
  .gl-caret { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════
   INTERACTIVE PREVIEWS
   Each miniature now reacts when you hover its card: the element that
   defines that profession is the one that moves. Nothing animates at
   rest, so a wall of twelve cards stays calm until you engage with one.
   ═══════════════════════════════════════════════════════════════ */

.gw-card .gw-preview {
  transition: transform .32s cubic-bezier(.22,.68,0,1);
  transform-origin: center 40%;
}
.gw-card:hover .gw-preview { transform: scale(1.045); }

/* Chrome dots warm up — the site feels "open" rather than a screenshot. */
.gw-card .gw-chrome i { transition: background .25s; }
.gw-card:hover .gw-chrome i:nth-child(1) { background: #FF5F57; }
.gw-card:hover .gw-chrome i:nth-child(2) { background: #FEBC2E; }
.gw-card:hover .gw-chrome i:nth-child(3) { background: #28C840; }

/* ── DEVELOPER — code types itself in ───────────────────── */
.gw-card .gl-dev .tk { transform-origin: left; transition: transform .3s ease; }
.gw-card:hover .gl-dev .gl-code:nth-child(1) .tk { animation: gl-type .34s ease both; }
.gw-card:hover .gl-dev .gl-code:nth-child(2) .tk { animation: gl-type .34s .07s ease both; }
.gw-card:hover .gl-dev .gl-code:nth-child(3) .tk { animation: gl-type .34s .14s ease both; }
@keyframes gl-type { from { transform: scaleX(.2); opacity: .4; } to { transform: scaleX(1); opacity: 1; } }
.gw-card:hover .gl-caret { animation-duration: .5s; }

/* ── DESIGNER — shapes drift apart ──────────────────────── */
.gw-card .gl-dsg .sh-circle,
.gw-card .gl-dsg .sh-square { transition: transform .38s cubic-bezier(.22,.68,0,1); }
.gw-card:hover .gl-dsg .sh-circle { transform: translate(-4px, -3px) rotate(-6deg); }
.gw-card:hover .gl-dsg .sh-square { transform: translate(5px, 3px) rotate(7deg); }
.gw-card .gl-dsg .gl-swatches i { transition: transform .3s ease; }
.gw-card:hover .gl-dsg .gl-swatches i:nth-child(1) { transform: translateY(-3px); }
.gw-card:hover .gl-dsg .gl-swatches i:nth-child(2) { transform: translateY(-3px); transition-delay: .04s; }
.gw-card:hover .gl-dsg .gl-swatches i:nth-child(3) { transform: translateY(-3px); transition-delay: .08s; }
.gw-card:hover .gl-dsg .gl-swatches i:nth-child(4) { transform: translateY(-3px); transition-delay: .12s; }

/* ── PHOTOGRAPHER — the gallery breathes ────────────────── */
.gw-card .gl-pho .gl-photos i { transition: transform .34s ease, filter .34s ease; }
.gw-card:hover .gl-pho .p1 { transform: scale(1.03); filter: brightness(1.15); }
.gw-card:hover .gl-pho .p2 { transform: translateX(2px); transition-delay: .05s; }
.gw-card:hover .gl-pho .p3 { transform: translateX(2px); transition-delay: .1s; }

/* ── MEDICAL — the pulse actually traces ────────────────── */
.gw-card .gl-med .gl-pulse polyline {
  stroke-dasharray: 260; stroke-dashoffset: 0;
}
.gw-card:hover .gl-med .gl-pulse polyline {
  animation: gl-trace 1.1s ease forwards;
}
@keyframes gl-trace {
  from { stroke-dashoffset: 260; }
  to   { stroke-dashoffset: 0; }
}
.gw-card .gl-med .gl-portrait { transition: transform .3s, box-shadow .3s; }
.gw-card:hover .gl-med .gl-portrait {
  transform: scale(1.08);
  box-shadow: 0 0 0 4px rgba(43,181,160,.16);
}

/* ── WRITER — the quote lifts, prose settles ────────────── */
.gw-card .gl-wri .gl-quote { transition: transform .34s cubic-bezier(.22,.68,0,1), opacity .3s; }
.gw-card:hover .gl-wri .gl-quote { transform: translateY(-3px) scale(1.12); opacity: 1; }
.gw-card .gl-wri .gl-prose i { transform-origin: left; transition: transform .3s ease; }
.gw-card:hover .gl-wri .gl-prose i:nth-child(1) { animation: gl-type .3s ease both; }
.gw-card:hover .gl-wri .gl-prose i:nth-child(2) { animation: gl-type .3s .06s ease both; }
.gw-card:hover .gl-wri .gl-prose i:nth-child(3) { animation: gl-type .3s .12s ease both; }

/* ── STUDENT — the sheet lifts off the page ─────────────── */
.gw-card .gl-stu .gl-sheet {
  transition: transform .34s cubic-bezier(.22,.68,0,1), box-shadow .34s;
}
.gw-card:hover .gl-stu .gl-sheet {
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(var(--shadow-rgb), .4);
}
.gw-card .gl-stu .gl-portrait.sm { transition: transform .3s; }
.gw-card:hover .gl-stu .gl-portrait.sm { transform: scale(1.1); }

/* ── CREATOR — play button pulses like a real player ────── */
.gw-card .gl-cre .gl-video { transition: transform .32s; }
.gw-card:hover .gl-cre .gl-video { transform: scale(1.02); }
.gw-card .gl-cre .gl-play { transition: transform .3s cubic-bezier(.22,.68,0,1.4); }
.gw-card:hover .gl-cre .gl-play { transform: scale(1.22); }
.gw-card:hover .gl-cre .gl-video::after {
  content: ''; position: absolute; inset: 0; border-radius: 6px;
  border: 2px solid rgba(var(--fg-rgb), .28);
  animation: gl-ripple 1.3s ease-out infinite;
}
@keyframes gl-ripple {
  from { transform: scale(.86); opacity: .85; }
  to   { transform: scale(1.06); opacity: 0; }
}

/* ── BUSINESS — the team arrives one by one ─────────────── */
.gw-card .gl-biz .gl-team .gw-person-glyph { transition: transform .3s cubic-bezier(.22,.68,0,1.3); }
.gw-card:hover .gl-biz .gl-team .gw-person-glyph:nth-child(1) { transform: translateY(-3px); }
.gw-card:hover .gl-biz .gl-team .gw-person-glyph:nth-child(2) { transform: translateY(-3px); transition-delay: .06s; }
.gw-card:hover .gl-biz .gl-team .gw-person-glyph:nth-child(3) { transform: translateY(-3px); transition-delay: .12s; }
.gw-card .gl-biz .gl-services i { transition: background .28s, border-color .28s; }
.gw-card:hover .gl-biz .gl-services i {
  background: rgba(255,180,84,.22);
  border-color: rgba(255,180,84,.38);
}

/* ── The person behind the work ─────────────────────────── */
.gw-card .gw-byline {
  transition: transform .3s cubic-bezier(.22,.68,0,1), background .3s;
}
.gw-card:hover .gw-byline {
  transform: translateY(-2px);
  background: rgba(11,12,15,.88);
}
.gw-card .gw-avatar { transition: transform .3s cubic-bezier(.22,.68,0,1.3), box-shadow .3s; }
.gw-card:hover .gw-avatar {
  transform: scale(1.08) rotate(-4deg);
  box-shadow: 0 4px 14px rgba(var(--shadow-rgb), .4);
}

/* The featured slide is always "live", so its caret runs at rest. */
.gw-slide.active .gl-caret { animation-duration: .8s; }
.gw-slide.active .gl-med .gl-pulse polyline {
  stroke-dasharray: 260;
  animation: gl-trace 2.4s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .gw-card:hover .gw-preview,
  .gw-card:hover .gl-dsg .sh-circle,
  .gw-card:hover .gl-dsg .sh-square,
  .gw-card:hover .gl-stu .gl-sheet,
  .gw-card:hover .gl-cre .gl-video,
  .gw-card:hover .gl-cre .gl-play,
  .gw-card:hover .gw-avatar,
  .gw-card:hover .gw-byline { transform: none; }
  .gw-card *,
  .gw-slide * { animation: none !important; }
}

/* ── WRITER — denser manuscript: pull-quote, prose, book spines ──
   The original layout put three hairlines in 115px of space, which
   read as an empty box next to the other professions. */
.gl-wri { gap: 8px; }
.gl-wri .gl-pull {
  display: flex; align-items: center; gap: 7px; flex-shrink: 0;
  border-left: 2px solid; padding: 5px 0 5px 8px;
}
.gl-wri .gl-quote {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 26px; line-height: .7; height: 15px; flex-shrink: 0;
}
.gl-wri .gl-pull-line { height: 5px; border-radius: 2px; display: block; flex: 1; }
.gl-wri .gl-pull-line.short { flex: 0 0 26%; }
.gl-wri .gl-prose { display: flex; flex-direction: column; gap: 5px; flex: 1; min-height: 0; }
.gl-wri .gl-prose i {
  height: 4px; border-radius: 2px; display: block; width: 100%;
  background: rgba(var(--fg-rgb), .14);
}
.gl-wri .gl-prose i.w60 { width: 60%; }
.gl-wri .gl-prose i.w80 { width: 80%; }
.gl-wri .gl-books { display: flex; gap: 5px; flex-shrink: 0; height: 26px; }
.gl-wri .gl-books span {
  flex: 1; border-radius: 3px; display: block;
  border: 1px solid rgba(var(--fg-rgb), .08);
}
.gl-wri .gl-byline { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.gl-wri .gl-byline span { height: 4px; border-radius: 2px; display: block; flex: 0 0 44px; }

/* Book spines fan out on hover. */
.gw-card .gl-wri .gl-books span { transition: transform .3s cubic-bezier(.22,.68,0,1.3); }
.gw-card:hover .gl-wri .gl-books span:nth-child(1) { transform: translateY(-3px) rotate(-2deg); }
.gw-card:hover .gl-wri .gl-books span:nth-child(2) { transform: translateY(-4px); transition-delay: .05s; }
.gw-card:hover .gl-wri .gl-books span:nth-child(3) { transform: translateY(-3px) rotate(2deg); transition-delay: .1s; }

/* ── BYLINE CLEARANCE ────────────────────────────────────
   .gw-byline is absolutely positioned at bottom:8px with z-index 2,
   so it was sitting on top of the last row of every layout — the
   business team row and the writer byline both disappeared under it.
   Reserve the space instead of letting them collide. */
.gw-preview-body { padding-bottom: 38px; }
.gw-card-art .gw-preview-body { padding-bottom: 34px; }

/* ── DESIGNER — fill the hollow middle ───────────────────
   .gl-shapes was flex:1 and swallowed 220px while holding only a
   circle and a square. Give it a fixed band and let case-study
   blocks take the remaining space. */
.gl-dsg .gl-shapes { flex: 0 0 auto; height: 52px; position: relative; }
.gl-dsg .gl-cases {
  flex: 1; min-height: 0;
  display: grid; grid-template-columns: 1.35fr 1fr; gap: 6px;
}
.gl-dsg .gl-cases i {
  display: block; border-radius: 5px;
  border: 1px solid rgba(var(--fg-rgb), .07);
}
.gw-card-art .gl-dsg .gl-shapes { height: 42px; }

/* Case blocks part on hover, like cards being dealt. */
.gw-card .gl-dsg .gl-cases i { transition: transform .32s cubic-bezier(.22,.68,0,1); }
.gw-card:hover .gl-dsg .gl-cases i:nth-child(1) { transform: translateY(-3px) rotate(-1deg); }
.gw-card:hover .gl-dsg .gl-cases i:nth-child(2) { transform: translateY(-3px) rotate(1.5deg); transition-delay: .06s; }

/* ── BUSINESS — the team row must stay visible ─────────── */
.gl-biz .gl-team { min-height: 18px; }
.gl-biz .gl-team .gw-person-glyph { width: 15px; height: 15px; }

/* ── FEATURED PREVIEW — keep its height when the slide stacks ──
   Below the two-column breakpoint the preview became a flex child
   with no height of its own and collapsed to a 39px strip, leaving
   the byline sitting on the browser chrome. */
.gw-slide .gw-preview { min-height: 230px; }
.gw-slide .gw-preview-body { min-height: 170px; }
@media (max-width: 760px) {
  .gw-slide .gw-preview { min-height: 200px; }
  .gw-slide .gw-preview-body { min-height: 145px; }
}
@media (max-width: 460px) {
  /* Below this the preview is too small to read; the copy carries it. */
  .gw-slide .gw-preview { display: none; }
}

/* ── STAGE HEIGHT WHEN STACKED ───────────────────────────
   The stage is locked to 4/3 with absolutely-positioned slides, which
   works in the two-column layout. Once the slide stacks, its content
   (copy + buttons + a 200px preview) is taller than that box and the
   name was clipped off the top. Let the stage size to the active slide
   instead; the crossfade is traded for a correct layout. */
@media (max-width: 760px) {
  .gw-stage { aspect-ratio: auto; min-height: 0; height: auto; }
  .gw-slide { position: relative; display: none; transform: none; opacity: 1; }
  .gw-slide.active { display: grid; transform: none; opacity: 1; }
}

/* ── The author's photograph ──────────────────────────────────
   A published portfolio carries its author's Google picture now, so
   the circle beside a card shows the actual person rather than two
   letters on a coloured disc.

   The initials stay in the markup underneath. The image is laid over
   them, so if the CDN 403s or the URL rots, its onerror hides it and
   what was always behind shows through — never a broken-image icon
   and never an empty hole. */
.gw-avatar.has-photo,
.gw-byline-av.has-photo {
  position: relative;
  overflow: hidden;
}
.gw-avatar.has-photo img,
.gw-byline-av.has-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

/* ═══════════════════════════════════════════════════════════════
   THE WALL ITSELF

   The page has always been called the Great Wall and has never had
   one. This is it: small framed rectangles hung at irregular heights,
   drawn low-fidelity so it reads as a gallery wall behind the work
   rather than as content of its own.

   Everything here is painted — no images, no requests. Fixed to the
   viewport rather than the page, so it stays put while the real work
   scrolls over it, the way a wall does behind the person walking past.
   ═══════════════════════════════════════════════════════════════ */

.gw-wall {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* The plaster: a very slight warm tint and a soft vignette, so the
     frames have something to sit on rather than floating in black. */
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(124, 92, 255, .07), transparent 60%),
    radial-gradient(90% 70% at 90% 110%, rgba(255, 180, 84, .05), transparent 60%);
}

.gw-wall i {
  position: absolute;
  display: block;
  border-radius: 2px;
  /* A frame: a hairline edge, a slightly lighter mount inside it, and
     a shadow underneath as though it were hanging off the wall. At
     this size the shadow does most of the work — the border is barely
     a pixel. */
  border: 1px solid rgba(var(--fg-rgb), .05);
  background: linear-gradient(160deg, rgba(var(--fg-rgb), .035), rgba(var(--fg-rgb), .01));
  box-shadow: 0 3px 10px rgba(var(--shadow-rgb), .34);
  opacity: var(--o, .8);

  /* Each frame breathes on its own clock. --t is its period and --y a
     negative delay, so they start mid-cycle and never fall into step:
     a wall where everything pulses together reads as a screen refresh,
     not as a room. Both are written into the markup by
     tools/build-great-wall.js from a fixed seed.

     transform and opacity only — the compositor handles both without
     a layout or a paint, which is what makes ~80 of these free. */
  animation: gw-breathe var(--t, 22s) ease-in-out var(--y, 0s) infinite;
  will-change: transform;
}

@keyframes gw-breathe {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  25%  { transform: translate3d(0.5%, -1.1%, 0) scale(1.035); }
  50%  { transform: translate3d(-0.4%, 0.7%, 0) scale(.985); }
  75%  { transform: translate3d(-0.7%, -0.5%, 0) scale(1.02); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

/* The picture inside the frame — one band and one block, the same
   low-fidelity shorthand the board previews use. Enough to read as a
   picture at a glance and never enough to look at. */
.gw-wall i::before,
.gw-wall i::after {
  content: "";
  position: absolute;
  border-radius: 1px;
  background: rgba(var(--fg-rgb), .05);
}

.gw-wall i::before { left: 16%; right: 16%; top: 20%; height: 12%; }
.gw-wall i::after  { left: 16%; right: 42%; top: 42%; height: 28%; }

/* A few frames catch the light. A wall where nothing stands out is a
   texture; one or two brighter frames make it a wall. Three tints
   rather than two now that there are eighty frames to spread them
   across — at this density two read as stripes. */
.gw-wall i[style*="--d:0"],
.gw-wall i[style*="--d:4"] {
  border-color: rgba(124, 92, 255, .2);
  background: linear-gradient(160deg, rgba(124, 92, 255, .085), rgba(var(--fg-rgb), .012));
}

.gw-wall i[style*="--d:2"] {
  border-color: rgba(255, 180, 84, .17);
  background: linear-gradient(160deg, rgba(255, 180, 84, .07), rgba(var(--fg-rgb), .012));
}


/* A slow sweep of light across the whole wall, like a room where the
   sun moves. One element, one transform — the frames themselves do
   not change, so this costs nothing per frame. */
.gw-wall::after {
  content: "";
  position: absolute;
  inset: -40% -60%;
  background: radial-gradient(closest-side,
    rgba(124, 92, 255, .1), rgba(124, 92, 255, .03) 55%, transparent 78%);
  animation: gw-sweep 48s linear infinite;
  pointer-events: none;
}

@keyframes gw-sweep {
  0%   { transform: translate3d(-22%, -8%, 0); }
  50%  { transform: translate3d(22%, 8%, 0); }
  100% { transform: translate3d(-22%, -8%, 0); }
}

/* Motion is the point of this background, so it is the first thing to
   go. The wall stays — it just stops moving. */
@media (prefers-reduced-motion: reduce) {
  .gw-wall i,
  .gw-wall::after { animation: none; }
}

/* The page's own content sits above the wall. Without this the
   sections would be painted behind it and the whole page would look
   like it was behind glass. */
body > nav,
body > main,
body > section,
body > footer,
body > hr,
/* EVERY FIXED OVERLAY HAS TO BE LISTED HERE.
   `position: relative` on a body-level div does not just change how it
   is positioned — it drops a fixed overlay back into the page flow, so
   it scrolls away and lands wherever the document happens to end.

   Three shipped features were doing exactly that on every page that
   loads this stylesheet: the Open Editor menu opened 28px above the
   viewport, the Free/Pro/Max panel opened a full screen height below
   the fold, and toasts appeared in the middle of the page. All three
   are appended to <body>, and none of them is page content.

   The list, and what each one is:
     .gw-wall    the wall itself, which this rule exists to sit above
     .xam-layer  the drifting motes
     .em-scrim   the Open Editor menu
     .lo-scrim   the Free / Pro / Max panel
     .ht-scrim   the how-to-use walkthrough
     .xt-stack   the toast stack
     .mod-scrim  the "inappropriate language" dialog
     .mod-toast  its warning toast
     .xs-overlay the site search
     .pay-scrim  checkout;  .pub-scrim  publishing
     .xsh-scrim  sharing;   .xet-scrim, .sheet-scrim, .gate-scrim  sheets and gates

   Those seven were missing, and every one of them opened below the
   footer on the home page, the Great Wall and the portfolio page. Any
   element that declares itself a dialog is left alone as well.

   If you add another body-level overlay, add it here too. */
body > div:not(.gw-wall):not(.xam-layer):not(.em-scrim):not(.lo-scrim):not(.ht-scrim):not(.xt-stack):not(.mod-scrim):not(.mod-toast):not(.xs-overlay):not(.pay-scrim):not(.pub-scrim):not(.xsh-scrim):not(.xet-scrim):not(.sheet-scrim):not(.gate-scrim):not([role="dialog"]):not([role="alertdialog"]):not([aria-modal="true"]) {
  position: relative;
  z-index: 1;
}

@media (max-width: 700px) {
  /* Twenty-seven frames on a phone is a busy background behind a
     single column of cards. Half of them is still a wall. */
  .gw-wall i:nth-child(even) { display: none; }
}

/* ═══════════════════════════════════════════════════════════════
   WALL TWO — WEBSITES
   ═══════════════════════════════════════════════════════════════ */

.gw-w-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

.gw-w-card {
  position: relative;
  display: block;
  border: 1px solid var(--border-1, #2A2A34);
  border-radius: 13px;
  overflow: hidden;
  background: var(--bg-2, #14141A);
  text-decoration: none;
  transition: transform .18s, border-color .18s, box-shadow .18s;
}

.gw-w-card:hover {
  transform: translateY(-4px);
  border-color: #7C5CFF;
  box-shadow: 0 18px 44px rgba(var(--shadow-rgb), .45);
}

.gw-w-shot {
  position: relative;
  display: block;
  overflow: hidden;
  background: #fff;
  min-height: 120px;
}

/* The starter preview is a 1600 x 1000 page of absolutely positioned
   elements, scaled by the script to whatever the card turned out to
   be. Nothing inside it is clickable — the card is the link. */
.gw-w-inner {
  position: absolute;
  left: 0;
  top: 0;
  width: 1600px;
  height: 1000px;
  transform-origin: 0 0;
}

.gw-w-shot * { pointer-events: none; }

.gw-w-meta {
  display: block;
  padding: 13px 15px;
  border-top: 1px solid var(--border-1, #2A2A34);
}

.gw-w-meta b {
  display: block;
  font-size: 14.5px;
  font-weight: 700;
  color: var(--text-1, #F5F5F7);
}

.gw-w-meta em {
  display: block;
  margin-top: 3px;
  font-style: normal;
  font-size: 11.5px;
  color: var(--text-3, #8B8D98);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gw-w-flag {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 4px 9px;
  border-radius: 100px;
  background: rgba(61, 220, 132, .9);
  color: #08130D;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* A starter is not somebody's published work and must not be dressed
   as one. */
.gw-w-flag.is-starter {
  background: rgba(17, 17, 20, .85);
  border: 1px solid rgba(var(--fg-rgb), .18);
  color: #C9BCFF;
}

/* ═══════════════════════════════════════════════════════════════
   WALL THREE — RESUMES
   ═══════════════════════════════════════════════════════════════ */

.gw-r-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 18px;
}

.gw-r-card {
  display: block;
  border: 1px solid var(--border-1, #2A2A34);
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-2, #14141A);
  text-decoration: none;
  transition: transform .18s, border-color .18s, box-shadow .18s;
}

.gw-r-card:hover {
  transform: translateY(-4px);
  border-color: #2BB5A0;
  box-shadow: 0 16px 40px rgba(var(--shadow-rgb), .45);
}

/* A4 is 1 : 1.414, and a resume shown at any other ratio is a resume
   somebody will be surprised by when they print it. */
.gw-r-sheet {
  position: relative;
  display: block;
  aspect-ratio: 1240 / 1754;
  overflow: hidden;
  background: #fff;
}

.gw-r-sheet > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.gw-r-meta {
  display: block;
  padding: 11px 13px;
  border-top: 1px solid var(--border-1, #2A2A34);
}

.gw-r-meta b {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-1, #F5F5F7);
}

.gw-r-meta em {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 11px;
  font-weight: 600;
}

.gw-empty {
  padding: 26px;
  border: 1px dashed var(--border-1, #2A2A34);
  border-radius: 12px;
  color: var(--text-3, #8B8D98);
  font-size: 13.5px;
  text-align: center;
}

/* ── Contact details, hidden ───────────────────────────────────
   Every sheet on this wall is a template with invented details, so
   nothing here is anybody real. It is blurred anyway: a wall of
   resumes with legible phone numbers teaches visitors that this is a
   place where such things are on display, and the day a real resume
   meets this renderer the blur wants to be already here rather than
   the thing somebody was going to add.

   Not selectable and not readable by a screen reader either — a blur
   that can be copied out is a decoration, not a redaction. */
.gw-redact {
  filter: blur(3.5px);
  opacity: .72;
  user-select: none;
  pointer-events: none;
  speak: never;
}

.gw-r-card:hover .gw-redact { filter: blur(4.5px); }

@media (prefers-reduced-motion: reduce) {
  .gw-redact { transition: none; }
}
