/* The light theme: made by tools/light_theme.py from ../style.css. Do not edit by hand. */
/* Letters cut into a polished deep blue and purple stone. Shared by every page. */

:root {
  --stone: #DED0AE;      /* the matrix colour, shown while the texture loads */
  --ink: #5A4630;        /* small carved letters */
  --text: #3E2E1F;       /* running text, for reading */
  --paint: #7A5233;      /* silver leaf in a letter you touch */
  --cut-dark: rgba(42, 31, 21, 0.42);
  --cut-light: rgba(255, 250, 238, 0.7);   /* matte: weathered stone, the lit edge dull and low */
  --pad: clamp(24px, 4vw, 56px);
  --section-gap: clamp(110px, 16vw, 200px);
}

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

html {
  background: var(--stone);
  color-scheme: light;
  -webkit-text-size-adjust: 100%;
}

body {
  position: relative;
  margin: 0;
  min-height: 100vh;
  min-height: max(600px, var(--screen, 100svh));   /* room for the plaque above the corner wordmark */
  display: flex;
  flex-direction: column;
  padding: var(--pad);
  background: var(--stone) url("stone.webp") 0 0 / 1600px auto repeat;
  color: var(--ink);
  font-family: "Jost", "Futura", "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

/* Soft daylight from the top left, as on a real slab. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 15% 0%, rgba(255, 245, 215, 0.2), rgba(255, 245, 215, 0) 60%);
}
body > * { position: relative; }

/* One page: the first screen, then Projects, then the CV */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
/* --screen: the window's height when the page opened (set in the page's head), kept while scrolling, so
   nothing moves when a phone's toolbars slide away or back (only a turn of the phone resets it) */
.hero { display: flex; flex-direction: column; min-height: calc(var(--screen, 100svh) - 2 * var(--pad)); }
.section-projects, .section-cv { margin-top: var(--section-gap); scroll-margin-top: 24px; }
/* between two sections, halfway down the gap: a carved rule (tools/ornament.py), simple and bold: a sunk
   medallion with my monogram, and one V-groove each way tapering out to a drilled point */
.section-projects::before, .section-cv::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(var(--section-gap) / -2);
  width: min(960px, 100%);
  aspect-ratio: 1920 / 144;
  transform: translate(-50%, -50%);
  background: url("cut-divider.webp") center / contain no-repeat;
  pointer-events: none;
}
.section-projects::before { background-image: url("cut-divider-2.webp"); }   /* the second rule (the same carving for now) */
.section-title { margin: 0; }
.section-projects .section-title { text-align: center; margin-right: -0.3em; }   /* letter-spacing leaves a gap after the last letter */
.section-projects .work { margin-top: clamp(28px, 4vw, 48px); }
.foot { margin-top: clamp(64px, 9vw, 110px); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: 12px 32px; }
.foot .credit { margin: 0; max-width: 560px; }
@media (max-width: 700px) {                       /* on a phone: the foot centred */
  .foot { flex-direction: column; align-items: center; text-align: center; }
  .foot .label a { margin-right: -0.3em; }
}
.foot a { display: inline-block; padding: 12px 0; }

::selection { background: rgba(122, 82, 51, 0.25); }

a {
  color: inherit;
  text-decoration: none;
  transition: color 0.6s ease, text-shadow 0.6s ease;
}
a:hover,
a:focus-visible {
  color: var(--paint);
  text-shadow: -1px -1px 0 rgba(42, 31, 21, 0.4), 1px 1px 0 rgba(255, 250, 238, 0.7);
}
a:focus-visible { outline: 1px solid currentColor; outline-offset: 6px; }

/* A small carved letter: shadow on the upper-left wall, light on the lower-right. */
.cut { text-shadow: -1px -1px 0 var(--cut-dark), 1px 1px 0 var(--cut-light); }

.label {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
}

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

/* Top line: place + local time on the left, links on the right. */
.top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 4px 32px;
  margin-top: calc(-0.4 * var(--pad));          /* a little higher, nearer the top edge */
}
.top > a,
.top > span { display: inline-block; padding: 14px 0; }
.top nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.top nav a {                                    /* each link in a small pill sunk in two levels (tools/ornament.py
                                                   --nav-pill), 9-sliced: its round ends kept, its middle stretched */
  --pill-h: 30px;
  display: inline-block;
  height: var(--pill-h);
  line-height: var(--pill-h);
  margin: 8px 0;
  padding: 0 4px 0 calc(4px + 0.3em);           /* (letter-spacing leaves a gap after the last letter: as much before the first) */
  border-style: solid;
  border-color: transparent;
  border-width: 0 calc(var(--pill-h) / 2);
  border-image: url("cut-nav-pill.webp") 0 34 fill / 0 calc(var(--pill-h) / 2) stretch;
}
.top nav .theme-switch, .top nav .lang-switch { opacity: 0.75; }   /* the theme and the language: quieter last links */
.top [aria-current="page"] { color: var(--paint); }
.time { font-variant-numeric: tabular-nums; }
@media (max-width: 480px) {                       /* the links on one line on a phone */
  .top nav { gap: 4px clamp(4px, 3.2vw - 4px, 12px); margin-inline: calc(12px - var(--pad)); }   /* (into the gutter a little, for the room) */
  .top nav a { --pill-h: 24px; font-size: 10px; letter-spacing: 0.07em; padding: 0 1px 0 calc(1px + 0.07em); }
}
@media (max-width: 360px) {                       /* (the smallest phones: still one line) */
  .top nav { gap: 4px clamp(2px, 3.2vw - 6px, 8px); }
  .top nav a { --pill-h: 22px; font-size: 9px; letter-spacing: 0.04em; padding: 0 0 0 0.04em; }
}
@media (max-width: 700px) {                       /* on a phone: the top line centred, the place over the links */
  .top { flex-direction: column; justify-content: center; gap: 0; }
  .top > span { margin-right: -0.3em; }           /* letter-spacing leaves a gap after the last letter */
  .top nav { justify-content: center; }
}

/* Home: the monogram in its cut frame, small, only the brand's mark, at the top centre (on wide screens
   level with the top line, between the place and the links; narrower, just under it), and the
   inscriptions on the stage below; the wordmark cut in the bottom-left corner */
.hero {
  --logo-w: clamp(120px, 9vw, 150px);          /* the plaque, 0.374 x as tall as wide */
  --logo-h: calc(var(--logo-w) * 0.374);
  --plaque-top: calc(var(--top-h) - 23.3px - var(--logo-h) / 2);   /* its middle on the top line's (23.3 px above the line's end) */
  --ins-top: max(calc(var(--plaque-top) + var(--logo-h) + 48px),
                 calc(var(--screen, 100svh) * 0.45 - var(--pad) - 230px));   /* every inscription from this line, the stage's middle near the optical centre */
}
@media (max-width: 1100px) { .hero { --plaque-top: calc(var(--top-h) + 6px); } }   /* (no room in the top line: under it) */
.stage {
  position: absolute;
  inset: 0;
  bottom: auto;
  z-index: 2;
  display: grid;
  place-items: start center;
  pointer-events: none;
}
.plaque {
  position: relative;
  display: block;
  width: var(--logo-w);                          /* the Corinthian plaque, elongated (~2.7 : 1); the monogram drawn 1.5 x as wide, 1.24 x as tall */
  line-height: 0;
}
.plaque img { display: block; width: 100%; height: auto; }
.plaque, .vine img:not(.vine-paint) { animation: plaque-in 1.6s ease both; }   /* the frame, the monogram and the vine come up as the page opens, in 1.6 s */
@keyframes plaque-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .plaque, .vine img { animation: none; } }
/* while the plaque is under the pointer (once it has come up) the vine takes its living colours
   (tools/vine.py --paint), running out from its middle along every stem, leaf and tendril to its ends;
   leaving, they draw back the same way. Its image's alpha is each place's reach from the middle; a filter
   shows the places within the growing reach (dark.html #vine-grow, set as it grows: inscription.js) */
.vine .vine-paint { position: absolute; inset: 0; filter: url(#vine-grow); opacity: 0.94; visibility: hidden; }
.vine .vine-paint.is-growing { visibility: visible; }
.plaque-mark { position: absolute; inset: 0; }   /* the monogram, in its frame for good */
.plaque-mark img { position: relative; }
.plaque-btn {                 /* the plaque is also the button that shows the inscription about me */
  margin-top: var(--plaque-top);
  pointer-events: auto;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.plaque-btn:focus-visible { outline: 1px solid var(--paint); outline-offset: 10px; }

.hero { --top-h: calc(46.6px - 0.4 * var(--pad)); }          /* where the top line ends, from the hero's top */
@media (max-width: 700px) { .hero { --top-h: calc(87px - 0.4 * var(--pad)); } }   /* (the top line in two rows) */
@media (max-width: 480px) { .hero { --top-h: calc(83px - 0.4 * var(--pad)); } }

/* The Work Hours inscription, carved straight into the stone at the right: cut in, line by line,
   when you touch the plaque or the Projects link (the one about me with the CV link, the GitHub one with the GitHub link). Where there is no room at the side (narrow screens,
   phones) it takes the plaque's place. */
.inscription {
  position: absolute;
  top: var(--ins-top);                          /* every one from the same line, centred on the stage */
  left: 50%;
  transform: translateX(-50%);
  width: 260px;
  text-align: center;
  visibility: hidden;
  transition: visibility 0s linear 0.9s;        /* (after its lines have faded) */
}
.inscription.is-open { visibility: visible; transition-delay: 0s; cursor: pointer; }   /* a click on it leads to its section */
.ins-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.ins-line {
  margin: 0;
  opacity: 0;
  clip-path: inset(-30% 130% -30% -30%);        /* the chisel runs left to right */
  transition: opacity 0.9s ease, clip-path 0s linear 0.9s;   /* leaving: it fades, as the next one is cut in over it */
}
.inscription.is-open .ins-line {
  opacity: 1;
  clip-path: inset(-30% -30% -30% -30%);
  transition: opacity 0.9s ease calc(var(--i) * 170ms), clip-path 1.4s cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--i) * 170ms);   /* slowly, line by line */
}
.ins-kicker { font-size: 16px; letter-spacing: 0.4em; margin-right: -0.4em; margin-top: -0.3125em; }   /* (the capitals' tops on the line every inscription starts from: the photo's top) */
.ins-logo .carved-logo { width: 46px; }
.ins-logo-big .carved-logo { width: 96px; }
.ins-logo-big { margin-top: -4.5px; }                               /* (the mark's top on that same line: its image has a margin) */                        /* the GitHub mark, the one thing in its inscription */
.ins-photo { position: relative; display: block; width: 312px; aspect-ratio: 789 / 740; margin-top: calc(-312px * 6 / 263); }   /* (the frame image has a 6-unit margin: its top on the line every inscription starts from) */   /* the portrait in a simple
   carved frame: a bead and a deep cove (cornice.py --style picture --frame-only) */
.ins-photo-frame { position: absolute; inset: 0; width: 100%; height: 100%; }
.ins-photo-img { position: absolute; left: 50%; top: 50%; width: 87.45%; height: auto; transform: translate(-50%, -50%); }
.ins-name { font-size: 19px; font-weight: 500; line-height: 1.3; letter-spacing: 0.06em; color: var(--text); }
.ins-logo .gilt, .ins-platforms .gilt { opacity: 0.95; }
.ins-title { line-height: 0; width: 100%; }
.ins-title img { display: block; width: 100%; height: auto; margin: 0 auto; }   /* the full width, as in the first inscriptions */
.ins-title-stack { display: flex; flex-direction: column; gap: 2px; }   /* the name, one word below the other */
.ins-rule {
  width: 48px;
  height: 1px;
  background: rgba(42, 31, 21, 0.42);              /* an engraved hairline ... */
  box-shadow: 0 1px 0 rgba(255, 250, 238, 0.48); /* ... and its lit lower edge */
}
.ins-text {                                    /* as large and open as the first inscriptions' */
  font-size: 12px;
  font-weight: 500;
  line-height: 2.1;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink);
}
.ins-platforms { display: flex; align-items: center; justify-content: center; gap: 14px; }
.ins-platforms .carved-logo { height: 24px; }
.ins-platforms .carved-logo img { height: 100%; width: auto; }
.ins-year { font-size: 12px; margin-right: -0.3em; }      /* letter-spacing leaves a gap after the last letter */
.ins-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 22px; font-size: 12px; }
.ins-links a { display: inline-block; padding: 8px 0; margin-right: -0.3em; }

@media (prefers-reduced-motion: reduce) {
  .ins-line, .inscription.is-open .ins-line { clip-path: none; transition: opacity 0.3s ease; }
}
.vine, .inscription.is-left { display: none; }
@media (min-width: 701px) {          /* on the right, as they first stood, centred in their column, straight on the
                                        stone, their middle a little below the optical centre */
  .hero { --frame-top: max(calc(var(--top-h) + 64px), calc(var(--screen, 100svh) * 0.45 - var(--pad) - 245px)); }
  .inscription { top: calc(var(--frame-top) + 51px); left: auto; right: calc(var(--pad) + 30px); transform: none; }
}
@media (min-width: 1300px) {         /* wide screens (html.classic): the plaque big at the optical centre, as it
                                        first stood; on the right the inscriptions, turning */
  .classic .hero {
    --logo-w: min(calc(100vw - 2 * var(--pad) - 720px), 700px);
    --plaque-top: max(60px, calc(var(--screen, 100svh) * 0.4 - var(--pad) - var(--logo-w) * 0.187));
    --frame-top: max(calc(var(--top-h) + 64px), calc(var(--plaque-top) + var(--logo-w) * 0.187 - 240px));   /* the inscriptions' middle on the plaque's */
  }
  .classic .inscription { top: var(--plaque-top); right: calc(12.5% - var(--logo-w) / 8 - 65px); }   /* between the gap's middle and the links' edge */
  .classic .vine {                    /* a grapevine resting on the plaque's top (tools/vine.py) */
    display: block;
    position: absolute;
    left: 50%;
    top: calc(var(--plaque-top) - var(--logo-w) * 0.185);
    width: calc(var(--logo-w) * 0.88);   /* a little inside the frame's corners: crowning it */
    transform: translateX(-50%);
    pointer-events: none;
  }
  .classic .vine img { display: block; width: 100%; height: auto; }
}
@media (max-width: 700px) {          /* phones: in the room between the plaque and the wordmark, the inscriptions,
                                         turning on their own */
  .inscription {
    top: calc((var(--links-bottom, 0px) + var(--mark-top, 100svh)) / 2);   /* midway between the links and the wordmark (inscription.js) */
    transform: translate(-50%, -50%) scale(var(--fit, 0.84));
    transform-origin: center;
  }
  #cv-preview .ins-photo { width: 236px; margin-top: calc(-236px * 6 / 263); }   /* the one about me: a smaller photo, to fit */
  /* (the hero stays one screen tall: the wordmark always on the first screen; an inscription with no
     room above it is left out, inscription.js) */
}
@media (max-width: 380px) {
  .ins-body { gap: 9px; }
  .ins-text { font-size: 10px; line-height: 1.75; }
}

.signature {
  --name-size: clamp(60px, 7.2vw, 112px);      /* the wordmark's font size (Jost Black) */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-top: 160px;
  padding-bottom: 14px;                         /* a little above the bottom margin: the eye reads the block as sitting low */
}
.name { margin: 0; line-height: 0; }
@media (max-width: 700px) {                       /* on a phone: the wordmark, tagline and byline centred, ... */
  .signature { align-items: center; text-align: center; padding-bottom: calc(var(--screen, 100svh) * 0.025); }   /* ... and lifted a hair */
  .hero {                                         /* the plaque small, the vine over it, under the place, over the links */
    --logo-w: 150px;
    --vine-top: calc(40px - 0.4 * var(--pad));    /* (under the place and its time) */
    --plaque-top: calc(var(--vine-top) + var(--logo-w) * 0.185);
    --over-top: calc(var(--plaque-top) + var(--logo-h) + 4px);   /* (the room it takes over the top line) */
  }
  .top nav { margin-top: calc(var(--over-top) - var(--vine-top)); }
  .vine {
    display: block;
    position: absolute;
    left: 50%;
    top: var(--vine-top);
    width: calc(var(--logo-w) * 0.88);
    transform: translateX(-50%);
    pointer-events: none;
  }
  .vine img { display: block; width: 100%; height: auto; }
  .signature .name { width: 100%; }
  .signature .engraved { margin: 0 auto; }
  .tagline { margin-right: -0.3em; white-space: nowrap; font-size: min(13px, 3.2vw); letter-spacing: min(0.3em, 0.6vw); }   /* (one line, however narrow the phone) */
}
.tagline { margin: calc(var(--name-size) * 0.2) 0 0; }
.byline { margin: 8px 0 0; font-size: 14px; letter-spacing: 0.06em; color: var(--ink); }

/* The carved wordmark (an image made by tools/carve.py); its width follows the font size it was set at. */
.engraved {
  display: block;
  width: min(100%, calc(var(--name-size) * 5.1));   /* font size x the word's width (5.1 em) */
  height: auto;
}

/* Projects: the project's number and name carved big, its figures, and carved replicas of the
   app and its website, all on the page's centre axis. Everything is cut into the stone; the engraved
   lines share its light. */
.work { width: 100%; margin-top: clamp(40px, 7vw, 88px); }
.project { display: flex; flex-direction: column; align-items: center; gap: clamp(20px, 2.6vw, 32px); text-align: center; }
.project-num { display: block; width: auto; height: clamp(46px, 4.2vw, 60px); }   /* the Roman I, carved: about the height of the title's letters */   /* the Roman I, carved */
.project-text { width: 100%; min-width: 0; }
.project-kind { margin: 0 0 22px; }
.project-name { display: inline-flex; flex-direction: column; align-items: center; gap: clamp(14px, 1.6vw, 20px); margin: 0 0 24px; line-height: 0; max-width: 100%; }
.project-name .carved-logo { width: clamp(62px, 6vw, 84px); flex: none; }   /* the Work Hours glyph, carved and gilded */
.project-name .carved-logo .gilt { opacity: 0.95; }
.project-name > .project-title { width: min(480px, calc(100vw - 2 * var(--pad))); }   /* in the Work Hours website's own wordmark (Newsreader) */
.project-title .gilt { opacity: 0.95; }                          /* the title painted silver in its cut, for good */
.project-line { max-width: 36em; margin: 0 auto; font-size: 18px; line-height: 1.6; color: var(--text); }
.figures { display: flex; flex-wrap: wrap; justify-content: center; gap: 18px clamp(28px, 4vw, 56px); margin: 30px 0 0; }
.figures div { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.figures dd { margin: 0; font-size: 30px; font-weight: 500; line-height: 1; letter-spacing: 0.04em; color: var(--text); }
.figures dd.rating { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.rating .value { display: none; }
.rating.is-rated .value { display: block; }                  /* a rating: the figure, then the stars */
.stars { position: relative; display: inline-block; width: max-content; font-size: 18px; line-height: 1; letter-spacing: 0.18em; }
.stars-empty { color: transparent; -webkit-text-stroke: 1px rgba(90, 70, 48, 0.55); }
.stars-fill { position: absolute; inset: 0 auto 0 0; width: 0; overflow: hidden; white-space: nowrap; color: rgba(62, 46, 31, 0.9); }
.note { font-size: 12px; font-weight: 400; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink); }
.specs dd.platforms { display: flex; align-items: center; gap: 18px; padding: 2px 0; }
.platforms .carved-logo { height: 34px; }
.platforms .carved-logo img { height: 100%; width: auto; }
.platforms .gilt, .social .gilt { opacity: 0.95; }          /* gilded for good, not only on hover */
.specs { margin: 30px auto 0; max-width: 560px; text-align: left; }
.specs div {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr);
  gap: 4px 20px;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid rgba(42, 31, 21, 0.3);            /* an engraved hairline ... */
  box-shadow: 0 1px 0 rgba(255, 250, 238, 0.36);            /* ... and its lit lower edge */
}
.specs dd { margin: 0; font-size: 16px; line-height: 1.5; color: var(--text); }
.case { text-transform: none; }
.credit { margin: 28px 0 0; font-size: 11px; line-height: 1.6; letter-spacing: 0.04em; color: var(--ink); opacity: 0.7; }

.replicas { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: 48px clamp(100px, 19vw, 300px); margin-top: clamp(48px, 7vw, 80px); }
.replica { margin: 0; display: flex; flex-direction: column; gap: 16px; }
.replica figcaption { text-align: center; }
.replica img { display: block; height: auto; }
.replica-app .phone img { width: min(46vw, 230px); }

/* the store chooser: touching one side of the phone, its store's logo appears in the middle of that
   side of the screen, carved and silvered; each side of the phone leads to its store */
.app-stage { display: flex; flex-direction: column; align-items: center; }
.phone { position: relative; }
.half { position: absolute; top: 0; bottom: 0; width: 50%; cursor: pointer; }
.half-play { left: 0; }
.half-apple { right: 0; }
.is-soon { cursor: default; }
.half-logo { position: absolute; top: 50%; left: 50%; height: 56px; transform: translate(-50%, -50%); }   /* always there */
.replica-app .phone .half-logo img { height: 100%; width: auto; }   /* (not the phone's own width) */
.half-play .half-logo { width: 48px; }                            /* the logos' own proportions (192 x 224, 192 x 192) */
.half-apple .half-logo { width: 56px; }
.half-logo .gilt { opacity: 0.95; }
.soon { position: absolute; left: 0; right: 0; top: calc(50% + 46px); text-align: center; font-size: 10px;
  letter-spacing: 0.28em; color: var(--paint); opacity: 0; transition: opacity 0.4s ease; margin-right: -0.28em; }
.half-apple:hover .soon { opacity: 1; }
/* a carved logo; silver leaf is laid into its cut when its link is touched */
.carved-logo { position: relative; display: block; line-height: 0; }
.carved-logo img { position: relative; display: block; width: 100%; height: auto; }
.gilt {
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, #9A6E4A 0%, #6E4829 45%, #4A2E18 100%);   /* silver leaf */
  -webkit-mask-size: 100% 100%;                 /* the logo's silhouette is set on the element (shape-*.png) */
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  opacity: 0;
  transition: opacity 0.45s ease;
}
.gilt.silver { background: linear-gradient(160deg, #9A6E4A 0%, #6E4829 45%, #4A2E18 100%); }   /* silver leaf */
/* painted: the leaf as real paint laid into the cut (paint-*.webp from tools/carve.py: lit by the
   same light as the walls, stopping a hair short of the edge), over the carving instead of under it */
.gilt.painted { z-index: 1; background-color: transparent; background-size: 100% 100%; background-repeat: no-repeat;
  -webkit-mask-image: none; mask-image: none; }
.logo-link:hover .gilt,
.logo-link:focus-visible .gilt { opacity: 0.92; }
.logo-link:focus-visible { outline: 1px solid var(--paint); outline-offset: 8px; }

/* the label's arrow turns silver with its carving */
.replica figcaption span { transition: color 0.4s ease; }
.replica-app:has(.half-play:hover) figcaption span,
.replica-site:has(.site-link:hover) figcaption span { color: var(--paint); }

.specs dd.stacked { display: flex; flex-direction: column; gap: 4px; }
.specs dd.stacked a, .specs dd a:not(.logo-link) { text-decoration: underline; text-decoration-color: rgba(62, 46, 31, 0.3); text-underline-offset: 4px; }
.specs dd.social { display: flex; gap: 18px; }
.social .carved-logo { width: 34px; }
.replica-site img { width: min(88vw, 560px); }


@media (max-width: 760px) {
  .project { gap: 20px; }
  .project-num { height: 42px; }
  .figures dd { font-size: 24px; }
  .specs div { grid-template-columns: 110px minmax(0, 1fr); }
}

/* CV: first a few lines about me, then the portrait and the essentials, centred */
.about { max-width: 36em; margin: 0 auto clamp(48px, 7vw, 88px); text-align: center; }
.about-title { margin: 0 -0.3em clamp(28px, 4vw, 48px) 0; }   /* (as far from its text as Projects' heading is from its content) */                            /* letter-spacing leaves a gap after the last letter */
.about-text { margin: 0; font-size: 18px; line-height: 1.7; color: var(--text); }

/* CV: the portrait, central; the essentials on one line under it */
.cv section.person { display: flex; flex-direction: column; align-items: center; padding: 0; margin: 0 auto clamp(48px, 7vw, 88px); }
.portrait { margin: 0; }
.portrait img { display: block; width: min(66vw, 340px); height: auto; }
.person-line {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 6px 14px;
  margin: 28px 0 0;
  text-align: center;
}
.person-line .sep { color: var(--ink); opacity: 0.6; }
@media (max-width: 700px) {                       /* on a phone: one under the other, centred, no points left hanging */
  .person-line { flex-direction: column; gap: 6px; }
  .person-line .sep { display: none; }
}
.person-line > .cut, .person-line > a.cut, .person-line .sep { margin-right: -0.3em; }   /* letter-spacing leaves a gap after the last letter: take it back, so both ends sit the same distance from the edges */
.person-line a { padding: 8px 0; }
.person-x { display: inline-flex; margin-top: 22px; padding: 4px; }   /* X, under the portrait */
.person-x .carved-logo { width: 30px; }
.person-x .gilt { opacity: 0.95; }                         /* silvered for good, not only on hover */
.cv { width: 100%; max-width: 980px; margin-left: auto; margin-right: auto; }
.cv section { padding: 28px 0 20px; }

@media (max-width: 720px) { .cv section { padding-top: 20px; } }
}
