/* ==========================================================================
   HOB — Harry O. Bear
   Core stylesheet. One file, token driven.
   Palette : obsidian / graphite / ivory / brass / slate
   Type    : Archivo (display, expanded) · IBM Plex Sans (body) · IBM Plex Mono (registry data)
   ========================================================================== */

/* --- 1. Tokens ----------------------------------------------------------- */

:root {
  --obsidian:  #0B0B0C;
  --graphite:  #17181A;
  --graphite-2:#202225;
  --ivory:     #F4F3EF;
  --ivory-dim: #DCDAD3;
  --brass:     #B98A3E;
  --brass-lit: #D7A954;
  --slate:     #8A8C90;
  --slate-dim: #5C5E62;

  --display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --body:    "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --gut:  clamp(1.25rem, 4vw, 3.5rem);   /* page gutter */
  --stack: clamp(4.5rem, 10vw, 9rem);    /* vertical rhythm between sections */
  --measure: 62ch;

  --hair: rgba(244, 243, 239, 0.12);
  --hair-ink: rgba(11, 11, 12, 0.14);

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in:  cubic-bezier(0.55, 0, 1, 0.45);
}

/* --- 2. Reset ------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Ground moved off <body> so the cursor-wave canvas (z-index -1) is visible
     behind the page instead of being painted over. */
  background: var(--obsidian);
}

body {
  margin: 0;
  background: transparent;
  color: var(--ivory);
  font-family: var(--body);
  font-size: clamp(1rem, 0.94rem + 0.28vw, 1.0625rem);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--brass-lit);
  outline-offset: 3px;
}

::selection { background: var(--brass); color: var(--obsidian); }

/* --- 3. Type ------------------------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  font-stretch: 112%;
  line-height: 1.04;
  letter-spacing: -0.018em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: clamp(2.5rem, 1.4rem + 4.8vw, 5.25rem); }
h2 { font-size: clamp(1.9rem, 1.3rem + 2.5vw, 3.25rem); }
h3 { font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.6rem); font-stretch: 106%; }
h4 { font-size: 1.0625rem; font-stretch: 104%; letter-spacing: -0.005em; }

p { margin: 0 0 1.1em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: clamp(1.0625rem, 0.98rem + 0.5vw, 1.3125rem);
  line-height: 1.55;
  color: var(--ivory-dim);
  max-width: 48ch;
}

.eyebrow {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 1.5rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--hair);
}

.muted { color: var(--slate); }

/* --- 4. Layout ----------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: var(--gut);
}

.section { padding-block: var(--stack); }
.section--tight { padding-block: calc(var(--stack) * 0.62); }

.section--light {
  background: var(--ivory);
  color: var(--obsidian);
}
.section--light .eyebrow { color: #8A6427; }
.section--light .eyebrow::after { background: var(--hair-ink); }
.section--light .lede { color: #3A3B3D; }
.section--light .muted { color: #62646A; }

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 5rem);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .split { grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); align-items: start; }
  .split--even { grid-template-columns: 1fr 1fr; }
}

.rule {
  height: 1px;
  background: var(--hair);
  border: 0;
  margin: 0;
}
.section--light .rule { background: var(--hair-ink); }

/* --- 5. Header ----------------------------------------------------------- */

.masthead {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(11, 11, 12, 0.78);
  backdrop-filter: blur(14px) saturate(120%);
  border-bottom: 1px solid var(--hair);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 68px;
}

.brandmark {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  flex-shrink: 0;
}
.brandmark img { height: 30px; width: auto; }
.brandmark span {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--slate);
  display: none;
}
@media (min-width: 620px) { .brandmark span { display: inline; } }

.nav { display: none; }
@media (min-width: 920px) {
  .nav { display: flex; align-items: center; gap: 2.1rem; }
}
.nav a {
  text-decoration: none;
  font-size: 0.875rem;
  letter-spacing: 0.005em;
  color: var(--ivory-dim);
  padding-block: 0.4rem;
  position: relative;
  transition: color 0.25s var(--ease-out);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.32s var(--ease-out);
}
.nav a:hover { color: var(--ivory); }
.nav a:hover::after,
.nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--ivory); }

.navtoggle {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 44px;                       /* tap target floor, WCAG 2.5.5 */
  min-height: 44px;
  margin-right: -8px;                    /* keeps the bars where they sat */
  padding: 0;
}
@media (min-width: 920px) { .navtoggle { display: none; } }
.navtoggle i {
  display: block;
  width: 22px;
  height: 1.5px;
  background: var(--ivory);
  transition: transform 0.3s var(--ease-out), opacity 0.2s linear;
}
.navtoggle[aria-expanded="true"] i:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.navtoggle[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.navtoggle[aria-expanded="true"] i:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.drawer {
  display: none;
  border-top: 1px solid var(--hair);
  background: var(--obsidian);
}
.drawer[data-open="true"] { display: block; }
@media (min-width: 920px) { .drawer { display: none !important; } }
.drawer a {
  display: block;
  padding: 1rem 0;
  text-decoration: none;
  font-family: var(--display);
  font-stretch: 108%;
  font-size: 1.35rem;
  border-bottom: 1px solid var(--hair);
}
.drawer a:last-child { border-bottom: 0; }

/* --- 6. Hero ------------------------------------------------------------- */

.hero {
  position: relative;
  padding-block: clamp(3.5rem, 9vw, 7rem) clamp(2.5rem, 6vw, 4.5rem);
  overflow: hidden;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 80% at 78% 8%, rgba(185, 138, 62, 0.13), transparent 62%),
    radial-gradient(90% 70% at 8% 92%, rgba(244, 243, 239, 0.05), transparent 60%);
  pointer-events: none;
}

.hero__inner { position: relative; }

.hero__mark {
  width: min(78vw, 620px);
  height: auto;
  margin: 0 0 clamp(2rem, 5vw, 3.4rem);
  opacity: 0;
  transform: translateY(18px);
  animation: rise 1s var(--ease-out) 0.1s forwards;
}

.hero h1 { max-width: 17ch; }
.hero h1 em {
  font-style: normal;
  color: var(--brass-lit);
}

.hero .lede { margin-top: 1.6rem; }

.hero__meta {
  margin-top: clamp(3rem, 7vw, 5rem);
  padding-top: 1.4rem;
  border-top: 1px solid var(--hair);
  display: grid;
  gap: 1.4rem 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
}
.hero__meta div { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; }
.hero__meta dt {
  color: var(--slate-dim);
  text-transform: uppercase;
  letter-spacing: 0.13em;
  font-size: 0.6875rem;
  margin-bottom: 0.4rem;
}
.hero__meta dd { margin: 0; color: var(--ivory-dim); }

@keyframes rise {
  to { opacity: 1; transform: none; }
}

/* --- 7. The Division Ledger (signature element) -------------------------- */

.ledger { border-top: 1px solid var(--hair); }

.ledger__group {
  padding-top: 1.6rem;
  margin-top: 2.6rem;
  border-top: 1px solid var(--hair);
}
.ledger__group:first-of-type { margin-top: 2rem; border-top: 0; padding-top: 0; }

.ledger__grouptitle {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 1.2rem;
}

.row {
  border-top: 1px solid var(--hair);
}
.row:last-child { border-bottom: 1px solid var(--hair); }

.row__head {
  width: 100%;
  display: grid;
  grid-template-columns: 4.2rem 1fr auto;
  align-items: baseline;
  gap: 1rem;
  padding: 1.15rem 0;
  text-align: left;
  transition: background 0.3s var(--ease-out), padding-inline 0.3s var(--ease-out);
}
.row__head:hover {
  background: rgba(244, 243, 239, 0.035);
  padding-inline: 0.9rem;
}

.row__code {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--brass);
  letter-spacing: 0.06em;
}

.row__name {
  font-family: var(--display);
  font-stretch: 108%;
  font-weight: 500;
  font-size: clamp(1.05rem, 0.96rem + 0.42vw, 1.35rem);
  letter-spacing: -0.012em;
}
.row__name small {
  display: block;
  font-family: var(--body);
  font-stretch: normal;
  font-weight: 400;
  font-size: 0.875rem;
  color: var(--slate);
  letter-spacing: 0;
  margin-top: 0.28rem;
  max-width: 46ch;
}

.row__flag {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
.row__flag::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--slate-dim);
}
.row__flag[data-state="active"]::before { background: var(--brass-lit); }
.row__flag[data-state="build"]::before  { background: #6E8FA6; }
/* Three states, and the dot carries the whole distinction:

     filled + colour   live      — a line open, or software being built
     filled + grey     shelved   — it was alive once, and stopped
     outline           specified — it was never filled in at all

   Which is why "specified" is a ring and "shelved" is a faded disc rather
   than the other way round. */
.row__flag[data-state="specified"]::before {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--slate);
}
.row__flag[data-state="shelved"]::before {
  background: var(--slate-dim);
  opacity: 0.75;
}

.row__body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.42s var(--ease-out);
}
.row[data-open="true"] .row__body { grid-template-rows: 1fr; }
.row__bodyinner { overflow: hidden; }
.row__bodyinner > div {
  padding: 0.2rem 0 1.9rem;
  display: grid;
  gap: 1.5rem 3rem;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .row__bodyinner > div { grid-template-columns: 4.2rem minmax(0, 1fr) minmax(0, 0.9fr); }
  /* Everything in the panel is reading, and reading lives in column 2. Only
     the spec list belongs in the narrow right-hand column, beside the opening
     paragraph.

     Placing the first child alone was enough while a row held exactly three
     children — paragraph, spec list, link — because auto-placement happened to
     put them right. Adding a fourth broke it silently: the new paragraph flowed
     into column 1, which is a 4.2rem gutter, and came out one word per line.
     Naming the columns explicitly means the panel does not depend on how many
     children a row happens to have. */
  .row__bodyinner > div > * { grid-column: 2; }
  .row__bodyinner > div > .speclist { grid-column: 3; grid-row: 1; }
}
.row__body p { font-size: 0.9375rem; color: var(--ivory-dim); }

.speclist { list-style: none; margin: 0; padding: 0; }
.speclist li {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  color: var(--slate);
  padding: 0.42rem 0;
  border-top: 1px solid var(--hair);
}
.speclist li:first-child { border-top: 0; }

/* --- 8. Capability grid -------------------------------------------------- */

.grid {
  display: grid;
  gap: 1px;
  background: var(--hair);
  border-block: 1px solid var(--hair);
  grid-template-columns: 1fr;
}
@media (min-width: 700px)  { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }

.cell {
  background: var(--obsidian);
  padding: clamp(1.6rem, 3vw, 2.4rem) clamp(1.4rem, 2.6vw, 2.1rem);
}
.section--light .grid { background: var(--hair-ink); border-color: var(--hair-ink); }
.section--light .cell { background: var(--ivory); }

.cell__idx {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  color: var(--brass);
  display: block;
  margin-bottom: 1.1rem;
}
.cell h3 { margin-bottom: 0.7rem; }
.cell p { font-size: 0.9375rem; color: var(--slate); margin: 0; }
.section--light .cell p { color: #55575C; }

/* --- 9. Process (sequence, so numbering is earned) ----------------------- */

.steps { counter-reset: step; border-top: 1px solid var(--hair-ink); }
.step {
  counter-increment: step;
  display: grid;
  gap: 0.5rem 2.2rem;
  grid-template-columns: 1fr;
  padding: 1.7rem 0;
  border-bottom: 1px solid var(--hair-ink);
}
@media (min-width: 800px) {
  .step { grid-template-columns: 5.5rem minmax(0, 20ch) minmax(0, 1fr); align-items: baseline; }
}
.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 0.75rem;
  color: #8A6427;
  letter-spacing: 0.08em;
}
.step h3 { font-size: 1.1rem; }
.step p { font-size: 0.9375rem; color: #55575C; margin: 0; }

/* --- 10. Product plates -------------------------------------------------- */

.plates {
  display: grid;
  gap: clamp(1rem, 2vw, 1.6rem);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.plate {
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  padding: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.plate__img {
  position: relative;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  background:
    repeating-linear-gradient(45deg, rgba(244,243,239,0.022) 0 10px, transparent 10px 20px),
    var(--graphite-2);
  color: var(--slate-dim);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  overflow: hidden;
}
.plate__img img { width: 100%; height: 100%; object-fit: cover; }

/* Canvas overlay for the pixel wash. Painted by js/hob.js; decorative only,
   so it is hidden outright when motion is reduced. `screen` keeps the brass
   reading as light over both the placeholder hatch and a real photograph. */
.plate__pixels {
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}
.plate__meta { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.plate__meta h4 { font-size: 1rem; }
.plate__meta span { font-family: var(--mono); font-size: 0.6875rem; color: var(--brass); letter-spacing: 0.08em; }
.plate p { font-size: 0.875rem; color: var(--slate); margin: 0; }

/* --- 11. Buttons --------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.95rem 1.6rem;
  border: 1px solid var(--brass);
  color: var(--brass-lit);
  background: transparent;
  transition: background 0.3s var(--ease-out), color 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}
.btn:hover { background: var(--brass); color: var(--obsidian); }
.btn:active { transform: translateY(1px); }

.btn--solid { background: var(--brass); color: var(--obsidian); border-color: var(--brass); }
.btn--solid:hover { background: var(--brass-lit); border-color: var(--brass-lit); }

.btn--ink { border-color: var(--obsidian); color: var(--obsidian); }
.btn--ink:hover { background: var(--obsidian); color: var(--ivory); }

.btnrow { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 2.2rem; }

/* --- 12. Callout band ---------------------------------------------------- */

.band {
  background: var(--graphite);
  border-block: 1px solid var(--hair);
}
.band__inner {
  display: grid;
  gap: 2rem;
  align-items: center;
  padding-block: clamp(3rem, 6vw, 4.6rem);
}
@media (min-width: 900px) {
  .band__inner { grid-template-columns: minmax(0, 1fr) auto; gap: 4rem; }
}

/* --- 13. Forms ----------------------------------------------------------- */

.form { display: grid; gap: 1.4rem; max-width: 640px; }
.field { display: grid; gap: 0.5rem; }
.field label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate);
}
.field input,
.field select,
.field textarea {
  font-family: var(--body);
  font-size: 0.9375rem;
  color: var(--ivory);
  background: var(--graphite);
  border: 1px solid var(--hair);
  padding: 0.85rem 1rem;
  width: 100%;
  transition: border-color 0.25s var(--ease-out), background 0.25s var(--ease-out);
}
.field textarea { min-height: 150px; resize: vertical; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--brass);
  background: var(--graphite-2);
  outline: none;
}
.field input::placeholder, .field textarea::placeholder { color: var(--slate-dim); }
.field select { appearance: none; background-image: none; }

.formnote { font-size: 0.8125rem; color: var(--slate-dim); max-width: 52ch; }

.hp { position: absolute; left: -9999px; opacity: 0; }

.formstatus {
  font-family: var(--mono);
  font-size: 0.8125rem;
  padding: 0.9rem 1.1rem;
  border-left: 2px solid var(--brass);
  background: rgba(185, 138, 62, 0.08);
}

/* --- 14. Footer ---------------------------------------------------------- */

.foot {
  border-top: 1px solid var(--hair);
  padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
}
.foot__cols {
  display: grid;
  gap: 2.6rem;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .foot__cols { grid-template-columns: 1.4fr repeat(3, 0.8fr); gap: 3rem; }
}
.foot h4 {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate-dim);
  margin: 0 0 1.1rem;
}
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.foot a { text-decoration: none; font-size: 0.9375rem; color: var(--ivory-dim); transition: color 0.25s var(--ease-out); }
.foot a:hover { color: var(--brass-lit); }
.foot__mark img { height: 34px; width: auto; margin-bottom: 1.2rem; }
.foot__legal {
  margin-top: 3rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--hair);
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 2rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  color: var(--slate-dim);
}

/* --- 15. Reveal on scroll ------------------------------------------------ */

[data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.75s var(--ease-out), transform 0.75s var(--ease-out);
}
[data-reveal].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
  .hero__mark { opacity: 1; transform: none; }
  .plate__pixels { display: none; }
}

/* --- 16. Utility --------------------------------------------------------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--brass);
  color: var(--obsidian);
  padding: 0.8rem 1.2rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  z-index: 100;
}
.skip:focus { left: 0; }

.prose h2 { margin-top: 2.6rem; margin-bottom: 1rem; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 1.9rem; margin-bottom: 0.6rem; }
.prose ul { padding-left: 1.15rem; max-width: var(--measure); }
.prose li { margin-bottom: 0.5rem; }

/* --- 17. Product page (HB·001) ------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.prodhero { padding-block: calc(var(--stack) * 0.7) 0; }
.prodhero__inner {
  display: grid;
  gap: clamp(2rem, 4vw, 4rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 900px) {
  .prodhero__inner { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
}
.prodhero__copy h1 { font-size: clamp(2.4rem, 1.4rem + 3.4vw, 4.2rem); }
.prodhero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 2.4rem;
}
.prodhero__media {
  margin: 0;
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  overflow: hidden;
}
.prodhero__media img { display: block; width: 100%; height: auto; }

/* Drawing title block: mono, hairline ruled, reads as a document header. */
.dwg {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  margin: clamp(2.4rem, 5vw, 4rem) 0 0;
  background: var(--hair);
  border: 1px solid var(--hair);
}
.dwg > div { background: var(--obsidian); padding: 1.1rem 1.2rem; }
.dwg dt {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
}
.dwg dd {
  margin: 0.5rem 0 0;
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--ivory-dim);
}

/* One chapter: media pins while its copy scrolls past, so the product stays
   present through the section without any script. */
.chapter {
  display: grid;
  gap: clamp(1.6rem, 3vw, 3.2rem);
  grid-template-columns: 1fr;
  align-items: start;
  padding-block: clamp(2.4rem, 5vw, 4.4rem);
  border-top: 1px solid var(--hair);
}
.chapter:first-of-type { border-top: 0; }
@media (min-width: 900px) {
  .chapter { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
  .chapter:nth-child(even) .chapter__media { order: 2; }
  .chapter__media { position: sticky; top: 12vh; }
}
.chapter__media {
  /* Plates are keyed to transparency, so they sit straight on the page ground
     rather than inside a frame. */
  margin: 0;
}
.chapter__media img { display: block; width: 100%; height: auto; }
.chapter__body h2 { font-size: clamp(1.5rem, 1.1rem + 1.2vw, 2.1rem); }
.chapter__body p { margin-top: 1.1rem; max-width: 46ch; }

.callouts { list-style: none; margin: 1.4rem 0 0; padding: 0; }
.callouts li {
  display: grid;
  grid-template-columns: 2.6rem 1fr;
  gap: 0.6rem;
  padding: 0.7rem 0;
  border-top: 1px solid var(--hair);
  font-size: 0.9375rem;
}
.callouts li span {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--brass);
  letter-spacing: 0.08em;
}

.spectable { margin-top: 2rem; overflow-x: auto; border: 1px solid var(--hair); }
.spectable table { width: 100%; border-collapse: collapse; min-width: 520px; }
.spectable th, .spectable td {
  text-align: left;
  padding: 0.95rem 1.2rem;
  border-bottom: 1px solid var(--hair);
  font-size: 0.875rem;
}
.spectable thead th {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
  font-weight: 500;
}
.spectable tbody tr:last-child th,
.spectable tbody tr:last-child td { border-bottom: 0; }
.spectable td:first-child { color: var(--slate); }
.spectable td:last-child { font-family: var(--mono); color: var(--ivory-dim); }

/* --- 18. Home hero split + flagship -------------------------------------- */

.hero__split {
  display: grid;
  gap: clamp(2rem, 4vw, 4.5rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 940px) {
  .hero__split { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
}
.hero__media {
  margin: 0;
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  overflow: hidden;
}
.hero__media img { display: block; width: 100%; height: auto; }
/* The clips are 9:16; holding them to 4:5 keeps the hero the shape it was
   before there was a video in it. */
/* The clip is 9:16 and its framing swings through the shot, so any crop shows
   ceiling for part of the loop. Shown at native ratio and width-capped instead,
   so the composition is always the authored one. */
.hero__media--video { max-width: 360px; margin-inline: auto; }
.hero__media--video video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  background: var(--graphite);
}
.hero__media figcaption {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
  padding: 0.9rem 1.1rem;
  border-top: 1px solid var(--hair);
}

/* --- the character field behind the hero -------------------------------
   A canvas of scrambling monospace, sitting under everything the hero says.
   Three things keep it a background rather than a competitor:

   · it is drawn in the page's own colours — graphite through slate, with the
     brass appearing rarely enough to read as an accent rather than a theme;
   · the canvas runs at half strength, and a scrim leans across the frame so
     the side carrying the headline stays near-black while the side carrying
     the mark lets the field through. The copy is the loudest thing in the
     hero and has to stay that way;
   · the outer vignette closes the edges so the field has no visible border.

   The section already has overflow:hidden, so the canvas is clipped to it. */
.hero__glitch {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--obsidian);
}
.hero__glitch canvas {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0.5;
}

.lg-vignette { position: absolute; inset: 0; pointer-events: none; }
.lg-vignette--outer {
  background: radial-gradient(circle, rgba(11, 11, 12, 0) 50%, rgba(11, 11, 12, 1) 100%);
}
.lg-vignette--center {
  background: radial-gradient(circle, rgba(11, 11, 12, 0.85) 0%, rgba(11, 11, 12, 0) 62%);
}

/* the lean: heaviest under the copy, lightest under the mark */
.hero__glitch::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg,
    var(--obsidian) 0%,
    rgba(11, 11, 12, 0.95) 28%,
    rgba(11, 11, 12, 0.74) 50%,
    rgba(11, 11, 12, 0.44) 74%,
    rgba(11, 11, 12, 0.32) 100%);
}

/* The hero's own wash and all of its content sit above the field. */
.hero::before { z-index: 1; }
.hero > .wrap { position: relative; z-index: 2; }

/* --- the mark, in the column the video vacated ------------------------- */
.hero__markwrap {
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero__markwrap .hero__mark {
  width: 100%;
  max-width: min(84vw, 520px);
  margin: 0;
}
/* One column: the mark goes back above the headline, where it was when it
   was part of the copy block, rather than stranded under the buttons. */
@media (max-width: 939px) {
  .hero__markwrap { order: -1; justify-content: flex-start; }
  .hero__markwrap .hero__mark { max-width: min(78vw, 420px); }
}

.flagship {
  display: grid;
  gap: clamp(1.6rem, 3vw, 3.4rem);
  grid-template-columns: 1fr;
  align-items: center;
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  padding: clamp(1.2rem, 2.4vw, 2.2rem);
}
@media (min-width: 900px) {
  .flagship { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.flagship__media { margin: 0; }
.flagship__media img { display: block; width: 100%; height: auto; }

/* Same title-block treatment as the product page, without the outer frame. */
.dwg--inline { margin-top: 2rem; border: 0; background: transparent; gap: 0; }
.dwg--inline > div {
  background: transparent;
  padding: 0.75rem 0;
  border-top: 1px solid var(--hair);
}

/* --- 19. Letter glitch background ---------------------------------------- */

.glitch { position: relative; overflow: hidden; }
.glitch > .glitch__canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.glitch > .wrap { position: relative; z-index: 1; }
/* Vignette so the field fades out rather than colliding with the section edge */
.glitch::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(ellipse at center, transparent 30%, var(--obsidian) 88%);
}

/* --- 20. Card swap -------------------------------------------------------- */

.swapstack {
  position: relative;
  /* Sized to hold the whole 3D stack: the slots step up and right, and the
     dropped card is clipped rather than falling into the next section. */
  min-height: 560px;
  margin-top: 2.4rem;
  perspective: 900px;
  overflow: hidden;
}
@media (min-width: 900px) {
  /* Pull the stack's right edge out to the viewport edge: that is the page
     gutter plus whatever the centred .wrap leaves either side of its 1320px
     cap. overflow:hidden then clips the cards exactly at the window edge, so
     they bleed off the page the way the original does -- and because the box
     stops at the edge rather than crossing it, no horizontal scrollbar. */
  .swapstack {
    margin-right: calc(-1 * (var(--gut) + max(0px, (100vw - 1320px) / 2)));
    min-height: clamp(700px, 76vw, 1000px);
    margin-top: 0;
  }
}
.swapcard {
  border: 1px solid var(--hair);
  border-radius: 12px;
  background: var(--obsidian);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.swapstack[data-cardswap-ready] .swapcard {
  position: absolute;
  top: 60%;
  left: 46%;
  width: min(520px, 92%);
  height: 360px;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}
@media (min-width: 900px) {
  /* Declared after the base rule on purpose: same specificity, so source
     order decides. Sits far enough right that the cards overhang the stack's
     edge -- which is the window edge -- and get cut there. */
  .swapstack[data-cardswap-ready] .swapcard {
    /* Viewport-relative, not a percentage of the container: the card has to be
       WIDER than the stack so it overhangs and is cut at the window edge. A %
       width would clamp to the container and never overflow. Sized so the
       visible half lands at roughly 50vw. */
    width: min(1400px, 105vw);
    height: min(820px, 62vw);
    left: 101%;
    /* Measured, not guessed: this puts the topmost card's edge level with the
       eyebrow in the column beside it, with the stack filling the box so there
       is no dead space left underneath. */
    top: 51%;
  }
}
.swapstack:not([data-cardswap-ready]) { perspective: none; min-height: 0; overflow: visible; margin-right: 0; }
.swapstack:not([data-cardswap-ready]) .swapcard { height: 300px; }
.swapstack:not([data-cardswap-ready]) .swapcard + .swapcard { margin-top: 1rem; }

.swapcard__bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.05rem;
  border-bottom: 1px solid var(--hair);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ivory-dim);
}
.swapcard__dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--brass);
  flex: none;
}
/* Media fills the rest of the card edge to edge. */
.swapcard__media {
  flex: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  background:
    repeating-linear-gradient(45deg, rgba(244,243,239,0.022) 0 10px, transparent 10px 20px),
    var(--graphite-2);
  color: var(--slate-dim);
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  padding: 0.9rem;
}
.swapcard__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top left;
}

/* The per-card notes now sit beside the stack instead of inside the cards. */
.swapnotes { margin-top: 1.6rem; }
.swapnotes strong { color: var(--ivory-dim); font-weight: 500; }

/* --- 21. Specular button -------------------------------------------------- */

@property --specular-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.btn--specular {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  background: rgba(244, 243, 239, 0.03);
  backdrop-filter: blur(3px);
}
.btn--specular::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(from var(--specular-angle),
    transparent 0deg, var(--brass-lit) 12deg, transparent 52deg,
    transparent 180deg, var(--brass) 192deg, transparent 232deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: specular-sweep 5.5s linear infinite;
  pointer-events: none;
}
/* Pointer tracking sets the angle directly, so the idle sweep steps aside. */
.btn--specular[data-tracking]::before { animation: none; }
.btn--specular::after {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: inherit;
  border: 1px solid rgba(244, 243, 239, 0.06);
  pointer-events: none;
}
@keyframes specular-sweep { to { --specular-angle: 360deg; } }
@media (prefers-reduced-motion: reduce) {
  .btn--specular::before { animation: none; }
}

/* --- 22. Funding campaign ------------------------------------------------- */

.campaign {
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  padding: clamp(1.4rem, 3vw, 2.4rem);
}
.campaign__figures {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  background: var(--hair);
  border: 1px solid var(--hair);
  margin: 1.6rem 0;
}
.campaign__figures > div { background: var(--obsidian); padding: 1rem 1.1rem; }
.campaign__figures dt {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
}
.campaign__figures dd {
  margin: 0.45rem 0 0;
  font-family: var(--mono);
  font-size: 1rem;
  color: var(--ivory);
}
.progress {
  height: 6px;
  background: var(--graphite-2);
  border: 1px solid var(--hair);
  overflow: hidden;
}
.progress__fill {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--brass), var(--brass-lit));
  transition: width 1.1s var(--ease-out);
}
.campaign__note {
  font-size: 0.8125rem;
  color: var(--slate);
  margin-top: 1.4rem;
  max-width: 60ch;
}

/* Pledge dialog */
.modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: none;
  place-items: center;
  padding: 1.2rem;
  background: rgba(11, 11, 12, 0.82);
  backdrop-filter: blur(4px);
}
.modal[data-open="true"] { display: grid; }
.modal__panel {
  width: min(560px, 100%);
  max-height: 88vh;
  overflow-y: auto;
  border: 1px solid var(--hair);
  background: var(--graphite);
  padding: clamp(1.4rem, 3vw, 2.2rem);
}
.modal__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.modal__close {
  background: none;
  border: 0;
  color: var(--slate);
  font-family: var(--mono);
  font-size: 0.75rem;
  cursor: pointer;
  padding: 0.3rem;
}
.modal__close:hover { color: var(--ivory); }
.tiers { display: grid; gap: 0.7rem; margin: 1.4rem 0; }
.tier {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.8rem;
  align-items: start;
  border: 1px solid var(--hair);
  padding: 0.9rem 1rem;
  cursor: pointer;
}
.tier:hover { border-color: var(--brass); }
.tier input { margin-top: 0.25rem; accent-color: var(--brass); }
.tier strong { font-size: 0.9375rem; display: block; }
.tier span { display: block; font-size: 0.8125rem; color: var(--slate); margin-top: 0.2rem; }
.tier em {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--mono);
  font-style: normal;
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brass);
}

/* --- 23. Steps on a dark section ----------------------------------------- */
/* .steps was authored for .section--light; these restate only the colours. */

.section:not(.section--light) .steps { border-top-color: var(--hair); }
.section:not(.section--light) .step { border-bottom-color: var(--hair); }
.section:not(.section--light) .step::before { color: var(--brass); }
.section:not(.section--light) .step p { color: var(--slate); }

/* --- 24. Cursor wave ------------------------------------------------------ */

.cursorwave {
  position: fixed;
  inset: 0;
  z-index: -1;          /* behind page content, above the html ground */
  pointer-events: none; /* never intercepts clicks or text selection */
}
@media (prefers-reduced-motion: reduce) {
  .cursorwave { display: none; }
}

/* --- 25. Magic bento (division ledger) ------------------------------------ */
/* Ported from the React Bits MagicBento spec: border glow that tracks the
   cursor, a global spotlight over the grid, hover particles, tilt, magnetism
   and a click ripple. Brass in place of the reference purple. */

.bento {
  display: grid;
  gap: clamp(0.6rem, 1.2vw, 1rem);
  grid-template-columns: 1fr;
  margin-top: 1.4rem;
  position: relative;
  user-select: none;
}
@media (min-width: 600px)  { .bento { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) {
  .bento { grid-template-columns: repeat(4, 1fr); }
  /* One feature tile per division, so the grid reads as a bento rather than
     a uniform card wall. 7 entries then fill two rows exactly. */
  .bento-card--feature { grid-column: span 2; }
}

.bento-card {
  --glow-x: 50%;
  --glow-y: 50%;
  --glow-intensity: 0;
  --glow-radius: 260px;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-height: 190px;
  padding: 1.15rem 1.25rem;
  border: 1px solid var(--hair);
  border-radius: 14px;
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  transform-style: preserve-3d;
  transition: transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out),
              border-color 0.3s var(--ease-out);
}
.bento-card:hover { border-color: rgba(185, 138, 62, 0.35); }

.bento-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.bento-card__code {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  color: var(--brass);
}
.bento-card__body { flex: 1; min-height: 0; }
.bento-card__title { font-size: 1.05rem; margin: 0 0 0.4rem; }
.bento-card__desc {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--slate);
  margin: 0;
  /* textAutoHide: full copy stays in the DOM, clamped visually */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.bento-card--feature .bento-card__desc { -webkit-line-clamp: 5; line-clamp: 5; }

.bento-card__specs { list-style: none; display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0; padding: 0; }
.bento-card__specs li {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  color: var(--slate-dim);
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 0.2rem 0.55rem;
}
.bento-card__open {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brass);
  text-decoration: none;
  border-top: 1px solid var(--hair);
  padding-top: 0.8rem;
}
.bento-card__open:hover { color: var(--brass-lit); }

/* Border glow that follows the cursor (masked ring, per the reference) */
.bento-card--glow::after {
  content: "";
  position: absolute;
  inset: 0;
  padding: 4px;
  border-radius: inherit;
  background: radial-gradient(var(--glow-radius) circle at var(--glow-x) var(--glow-y),
    rgba(185, 138, 62, calc(var(--glow-intensity) * 0.75)) 0%,
    rgba(185, 138, 62, calc(var(--glow-intensity) * 0.35)) 30%,
    transparent 60%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  z-index: 1;
}
.bento-card--glow:hover { box-shadow: 0 8px 30px rgba(0,0,0,0.45), 0 0 26px rgba(185,138,62,0.10); }

/* Global spotlight element, appended to <body> */
.bento-spotlight {
  position: fixed;
  width: 700px; height: 700px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%);
  mix-blend-mode: screen;
  z-index: 3;
  transition: opacity 0.3s ease;
  background: radial-gradient(circle,
    rgba(185,138,62,0.10) 0%, rgba(185,138,62,0.06) 15%,
    rgba(185,138,62,0.03) 28%, rgba(185,138,62,0.015) 45%, transparent 70%);
}

.bento-particle {
  position: absolute;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: rgba(185, 138, 62, 0.9);
  box-shadow: 0 0 6px rgba(185, 138, 62, 0.6);
  pointer-events: none;
  z-index: 2;
  animation: bento-drift var(--dur, 3s) ease-in-out infinite alternate;
}
@keyframes bento-drift {
  from { transform: translate(0, 0); opacity: 0.85; }
  to   { transform: translate(var(--dx, 20px), var(--dy, -20px)); opacity: 0.25; }
}

.bento-ripple {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 3;
  background: radial-gradient(circle, rgba(185,138,62,0.35) 0%, rgba(185,138,62,0.16) 30%, transparent 70%);
  animation: bento-ripple 0.8s var(--ease-out) forwards;
}
@keyframes bento-ripple {
  from { transform: scale(0); opacity: 1; }
  to   { transform: scale(1); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .bento-card { transition: none; }
  .bento-spotlight, .bento-particle, .bento-ripple { display: none; }
}

/* ==========================================================================
   Modal cards — the bento tile, expanded

   The tile is the trigger. A stretched transparent button sits over it so a
   click anywhere opens the panel, while the tile's own "Open HW.01" link is
   lifted above that button and still navigates. The grid already sets
   user-select:none, so nothing is lost by covering the text.
   ========================================================================== */
.bento-card__expand {
  position: absolute;
  inset: 0;
  z-index: 0;
  appearance: none;
  border: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  cursor: pointer;
  border-radius: inherit;
}
.bento-card__expand:focus-visible {
  outline: 2px solid var(--brass-lit);
  outline-offset: -4px;
}
/* the real link stays reachable above the expand surface */
.bento-card__open { position: relative; z-index: 2; }

.cardmodal {
  padding: 0;
  border: 0;
  background: transparent;
  max-width: none;
  max-height: none;
  width: 100%;
  height: 100%;
  overflow: visible;
  color: var(--ivory);
}
.cardmodal::backdrop {
  background: rgba(6, 6, 7, 0.82);
  backdrop-filter: blur(3px);
}
@supports not (backdrop-filter: blur(3px)) {
  .cardmodal::backdrop { background: rgba(6, 6, 7, 0.93); }
}

.cardmodal__panel {
  position: absolute;
  inset: clamp(0px, 4vh, 3.5rem) clamp(0px, 4vw, 4rem);
  display: flex;
  flex-direction: column;
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  border: 1px solid var(--hair);
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6);
  overflow: auto;
  padding: clamp(1.4rem, 4vw, 3rem);
  gap: clamp(1.2rem, 3vw, 2rem);
}
/* On a phone it is the screen, with no border to waste width on. */
@media (max-width: 640px) {
  .cardmodal__panel { inset: 0; border: 0; }
}

.cardmodal__head {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--hair);
}
.cardmodal__code {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
}
.cardmodal__flag {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
}
.cardmodal__close {
  margin-left: auto;
  appearance: none;
  background: transparent;
  border: 1px solid var(--hair);
  color: var(--ivory-dim);
  font-size: 1.5rem;
  line-height: 1;
  width: 2.4rem;
  height: 2.4rem;
  cursor: pointer;
  transition: border-color 0.2s var(--ease-out), color 0.2s var(--ease-out);
}
.cardmodal__close:hover { border-color: rgba(185, 138, 62, 0.5); color: var(--brass-lit); }
.cardmodal__close:focus-visible { outline: 2px solid var(--brass-lit); outline-offset: 2px; }

.cardmodal__body { max-width: var(--measure); }
.cardmodal__title {
  font-family: var(--display);
  font-size: clamp(1.6rem, 4vw, 2.6rem);
  line-height: 1.08;
  margin: 0 0 1rem;
}
/* The point of the panel: in the grid this text is clamped, here it is not. */
.cardmodal__desc {
  margin: 0;
  color: var(--ivory-dim);
  font-size: 1.0625rem;
  line-height: 1.65;
}
.cardmodal__specs {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 1.6rem 0 0;
  padding: 0;
}
.cardmodal__specs li {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--slate);
  border: 1px solid var(--hair);
  padding: 0.35rem 0.6rem;
}

.cardmodal__foot {
  margin-top: auto;
  padding-top: 1.2rem;
  border-top: 1px solid var(--hair);
}
.cardmodal__open {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass);
  text-decoration: none;
}
.cardmodal__open:hover { color: var(--brass-lit); }

/* The panel travels from the tile via the Web Animations API; the backdrop
   is the only part CSS animates, and it stands down with everything else. */
.cardmodal[data-open="true"]::backdrop { animation: cardmodal-veil 0.32s var(--ease-out); }
@keyframes cardmodal-veil { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .cardmodal[data-open="true"]::backdrop { animation: none; }
}

/* ==========================================================================
   Product summaries

   Two shapes, because the pages ask for two different things. On a product
   page the summary is read: a short paragraph under the lede, set between the
   lede and the body copy so it is clearly a précis and not the start of the
   argument. On a division page it is scanned: one line per entry, in the
   mono face the codes and specs already use, so a reader can take in seven
   lines without opening seven pages.
   ========================================================================== */
.prodhero__sum {
  margin: 1.1rem 0 0;
  max-width: 58ch;
  color: var(--slate);
  font-size: 0.9375rem;
  line-height: 1.7;
  padding-left: 1rem;
  border-left: 1px solid var(--hair);
}

.plate__sum {
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: var(--slate-dim);
  margin: 0.7rem 0 0;
  padding-top: 0.7rem;
  border-top: 1px solid var(--hair);
}
/* Inside an accordion row the line closes the panel, so it wants the room. */
.row__bodyinner .plate__sum { margin-top: 1.2rem; padding-top: 0.9rem; }

/* ==========================================================================
   Page flip — a two-page spread

   Without JavaScript this is an ordered list of sections, all visible. The
   book below only applies once js/page-flip.js has paired the pages into
   leaves and set [data-pageflip-ready].

   Every leaf lives in the RIGHT half with its hinge on the spine, so turning
   one carries its back face into the LEFT half. That is the whole trick, and
   it is why the back face is authored pre-rotated.
   ========================================================================== */
.flip { position: relative; margin-top: 1.6rem; }

.flip__page {
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  padding: clamp(1.3rem, 3vw, 2.2rem);
  margin-bottom: 1rem;
}
.flip__page > h3 {
  font-family: var(--display);
  font-size: clamp(1.05rem, 2vw, 1.35rem);
  margin: 0 0 0.8rem;
}
.flip__page p { max-width: 46ch; font-size: 0.9375rem; }
.flip__page p + p { margin-top: 0.8rem; }
.flip__folio {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
  display: block;
  margin-bottom: 0.8rem;
}
.flip__figure { margin: 0 0 1rem; border: 1px solid var(--hair); background: var(--graphite-2); }
.flip__figure img { display: block; width: 100%; height: auto; }
.flip__figure figcaption {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate-dim);
  padding: 0.5rem 0.7rem;
  border-top: 1px solid var(--hair);
}
.flip__data { margin: 1rem 0 0; }
.flip__data div { display: flex; gap: 0.8rem; padding: 0.4rem 0; border-top: 1px solid var(--hair); }
.flip__data dt {
  font-family: var(--mono); font-size: 0.625rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--slate-dim); flex: 0 0 8.5rem;
}
.flip__data dd { margin: 0; font-family: var(--mono); font-size: 0.75rem; color: var(--ivory-dim); }

/* --- once paired into leaves, it becomes a book -------------------------- */
[data-pageflip-ready] {
  perspective: 2400px;
  aspect-ratio: 3 / 2;
  margin-bottom: 0;
}
[data-pageflip-ready] .flip__leaf {
  position: absolute;
  top: 0;
  left: 50%;                 /* the spine */
  width: 50%;
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
  transition: transform 0.68s var(--ease-out);
}
[data-pageflip-ready] .flip__leaf.is-turned { transform: rotateY(-180deg); }
[data-pageflip-ready].is-dragging .flip__leaf { transition: none; }

[data-pageflip-ready] .flip__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  overflow: auto;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
}
/* the back is pre-rotated so it reads correctly once the leaf is over */
[data-pageflip-ready] .flip__face--back { transform: rotateY(180deg); }
[data-pageflip-ready] .flip__face .flip__page { margin: 0; height: 100%; border: 0; }

/* the gutter shadow falls towards the spine on both halves */
[data-pageflip-ready] .flip__face--front .flip__page { border-left: 1px solid var(--hair); }
[data-pageflip-ready] .flip__face--back  .flip__page { border-right: 1px solid var(--hair); }
[data-pageflip-ready] .flip__face::before {
  content: "";
  position: absolute; top: 0; bottom: 0; width: 30px;
  pointer-events: none; z-index: 1;
}
[data-pageflip-ready] .flip__face--front::before {
  left: 0; background: linear-gradient(90deg, rgba(0,0,0,0.5), transparent);
}
[data-pageflip-ready] .flip__face--back::before {
  right: 0; background: linear-gradient(270deg, rgba(0,0,0,0.5), transparent);
}
[data-pageflip-ready]:focus-visible { outline: 2px solid var(--brass-lit); outline-offset: 6px; }

/* One page at a time where a spread will not fit. */
@media (max-width: 760px) {
  [data-pageflip-ready] { aspect-ratio: 3 / 4; }
  [data-pageflip-ready] .flip__leaf { left: 0; width: 100%; }
  [data-pageflip-ready] .flip__face--back { display: none; }
}

.flip__nav { display: flex; align-items: center; gap: 1rem; margin-top: 1.2rem; }
.flip__btn {
  appearance: none; background: transparent; border: 1px solid var(--hair);
  color: var(--ivory-dim); font-family: var(--mono); font-size: 0.9rem;
  width: 2.6rem; height: 2.6rem; cursor: pointer;
  transition: border-color 0.2s var(--ease-out), color 0.2s var(--ease-out);
}
.flip__btn:hover:not(:disabled) { border-color: rgba(185, 138, 62, 0.5); color: var(--brass-lit); }
.flip__btn:disabled { opacity: 0.3; cursor: default; }
.flip__btn:focus-visible { outline: 2px solid var(--brass-lit); outline-offset: 2px; }
.flip__count {
  font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--slate-dim); margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  [data-pageflip-ready] .flip__leaf { transition: none; }
}

/* ==========================================================================
   Concept plates

   The line plates sit inside .plate__img, which crops to fill. The concept
   plates are 16:9 and carry the AI column as markup over the right hand side
   (see Concept AI layer below), so they must never be cropped: the caption
   below is the only chrome, and the image sets its own height.
   ========================================================================== */

.concepts {
  display: grid;
  gap: clamp(1rem, 2vw, 1.6rem);
  /* Two up. The AI column is markup now and reflows, so a third column is
     no longer ruled out by type size; the 440px floor is what holds it. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
  margin-top: clamp(2rem, 4vw, 3rem);
}
.concept {
  margin: 0;
  border: 1px solid var(--hair);
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  overflow: hidden;
}
.concept img { display: block; width: 100%; height: auto; }
.concept figcaption {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.9rem 1.1rem;
  border-top: 1px solid var(--hair);
}
.concept__code {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass);
}
.concept__note { font-size: 0.8125rem; line-height: 1.55; color: var(--slate); }
.concept--wide { margin-top: clamp(2rem, 4vw, 3rem); }
.concept--wide figcaption { flex-direction: row; justify-content: space-between; }

/* ==========================================================================
   Concept AI layer

   The Ask / Understand / Act column used to be drawn into the SVG, which is
   why .concepts was capped at two up: baked type does not reflow, so a third
   column shrank it past reading. The labels are real markup now, so the plate
   carries a render underneath and the column scales with the frame. Sizing is
   in cqw against .conceptai__frame so one rule serves both the full-width
   plate on a line page and the half-width plate in the grid.
   ========================================================================== */
.conceptai__frame {
  position: relative;
  display: block;
  container-type: inline-size;
}
.conceptai__frame img { display: block; width: 100%; height: auto; }

.conceptai__layer {
  position: absolute;
  inset: 0 0 0 auto;
  width: 46%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4cqw;
  padding: 4cqw 4.5cqw;
  /* The render leaves this half near-black, but the scrim guarantees contrast
     rather than trusting the generation to stay dark. */
  background: linear-gradient(90deg, transparent, rgba(11, 11, 12, 0.72) 22%);
}

.conceptai__badge {
  margin: 0;
  align-self: start;
  font-family: var(--mono);
  font-size: 1.55cqw;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
  border: 1px solid rgba(185, 138, 62, 0.42);
  padding: 0.7cqw 1.2cqw;
}

.conceptai__steps { margin: 0; display: grid; gap: 2.6cqw; }
.conceptai__steps > div { display: grid; gap: 0.7cqw; }
.conceptai__steps dt {
  font-family: var(--mono);
  font-size: 1.5cqw;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ivory);
}
.conceptai__steps dd {
  margin: 0;
  font-size: 1.75cqw;
  line-height: 1.45;
  color: var(--ivory-dim);
  max-width: 26ch;
}

.conceptai__stamp {
  margin: 0;
  font-family: var(--mono);
  font-size: 1.3cqw;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate-dim);
}

/* Narrow plate: the column stops overlaying and sits under the render, where
   it has the full width to set in ordinary type. The cut is at 640px because
   the column is 46% of the frame and sized in cqw: below that the copy drops
   under ~11px, which is the same unreadability the baked-in type had. */
@container (max-width: 640px) {
  .conceptai__layer {
    position: static;
    width: auto;
    gap: 1.1rem;
    padding: 1.1rem 1.2rem 1.3rem;
    background: var(--graphite);
    border-top: 1px solid var(--hair);
  }
  .conceptai__badge { font-size: 0.625rem; padding: 0.3rem 0.55rem; }
  .conceptai__steps { gap: 0.85rem; }
  .conceptai__steps > div { gap: 0.2rem; }
  .conceptai__steps dt { font-size: 0.625rem; }
  .conceptai__steps dd { font-size: 0.8125rem; max-width: none; }
  .conceptai__stamp { font-size: 0.5625rem; }
}

/* No container query support: fall back to the flowed layout at every width
   rather than overlaying type that cannot size itself. */
@supports not (container-type: inline-size) {
  .conceptai__layer {
    position: static;
    width: auto;
    gap: 1.1rem;
    padding: 1.1rem 1.2rem 1.3rem;
    background: var(--graphite);
    border-top: 1px solid var(--hair);
  }
  .conceptai__badge { font-size: 0.625rem; padding: 0.3rem 0.55rem; }
  .conceptai__steps { gap: 0.85rem; }
  .conceptai__steps dt { font-size: 0.625rem; }
  .conceptai__steps dd { font-size: 0.8125rem; max-width: none; }
  .conceptai__stamp { font-size: 0.5625rem; }
}

/* ==========================================================================
   Blueprint band

   A drawing sheet on every page: directly under the hero on the product
   pages, above the footer everywhere else. It is decoration, so the image
   carries an empty alt and the title block below it is the only text: the
   band must never be the sole carrier of anything a reader needs.

   Bottom padding is deliberately 0. The band is followed by a .section that
   brings its own top padding, and above the footer it needs no trailing gap.
   ========================================================================== */
.blueprint { padding: clamp(2.5rem, 5vw, 4rem) 0 0; }
.blueprint__sheet {
  border: 1px solid var(--hair);
  background: var(--obsidian);
  overflow: hidden;
}
.blueprint__sheet img {
  display: block;
  width: 100%;
  height: auto;
  /* Held back so the sheet reads as ground, not as a second subject
     competing with the page content above it. */
  opacity: 0.82;
}
.blueprint__title {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  justify-content: space-between;
  padding: 0.85rem 1.1rem;
  border-top: 1px solid var(--hair);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
}
.blueprint__title span:first-child { color: var(--brass); }

@media (prefers-reduced-motion: no-preference) {
  .blueprint__sheet img { transition: opacity 0.4s ease; }
}

/* ==========================================================================
   Manual page detail

   Pages 03-05 of the line manual carried one sentence each and a lot of dead
   space. They now take a macro detail plate, and a ruled list that names the
   items the sentence already names — no specification is introduced here that
   the page does not already state elsewhere.
   ========================================================================== */
.flip__figure--after { margin-top: 1.1rem; }
.flip__rows { margin: 1.1rem 0 0; }
.flip__rows > div {
  display: grid;
  grid-template-columns: minmax(0, 9.5rem) 1fr;
  gap: 0.25rem 1rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--hair);
}
.flip__rows dt {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass);
  align-self: start;
  padding-top: 0.15rem;
}
.flip__rows dd { margin: 0; font-size: 0.875rem; line-height: 1.5; color: var(--ivory-dim); }
@media (max-width: 520px) {
  .flip__rows > div { grid-template-columns: 1fr; }
}

/* Finish palette. The swatches are a drawn intent, not a supplier's sample:
   the folio says so, and the hex is the site token the chip is built from. */
.finish { margin: 1.2rem 0 0; }
.finish__label {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
  margin: 0 0 0.6rem;
}
.finish__row {
  display: grid;
  /* 72px lets all six chips sit on one row inside a manual page; a larger
     minimum wrapped the sixth on its own and left an empty cell. */
  grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
}
.finish__chip { background: var(--graphite); }
.finish__swatch {
  height: 44px;
  /* Two layers make the metal: a fine vertical grain over an oblique sheen. */
  background-image:
    repeating-linear-gradient(90deg, rgba(244,243,239,0.05) 0 1px, transparent 1px 3px),
    linear-gradient(102deg, var(--m-dark) 0%, var(--m-lit) 36%, var(--m-mid) 54%, var(--m-dark) 100%);
}
.finish__name {
  display: block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ivory-dim);
  padding: 0.45rem 0.5rem 0.1rem;
}
.finish__hex {
  display: block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.08em;
  color: var(--slate-dim);
  padding: 0 0.5rem 0.5rem;
}

/* ==========================================================================
   Ledger row mark

   The ledger panels were text only. A mark or a product shot sits in the
   narrow right-hand column beneath the spec list. Column 3 is named
   explicitly for the same reason the spec list is: auto-placement drops
   anything unnamed into the 4.2rem gutter.
   ========================================================================== */
.row__mark {
  margin: 0;
  border: 1px solid var(--hair);
  background: var(--graphite-2);
}
.row__mark img { display: block; width: 100%; height: auto; }
.row__mark--pad img { padding: 1.1rem; box-sizing: border-box; }
.row__mark figcaption {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate-dim);
  padding: 0.45rem 0.6rem;
  border-top: 1px solid var(--hair);
}
@media (min-width: 760px) {
  .row__bodyinner > div > .row__mark { grid-column: 3; }
}

/* ==========================================================================
   Marks

   Brand artefacts on the house page. They are the one place on the site with
   colour outside the palette, so they sit boxed on their own ground rather
   than loose in the page.
   ========================================================================== */
.marks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
  margin-top: 1.6rem;
}
.marks figure { margin: 0; background: var(--graphite); display: flex; flex-direction: column; }
.marks img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 190px;
  object-fit: contain;
  padding: 1.2rem;
  box-sizing: border-box;
  margin-top: auto;
}
.marks figcaption {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate-dim);
  padding: 0.5rem 0.6rem;
  border-top: 1px solid var(--hair);
}

/* ==========================================================================
   Film reel

   Four of the five clips are 540x960 and one is 960x540, so the portrait set
   runs as a strip and the landscape one takes the wide plate above it. Nothing
   autoplays from markup: hob.js starts a clip only when it is on screen and
   only when the visitor has not asked for reduced motion, in which case the
   native controls appear instead.
   ========================================================================== */
.film { margin-top: clamp(2rem, 4vw, 3rem); }
.film__wide {
  margin: 0 0 1px;
  border: 1px solid var(--hair);
  background: var(--obsidian);
  overflow: hidden;
}
.film__wide video { display: block; width: 100%; height: auto; }

.reel {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
}
.reel__item { margin: 0; background: var(--obsidian); display: flex; flex-direction: column; }
.reel__frame { position: relative; aspect-ratio: 9 / 16; background: var(--graphite-2); }
.reel__frame video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.reel__item figcaption,
.film__wide figcaption {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate-dim);
  padding: 0.5rem 0.6rem;
  border-top: 1px solid var(--hair);
}

/* ==========================================================================
   Tenets

   Three-up commitment cards, used on the modular desktop. Each carries a
   plate, a claim and the ruled detail behind it, so the claim is never left
   as a slogan on its own.
   ========================================================================== */
.tenets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
  margin-top: clamp(1.6rem, 3vw, 2.4rem);
}
.tenet {
  background: linear-gradient(168deg, var(--graphite), var(--obsidian));
  padding: 0;
  display: flex;
  flex-direction: column;
}
.tenet__media { margin: 0; border-bottom: 1px solid var(--hair); }
.tenet__media img { display: block; width: 100%; height: auto; }
.tenet__body { padding: clamp(1.1rem, 2.4vw, 1.5rem); }
.tenet__body h3 {
  font-family: var(--display);
  font-size: clamp(1rem, 1.8vw, 1.2rem);
  margin: 0 0 0.7rem;
}
.tenet__body > p { font-size: 0.9375rem; margin: 0; max-width: 42ch; }
.tenet__body .flip__rows { margin-top: 1rem; }
.tenet__body .flip__rows > div { grid-template-columns: minmax(0, 7.5rem) 1fr; }

/* An inset plate inside a tenet body. It sits below the claim rather than in
   .tenet__media, so the three cards keep their headings on one line: the
   media band is what aligns them, and a second image up there would not. */
.tenet__inset {
  margin: 1rem 0 0;
  border: 1px solid var(--hair);
  background: var(--graphite-2);
}
.tenet__inset img { display: block; width: 100%; height: auto; }
.tenet__inset figcaption {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate-dim);
  padding: 0.45rem 0.6rem;
  border-top: 1px solid var(--hair);
}

/* A specimen plate: the subject on its own, held narrower than the wide
   concept plate so it reads as "here is the part" rather than as a hero. */
.concept--specimen { max-width: 560px; margin-top: clamp(1.6rem, 3vw, 2.2rem); }

/* ==========================================================================
   Bento card media and open button

   .bento-card__body carries flex:1, so a short description left a large gap
   above the spec chips. The plate takes that room instead of the gap doing
   nothing, and the open control now reads as a button rather than a line of
   mono text that people were not treating as clickable.
   ========================================================================== */
.bento-card__media {
  margin: 0;
  border: 1px solid var(--hair);
  background: var(--graphite-2);
  overflow: hidden;
  /* Fixed ratio so a row of tiles keeps a common baseline whatever the
     source image happens to be. */
  aspect-ratio: 16 / 9;
}
.bento-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
/* Brand marks are transparent artwork, not photography: they must sit whole
   inside the plate rather than be cropped to fill it. */
.bento-card__media--mark { background: var(--graphite); }
.bento-card__media--mark img { object-fit: contain; padding: 0.9rem; box-sizing: border-box; }

.bento-card--feature .bento-card__media { aspect-ratio: 21 / 9; }

/* The open control, as a button in both the tile and the panel. */
.bento-card__open,
.cardmodal__open {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  align-self: start;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brass);
  text-decoration: none;
  border: 1px solid rgba(185, 138, 62, 0.42);
  border-top: 1px solid rgba(185, 138, 62, 0.42);
  padding: 0.55rem 0.9rem;
  background: transparent;
  transition: border-color 0.2s ease, color 0.2s ease, background-color 0.2s ease;
}
.bento-card__open::after,
.cardmodal__open::after { content: "\2192"; }
.bento-card__open:hover,
.cardmodal__open:hover {
  color: var(--brass-lit);
  border-color: rgba(215, 169, 84, 0.8);
  background: rgba(185, 138, 62, 0.08);
}
.bento-card__open:focus-visible,
.cardmodal__open:focus-visible { outline: 2px solid var(--brass-lit); outline-offset: 2px; }

.cardmodal__media {
  margin: 0 0 1.2rem;
  border: 1px solid var(--hair);
  background: var(--graphite-2);
  overflow: hidden;
  aspect-ratio: 16 / 9;
}
.cardmodal__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.cardmodal__media--mark { background: var(--graphite); }
.cardmodal__media--mark img { object-fit: contain; padding: 1.6rem; box-sizing: border-box; }
