/* Portfolio Dungeon, project page. Zone `dgn-`, instrument layer. */

/* 1. Shell */

/* Scanlines: hard stops, black at 6%. A CRT texture, not a gradient. */
.dgn-scanlines {
  pointer-events: none;
  position: fixed;
  inset: 0;
  z-index: 0;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 3px,
    rgba(0, 0, 0, 0.06) 3px,
    rgba(0, 0, 0, 0.06) 4px
  );
}
@media (prefers-reduced-motion: reduce) {
  .dgn-scanlines { display: none; }
}

/* Composed from --header-h rather than copying its value. */
.dgn-wrapper {
  position: relative;
  z-index: 1;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-block: calc(var(--header-h) + var(--rhythm-inter)) var(--rhythm-section);
  padding-inline: var(--space-7);
  font-family: var(--type-family-system);
}

@media (max-width: 767px) {
  .dgn-wrapper {
    padding-inline: var(--space-5);
    padding-block-end: var(--rhythm-inter);
  }
}

/* 2. Hero */
.dgn-hero { margin-block-end: var(--rhythm-inter); }

.dgn-banner-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-block-end: var(--rhythm-intra);
}

/* ASCII in --paper, and it scrolls. */
/* width:max-content is what makes the scroll real; block would clip it. */
.dgn-banner {
  display: block;
  width: max-content;
  font-family: var(--type-family-system);
  font-size: var(--type-chrome);
  line-height: 1.25;
  color: var(--text-primary);
  white-space: pre;
  user-select: none;
}

.dgn-hero-labels {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-block-end: var(--space-4);
}

/* Pills are metadata, not active state: no accent, OS radius, never a pill shape. */
.dgn-chip {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
  color: var(--text-meta);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-os);
  padding: var(--space-1) var(--space-3);
}
.dgn-chip--dim {
  color: var(--text-meta);
  border-color: var(--border-default);
  opacity: 0.7;
}

.dgn-tagline {
  font-family: var(--type-family-system);
  font-size: var(--type-chrome);
  color: var(--text-secondary);
  line-height: 1.7;
  max-width: var(--measure);
}

/* Terminal caret: the only legitimate accent in the hero, it signals a state. */
.dgn-cursor::after {
  content: "█";
  color: var(--state-active);
  font-size: 0.9em;
  margin-inline-start: 2px;
  animation: dgn-blink 1s step-end infinite;
}
@keyframes dgn-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .dgn-cursor::after { animation: none; opacity: 1; }
}

/* 3. Sections. Each is an inspection window. */
.dgn-section {
  margin-block-end: var(--rhythm-inter);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-os);
  overflow: hidden;
}

.dgn-section-header {
  background: var(--surface-chrome);
  border-bottom: 1px solid var(--border-default);
  padding: var(--space-3) var(--space-5);
}

/* Command prompt. Blurred halo removed here too. */
.dgn-prompt {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  color: var(--state-active);
  line-height: 1;
}
.dgn-prompt .dgn-user { color: var(--text-meta); }

.dgn-section-body { padding: var(--space-5); }

.dgn-prose {
  font-family: var(--type-family-system);
  font-size: var(--type-chrome);
  color: var(--text-secondary);
  line-height: 1.85;
  max-width: var(--measure);
}
.dgn-prose p + p { margin-block-start: var(--space-4); }
.dgn-prose strong { color: var(--text-primary); font-weight: 500; }

/* Emphasis by weight, not accent. */
.dgn-prose em {
  color: var(--text-primary);
  font-style: normal;
  font-weight: 500;
}

.dgn-how-grid {
  display: grid;
  /* min() not a flat 280: at 375 the section body is 277px. D-218. */
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 0 var(--space-7);
}
.dgn-how-grid .dgn-sub { margin-block-end: 0; padding-block-end: var(--space-6); }

.dgn-sub { margin-block-end: var(--space-6); }
.dgn-sub:last-child { margin-block-end: 0; }

.dgn-sub-prompt {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  color: var(--text-meta);
  margin-block-end: var(--space-4);
  padding-block-end: var(--space-2);
  border-bottom: 1px solid var(--border-default);
}
.dgn-sub-prompt strong { color: var(--text-primary); }

/* 4. Roster. Dense table; it scrolls rather than folding into cards. */
.dgn-roster-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-block-start: var(--space-2);
}

.dgn-roster {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  border-collapse: collapse;
  width: 100%;
  min-width: 580px;
}
.dgn-roster th {
  color: var(--text-meta);
  font-weight: 400;
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
  padding: var(--space-2) var(--space-4) var(--space-2) 0;
  text-align: left;
  border-bottom: 1px solid var(--border-default);
}
.dgn-roster td {
  padding: var(--space-2) var(--space-4) var(--space-2) 0;
  vertical-align: top;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-default);
  line-height: 1.6;
}
.dgn-roster tr:last-child td { border-bottom: none; }

.dgn-roster .td-room    { color: var(--text-meta); padding-right: var(--space-5); }
.dgn-roster .td-name    { color: var(--text-primary); }
.dgn-roster .td-project { color: var(--text-meta); }
.dgn-roster .td-pivot   { color: var(--text-primary); }
.dgn-roster .td-plain   { color: var(--state-disabled); }

/* 5. Equipment and shapes */
.dgn-gear-list {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  list-style: none;
  margin-block-start: var(--space-2);
  padding: 0;
}
.dgn-gear-list li {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--border-default);
  line-height: 1.5;
}
.dgn-gear-list li:last-child { border-bottom: none; }

.dgn-gear-slot {
  color: var(--text-meta);
  /* flex-shrink or the lower bound becomes an upper one and INSPECT gets squeezed. */
  min-width: 52px;
  flex-shrink: 0;
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
}
.dgn-gear-name { color: var(--text-primary); }
.dgn-gear-cond { color: var(--text-meta); }

.dgn-forms-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3);
  margin-block-start: var(--space-3);
}

.dgn-form-card {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-os);
  padding: var(--space-3) var(--space-4);
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  background: var(--surface-base);
}
.dgn-form-card .fc-name {
  color: var(--text-primary);
  letter-spacing: var(--meta-tracking);
  margin-block-end: var(--space-2);
}
.dgn-form-card .fc-stat { color: var(--text-meta); line-height: 1.7; }

/* Trigger and reward were in the game and nowhere on the page. D-204. */
.dgn-form-card .fc-flavor {
  color: var(--text-meta);
  line-height: 1.7;
  margin-block-start: var(--space-1);
}

/* A definition list, because that is what it is. */
.dgn-form-card .fc-meta {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--space-3);
  margin-block-start: var(--space-3);
  padding-block-start: var(--space-2);
  border-top: 1px solid var(--border-default);
}
.dgn-form-card .fc-meta dt {
  color: var(--text-meta);
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
  line-height: 1.7;
}
.dgn-form-card .fc-meta dd {
  margin: 0;
  color: var(--text-secondary);
  line-height: 1.7;
}

/* Le titre est ce qu on emporte : encre pleine, comme le nom de la forme. */
.dgn-form-card .fc-title { color: var(--text-primary); }

/* 6. Credits */
.dgn-credits {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  list-style: none;
  margin-block-start: var(--space-1);
  padding: 0;
}
.dgn-credits li {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--border-default);
  color: var(--text-secondary);
  line-height: 1.6;
}
.dgn-credits li:last-child { border-bottom: none; }

.dgn-credits .cr-key {
  color: var(--text-meta);
  min-width: 100px;
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
  flex-shrink: 0;
}

/* Inline link: third primitive, four states. */
.dgn-credits a {
  color: var(--text-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--motion-state);
}
.dgn-credits a:hover  { color: var(--action-hover); }
.dgn-credits a:active { color: var(--action-pressed); }
.dgn-credits a:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

/* 7. Launch link. Only real CTA on the page. */
.dgn-play-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-block-start: var(--space-1);
  padding: var(--space-3) var(--space-5);
  background: var(--surface-raised);
  border: 1px solid var(--border-accent);
  border-radius: var(--radius-os);
  color: var(--text-accent);
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: var(--elevation-rest);
  transform: translate(0, 0);
  transition:
    box-shadow var(--motion-state),
    transform var(--motion-state),
    background-color var(--motion-state);
}
.dgn-play-link:hover {
  background: var(--action-ghost);
  box-shadow: var(--elevation-hover);
  transform: translate(-1px, -1px);
}
.dgn-play-link:active {
  box-shadow: var(--elevation-pressed);
  transform: translate(3px, 3px);
  transition-duration: var(--dur-press);
}
.dgn-play-link:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

@media (prefers-reduced-motion: reduce) {
  .dgn-play-link:hover,
  .dgn-play-link:active { transform: translate(0, 0); }
}

/* 7. Full width, as a terminal. D-202. */

/* 7.1 Session bar, reusing .win-titlebar. */
.dgn-shell-bar {
  /* Left-flagged: space-between pushed the path to the edge of a 1425px bar. */
  justify-content: flex-start;
  gap: var(--space-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-os);
  margin-block-end: var(--rhythm-intra);
}

.dgn-shell-end {
  font-family: var(--type-family-system);
  font-size: var(--type-meta);
  color: var(--state-active);
  padding-block-start: var(--space-5);
  border-top: 1px solid var(--border-default);
}
/* Prompt path, was a style attribute on three section headers. D-218. */
.dgn-shell-path { color: var(--text-meta); }
.dgn-shell-end .dgn-user { color: var(--text-meta); }

/* 7.2 Hero on one line: stacked, banner and stats left 620px empty. */
@media (min-width: 1300px) {
  .dgn-hero {
    display: grid;
    grid-template-columns: auto minmax(320px, 1fr);
    grid-template-areas:
      'banner labels'
      'banner tagline';
    column-gap: var(--space-7);
    align-items: start;
  }
  .dgn-banner-scroll { grid-area: banner; margin-block-end: 0; }
  .dgn-hero-labels   { grid-area: labels; align-self: end; }
  .dgn-tagline       { grid-area: tagline; }
}

/* 7.3 Top-level prose in two columns, direct child only. */
.dgn-section-body > .dgn-prose {
  max-width: none;
  columns: 2;
  column-gap: var(--space-7);
  column-rule: 1px solid var(--border-default);
  counter-reset: dgn-line;
}

/* A paragraph never breaks across columns. */
.dgn-section-body > .dgn-prose p {
  break-inside: avoid;
  position: relative;
  padding-inline-start: var(--space-6);
  counter-increment: dgn-line;
}
.dgn-section-body > .dgn-prose p:first-child { margin-block-start: 0; }

/* 7.4 Line numbers: the command says cat -n. */
.dgn-section-body > .dgn-prose p::before {
  content: counter(dgn-line, decimal-leading-zero);
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  color: var(--text-meta);
  user-select: none;
}

/* Below 900 the second column gives 40 characters. Back to one. */
@media (max-width: 900px) {
  .dgn-section-body > .dgn-prose { columns: 1; }
}

/* 7.5 Roster and lists fill their column. */
.dgn-gear-list { width: 100%; }

/* 8. Layout pass. D-218. */

/* 8.1 Internal rhythm is a rule, not seven style attributes. */
.dgn-sub > * + * { margin-block-start: var(--space-5); }
/* Prompt keeps its rule and inset but not its margin, or the two add up. */
.dgn-sub .dgn-sub-prompt { margin-block-end: 0; }

/* 8.2 Framed note: hand-copied rgba border replaced by a token. */
.dgn-callout {
  border-left: 2px solid var(--border-accent-soft);
  padding-inline-start: var(--space-4);
}

/* 8.3 Verb list keeps the reading measure; the slot list does not. */
/* Bound dropped: .dgn-split gives it half a block. D-222. */

.dgn-gear-list--relics li {
  display: grid;
  grid-template-columns: max-content max-content minmax(0, 1fr);
  column-gap: var(--space-4);
}

@media (max-width: 640px) {
  /* Three mono columns on a phone give six-character names. */
  .dgn-gear-list--relics li {
    grid-template-columns: max-content minmax(0, 1fr);
  }
  .dgn-gear-list--relics .dgn-gear-cond { grid-column: 2; }
}

/* 8.4 Boss row: active state, the one accent the table allows. */
.dgn-roster tr.is-boss .td-room,
.dgn-roster tr.is-boss .td-name { color: var(--state-active); }
.dgn-roster tr.is-boss .td-pivot { color: var(--text-meta); }

/* 8.5 systems and roster get their width back. */
.dgn-sub--wide { margin-block-end: var(--space-7); }
.dgn-sub--wide:last-child { margin-block-end: 0; }

/* 8.6 · LE LIEN DE FIN. Son ecart vivait dans un div sans classe. */
.dgn-play-wrap { margin-block-start: var(--space-6); }

/* 9. A full-width block fills its width. D-222. */
.dgn-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-5) var(--space-7);
  align-items: start;
}

/* .dgn-sub > * + * targets direct children only, and the column is one. */
.dgn-split-text > * + * { margin-block-start: var(--space-5); }

.dgn-prose--cols {
  max-width: none;
  columns: 2;
  column-gap: var(--space-7);
  column-rule: 1px solid var(--border-default);
}

/* A paragraph never breaks across columns. */
.dgn-prose--cols p { break-inside: avoid; }

/* Below 900 the second column gives 35 characters, half the measure. */
@media (max-width: 900px) {
  .dgn-split { grid-template-columns: minmax(0, 1fr); }
  .dgn-prose--cols { columns: 1; column-rule: none; }
}
