/* ==========================================================================
   Overplus — overplus.ca
   A two-colour print sheet: newsprint, ink, and one fluorescent red.

   The three brand anchors come from logo/overplus_logo.py. If they change
   there (and the logo is regenerated), change them here to match.

   Colour rule: red is the fifth tile. It shows up as a small square — a
   bullet, the switch, a puzzle tile — or as a thin rule. Never as text and
   never as a big background. (Red on paper is only 3.2:1.)

   The page is built from the same parts as joeyvilleneuve.ca — the header,
   numbered sections, project cards and their popup, the closing contact
   band — so the two sites stay in step. Change a shared part on both.
   ========================================================================== */

:root{
  /* brand anchors — keep in sync with logo/overplus_logo.py */
  --ink:#1C1A17;
  --paper:#E9E6DF;
  --red:#FC0345;
  /* the one accent the shared components use (labels, buttons, links, switch);
     joeyvilleneuve.ca uses the same components with mint here */
  --accent:var(--red);
  /* The switch thumb is a control, so it needs 3:1 on the ground. Red has it;
     joeyvilleneuve.ca deepens its mint here. */
  --accent-strong:var(--accent);

  /* light — the default */
  --ground:var(--paper);
  --figure:var(--ink);
  --muted:#57524A;          /* secondary text, 6.2:1 on paper */
  --rule:#C0B9AB;           /* decorative hairlines */
  --line:#7E776B;           /* control outlines and link underlines, 3.6:1 on paper */
  --raised:#F5F3EE;         /* panels, cards and the closing band: a warm white */
  --media:#DDD8CE;          /* behind posters and video */
  --slot:#DDD8CE;           /* an unlit puzzle tile */
  --grain-blend:multiply;
  --grain-opacity:.22;

  --sans:"Archivo","Helvetica Neue",Helvetica,Arial,sans-serif;
  --serif:"Newsreader","Iowan Old Style",Georgia,serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  --wrap:80rem;
  --gutter:clamp(1.25rem,4vw,3rem);
  --ease:cubic-bezier(.2,.7,.2,1);

  color-scheme:light;
}

/* dark — only when someone picks it with the switch in the masthead */
:root[data-theme="dark"]{
  --ground:var(--ink);
  --figure:var(--paper);
  --muted:#A39C90;          /* 6.4:1 on ink */
  --rule:#3A3631;
  --line:#716B61;           /* 3.3:1 on ink */
  --raised:#24211D;
  --media:#141210;
  --slot:#35312B;
  --grain-blend:screen;
  --grain-opacity:.05;
  color-scheme:dark;
}

/* ── base ────────────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}

html{
  -webkit-text-size-adjust:100%;
  background:var(--ground);
  scroll-behavior:smooth;
  scroll-padding-top:5rem;   /* a section you jump to clears the sticky masthead */
}
/* At least a screen tall, so the closing band always sits at the bottom; when
   there's room to spare (no projects yet, a tall screen) the hero centres in it. */
body{
  margin:0;
  min-height:100vh;
  min-height:100svh;
  display:flex; flex-direction:column;
  background:var(--ground);
  color:var(--figure);
  font-family:var(--sans);
  font-size:clamp(1rem,.95rem + .2vw,1.0625rem);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
main{flex:1; display:flex; flex-direction:column; justify-content:center}

img,video{display:block; max-width:100%; height:auto}
h1,h2,h3{text-wrap:balance}
p{text-wrap:pretty}
b{font-weight:700}
[hidden]{display:none !important}

::selection{background:var(--accent); color:var(--ink)}
:focus-visible{outline:2px solid var(--figure); outline-offset:3px}

/* no scrolling the page behind a popup or the puzzle */
html:has(dialog[open]){overflow:hidden}

/* Press grain. Kept light — on paper it multiplies over every glyph, so
   anything above ~.25 starts eating text contrast. */
body::after{
  content:"";
  position:fixed; inset:0; z-index:99;
  pointer-events:none;
  opacity:var(--grain-opacity);
  mix-blend-mode:var(--grain-blend);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.2'/%3E%3C/svg%3E");
}

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

.label{
  font-family:var(--mono);
  font-size:.75rem; font-weight:500; line-height:1.4;
  letter-spacing:.13em; text-transform:uppercase;
  color:var(--muted);
}

/* read by screen readers, not shown */
.visually-hidden{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

.skip{
  position:absolute; left:var(--gutter); top:-5rem; z-index:100;
  padding:.65rem .9rem;
  font:500 .75rem/1 var(--mono); letter-spacing:.1em; text-transform:uppercase;
  color:var(--ground); background:var(--figure); text-decoration:none;
}
.skip:focus{top:.75rem}

/* the fifth tile, used as a bullet */
.sq{display:inline-block; flex:none; width:7px; height:7px; background:var(--accent)}
.kicker{display:flex; align-items:center; gap:.6rem; margin:0}

/* ── buttons ─────────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex; align-items:center; gap:.65rem;
  padding:.85rem 1.15rem;
  font-family:var(--mono);
  font-size:.75rem; font-weight:500; line-height:1;
  letter-spacing:.1em; text-transform:uppercase;
  color:var(--figure); background:transparent;
  border:1px solid var(--figure); border-radius:0;
  text-decoration:none; cursor:pointer;
  transition:background-color .2s, color .2s;
}
.btn--solid{background:var(--figure); color:var(--ground)}
/* Hover inverts a button, but only with a real pointer: on a touch screen a
   tap leaves :hover stuck on, so a button would still be inverted when you
   came back to the tab. The same goes for every hover on the page. */
@media (hover:hover){
  .btn:hover{background:var(--figure); color:var(--ground)}
  .btn--solid:hover{background:transparent; color:var(--figure)}
}
/* the fifth tile, riding along on the primary button */
.btn--solid::before{content:""; flex:none; width:.5rem; height:.5rem; background:var(--accent)}
.btn--small{padding:.7rem .85rem}

/* ── links ───────────────────────────────────────────────────────────────── */
/* a link in running text: an underline you can see, accent on hover — the
   same as joeyvilleneuve.ca's .text_link */
.text-link{
  color:inherit;
  text-decoration:underline;
  text-decoration-color:var(--line);
  text-decoration-thickness:max(1px,.06em);
  text-underline-offset:.18em;
  transition:text-decoration-color .2s;
}
@media (hover:hover){.text-link:hover{text-decoration-color:var(--accent)}}

/* "↗" marks a link that leaves the site; point at the link and it nudges
   toward where it goes. Buttons skip it: being a button already says it's
   a link. */
.arrow{display:inline-block; transition:transform .25s var(--ease)}

/* Boxes you can press (cards, filters, the menu button) answer a hover with a
   2px ink outline: the border darkens and a 1px ring doubles it. The ring is
   a shadow, so nothing shifts. Only with a real pointer: on a touch screen a
   tap leaves :hover stuck on. Same as joeyvilleneuve.ca. */
@media (hover:hover){
  a:hover .arrow{transform:translate(2px,-2px)}
  .filter:hover,
  .card:hover,
  .menu-button:hover{border-color:var(--figure); box-shadow:0 0 0 1px var(--figure)}
}

/* ── masthead ────────────────────────────────────────────────────────────── */
/* sticks to the top as the page scrolls; solid, like the rest of the sheet */
.masthead{
  position:sticky; top:0; z-index:50;
  background:var(--ground);
  border-bottom:1px solid var(--rule);
}
.masthead__inner{
  position:relative;
  display:flex; align-items:center; justify-content:space-between;
  gap:1rem 2rem;
  min-height:3.75rem;
}
.lockup{display:inline-flex; align-items:center; gap:.6rem; color:inherit; text-decoration:none}
.lockup span{font-size:1rem; font-weight:700; letter-spacing:-.015em}

/* ── the mark, inline ─────────────────────────────────────────────────────
   The marks on the page (the masthead's, and the big one in the hero) are
   the logo files' own SVG written inline — the 24px file up top, the 1024px
   file in the hero, same viewBox and rects — coloured here, so each tile can
   move. Point at one and its tiles turn over in a wave, left to right, the
   way tiles flip in Flip, landing on the red one last (main.js adds the
   class). Inline SVG draws the same way at rest and mid-turn; tiles built
   from boxes shifted a pixel as a turn began and ended. */
.mark{display:block; flex:none; width:24px; height:24px}
.mark rect{fill:var(--figure); transform-box:fill-box; transform-origin:center}
.mark rect:nth-child(4){fill:var(--red)}                                  /* the right tile */
/* the wave: the left tile turns first, the middle column 90ms later, the red tile last */
.mark.is-flipping rect{animation:mark-flip .45s 90ms cubic-bezier(.55,0,.25,1) both}
.mark.is-flipping rect:nth-child(2){animation-delay:0s}
.mark.is-flipping rect:nth-child(4){animation-delay:180ms}
/* a half turn, seen side-on: a square lands looking just as it started */
@keyframes mark-flip{to{transform:scaleX(-1)}}
/* Windows high-contrast mode: draw the tiles in the text colour */
@media (forced-colors:active){.mark{forced-color-adjust:none} .mark rect{fill:CanvasText}}

/* section links: a red rule grows under the one you point at */
.nav{display:flex; align-items:center; gap:clamp(1rem,2.4vw,2rem)}
.nav__link{
  padding:.45rem 0;
  font-family:var(--mono);
  font-size:.75rem; font-weight:500;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--figure); text-decoration:none;
  background:linear-gradient(var(--accent),var(--accent)) 0 100% / 0 2px no-repeat;
  transition:background-size .25s var(--ease);
}
@media (hover:hover){.nav__link:hover{background-size:100% 2px}}

/* on phones the links and the switch fold into this menu (see the bottom) */
.menu-button{
  display:none;
  padding:.6rem .85rem;
  font:500 .75rem/1 var(--mono);
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--figure);
  background:none;
  border:1px solid var(--line);
  cursor:pointer;
  transition:border-color .2s, box-shadow .2s;
}
.menu-button[aria-expanded="true"]{border-color:var(--figure)}

/* ── the light / dark switch ─────────────────────────────────────────────
   A real switch (role="switch"), labelled on both sides. The thumb is the
   fifth tile, so it stays red either way — its position is the state. */
.mode{
  --w:2.6rem;
  --h:1.35rem;
  --pad:3px;
  display:inline-flex; align-items:center; gap:.65rem;
  margin:0; padding:.4rem 0;
  font-family:var(--mono);
  font-size:.75rem; font-weight:500; line-height:1;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted);
  background:none; border:0;
  cursor:pointer;
}
.mode__track{
  position:relative; flex:none;
  width:var(--w); height:var(--h);
  border:1.5px solid var(--figure);
  transition:background-color .2s;
}
@media (hover:hover){.mode:hover .mode__track{background:color-mix(in srgb, var(--figure) 8%, transparent)}}
.mode__thumb{
  position:absolute; top:var(--pad); left:var(--pad);
  width:calc(var(--h) - 3px - 2 * var(--pad));
  height:calc(var(--h) - 3px - 2 * var(--pad));
  background:var(--accent-strong);
  transition:transform .3s var(--ease);
}
.mode[aria-checked="true"] .mode__thumb{transform:translateX(calc(var(--w) - var(--h)))}
.mode__label{transition:color .2s}
.mode[aria-checked="false"] .mode__label--light,
.mode[aria-checked="true"] .mode__label--dark{color:var(--figure)}

/* ── hero ────────────────────────────────────────────────────────────────── */
.hero{padding-block:clamp(2.5rem,8vh,5.5rem) clamp(1rem,3vh,2.5rem)}
.hero .wrap{container-type:inline-size}

/* One font-size drives the mark and the word, so the lockup keeps its
   proportions at every width; cqi sizes it to the column, not the window. */
.hero__lockup{
  display:flex; align-items:center; gap:.19em;
  font-size:clamp(3rem,15vw,14rem);
  font-size:clamp(3rem,18.6cqi,14rem);  /* ≈ the full column width */
  animation:rise .9s var(--ease) backwards;
}
.hero__lockup h1{
  margin:0;
  font-size:1em; font-weight:800;
  letter-spacing:-.045em; line-height:.9;
}

/* The mark is also a button — press it and Flip opens. On hover its tiles
   turn over in a wave (see .mark); pressed, it gives a little. */
.hero__mark{
  flex:none; display:block;
  width:.96em; height:.96em;
  margin:0; padding:0;
  font:inherit; color:inherit;
  background:none; border:0;
  cursor:pointer;
  transition:transform .35s var(--ease);
}
.hero__mark .mark{width:100%; height:100%}
.hero__mark:active{transform:scale(.97)}
.hero__mark:focus-visible{outline-offset:.05em}

.hero__row{
  display:grid; grid-template-columns:minmax(0,1.25fr) minmax(0,.85fr);
  gap:clamp(2rem,6vw,6rem); align-items:start;
  margin-top:clamp(1.75rem,4.5vh,3rem);
  padding-top:clamp(1.5rem,3.5vh,2.25rem);
  border-top:1px solid var(--rule);
}
.hero__intro{animation:rise .9s .12s var(--ease) backwards}
.lede{
  margin:0; max-width:28ch;
  font-size:clamp(1.35rem,1rem + 1.35vw,2.1rem); font-weight:500;
  line-height:1.28; letter-spacing:-.02em;
}

@keyframes rise{from{opacity:0; transform:translateY(20px)}}

/* ── panels ──────────────────────────────────────────────────────────────
   One flat style for the definition, the popups and Flip: a solid white
   sheet with a hairline border. */
.panel{
  background:var(--raised);
  border:1px solid var(--rule);
}

.definition{
  padding:clamp(1.4rem,2.6vw,2.1rem);
  animation:rise .9s .24s var(--ease) backwards;
}
.definition p{margin:0}
.definition .kicker{margin-bottom:1.1rem}
.definition__head{display:flex; flex-wrap:wrap; align-items:baseline; gap:.2rem .65rem}
.definition dfn{
  font-family:var(--serif); font-style:normal;
  font-size:1.65rem; font-weight:600; line-height:1.1;
}
.definition .pos{font-family:var(--serif); font-style:italic; font-size:1.1rem; color:var(--muted)}
.definition .pron{
  margin-top:.35rem;
  font-family:var(--mono); font-size:.8rem; letter-spacing:.04em;
  color:var(--muted);
}
.definition .definition__body{
  margin-top:1rem;
  font-family:var(--serif);
  font-size:clamp(1.3rem,1.1rem + .55vw,1.6rem); font-weight:500;
  line-height:1.4;
}

/* ── sections ────────────────────────────────────────────────────────────
   Each opens with a hairline (the same line the panels use) and a two-column
   head: number and title on the left, what it holds on the right. One line
   weight everywhere keeps the page quiet. Same as joeyvilleneuve.ca. */
.section{padding-top:clamp(4.5rem,10vw,7.5rem)}
.section__head{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  align-items:end;
  gap:1rem 3rem;
  margin-bottom:clamp(1.75rem,4vw,2.75rem);
  padding-top:1.1rem;
  border-top:1px solid var(--rule);
}
.section__index{margin:0 0 .9rem}
.section__head h2,
.footer__contact h2{
  margin:0;
  font-size:clamp(2rem,1.4rem + 2.4vw,3.25rem); font-weight:800;
  letter-spacing:-.04em; word-spacing:.05em; line-height:.95;
}
.section__intro{justify-self:end; max-width:44ch; margin:0; color:var(--muted)}

/* ── filters ─────────────────────────────────────────────────────────────── */
.filters{display:flex; flex-wrap:wrap; gap:.5rem}
.filter{
  display:inline-flex; align-items:center; gap:.5rem;
  padding:.6rem .85rem;
  font:500 .75rem/1 var(--mono);
  letter-spacing:.1em; text-transform:uppercase;
  color:var(--figure);
  background:transparent;
  border:1px solid var(--line); border-radius:0;
  cursor:pointer;
  transition:border-color .2s, background-color .2s, color .2s, box-shadow .2s;
}
/* the chosen filter is a solid button, tile and all */
.filter[aria-pressed="true"]{color:var(--ground); background:var(--figure); border-color:var(--figure)}
.filter[aria-pressed="true"]::before{content:""; width:.45rem; height:.45rem; background:var(--accent)}
.filters__count{margin:1rem 0 1.25rem}

/* ── project cards ───────────────────────────────────────────────────────
   Same as joeyvilleneuve.ca: a poster, and a looping preview that plays only
   while the mouse is over the card — one at a time. */
.projects{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(min(100%,19rem),1fr));
  gap:1.25rem;
}
.card{
  display:flex; flex-direction:column;
  margin:0; padding:0;
  font:inherit; color:inherit; text-align:left;
  background:var(--raised);
  border:1px solid var(--rule); border-radius:0;
  cursor:pointer;
  /* the card stays put on hover (no lift), so the pointer never slips off its
     edge; the outline and the preview are the response */
  transition:border-color .25s var(--ease), box-shadow .25s var(--ease);
  animation:rise .6s var(--ease) backwards;
  animation-delay:calc(var(--i,0) * 40ms);
}
.card__media{position:relative; display:block; aspect-ratio:16 / 10; overflow:hidden; background:var(--media)}
.card__poster,
.card__video{position:absolute; inset:0; width:100%; height:100%; object-fit:cover}
/* the preview fades in over the poster once it's actually playing */
.card__video{z-index:1; opacity:0; transition:opacity .25s ease}
.card.is-playing .card__video{opacity:1}
.card__number{
  position:absolute; top:.6rem; right:.6rem; z-index:2;
  display:inline-flex; align-items:center; gap:.4rem;
  padding:.2rem .45rem;
  font:500 .75rem/1.3 var(--mono); letter-spacing:.08em;
  color:var(--paper); background:var(--ink);
}
/* a red tile lights up in the corner while the preview plays */
.card.is-playing .card__number::before{content:""; width:6px; height:6px; background:var(--accent)}
.card__body{display:flex; flex-direction:column; gap:.45rem; padding:1rem 1.1rem 1.15rem}
.card__title{font-size:1.15rem; font-weight:700; letter-spacing:-.02em; line-height:1.2}
.card__tech{font-size:.875rem; color:var(--muted)}

/* ── the project popup ───────────────────────────────────────────────────── */
.modal{
  width:min(100% - 2 * var(--gutter), 52rem);
  max-width:none;
  max-height:calc(100% - 2rem);
  margin:auto; padding:0;
  color:var(--figure);
  overflow:auto;
  overscroll-behavior:contain;
}
/* literal colour: ::backdrop doesn't reliably inherit custom properties yet */
.modal::backdrop{background:rgba(28,26,23,.6)}
.modal[open]{animation:sheet-in .35s var(--ease)}
.modal__inner{padding:clamp(1.1rem,3vw,2rem)}
.modal__top{display:flex; align-items:center; justify-content:space-between; gap:1rem}
.modal__title{
  margin:.9rem 0 1rem;
  font-size:clamp(1.6rem,1.2rem + 1.6vw,2.4rem); font-weight:800;
  letter-spacing:-.04em; line-height:.95;
}
.modal__media{margin-bottom:1rem; background:var(--media)}
.modal__media video{width:100%; height:auto; max-height:62vh; margin:0 auto; object-fit:contain}
.modal__tech{margin:0; font-size:.9rem; color:var(--muted)}
.modal__body{max-width:62ch; margin:.75rem 0 0; color:var(--muted)}
.modal__links{display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1.25rem}

/* ── Flip: the puzzle hidden in the mark ─────────────────────────────────── */
.flip{
  width:min(100% - 2 * var(--gutter), 56rem);
  max-width:none;
  max-height:calc(100% - 2rem);
  margin:auto; padding:0;
  color:var(--figure);
  overflow:auto;
  overscroll-behavior:contain;
}
/* literal colour: ::backdrop doesn't reliably inherit custom properties yet */
.flip::backdrop{background:rgba(28,26,23,.45)}
.flip[open]{animation:sheet-in .4s var(--ease)}
.flip[open]::backdrop{animation:fade-in .4s ease}
@keyframes sheet-in{from{opacity:0; transform:translateY(1.5rem)}}
@keyframes fade-in{from{opacity:0}}

.flip__inner{padding:clamp(1.25rem,3.5vw,2.75rem)}
.flip__top{display:flex; align-items:center; justify-content:space-between; gap:1rem}

.flip__layout{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  grid-template-areas:"intro board" "play board";
  align-items:start;
  gap:1.5rem clamp(1.75rem,4vw,3.5rem);
  margin-top:clamp(1rem,2.5vw,1.75rem);
}
.flip__intro{grid-area:intro}
.flip__play{grid-area:play}
.flip h2{
  margin:0 0 .9rem;
  font-size:clamp(2.5rem,1.8rem + 2.6vw,4rem); font-weight:800;
  letter-spacing:-.05em; line-height:.9;
}
.flip__intro p{margin:0; max-width:40ch}

.flip__stats{display:flex; gap:clamp(1.5rem,4vw,3rem); margin:0}
.flip__stats div{min-width:4.5rem}
.flip__stats dd{
  margin:.35rem 0 0;
  font-size:clamp(2.25rem,1.8rem + 1.5vw,3rem); font-weight:800;
  letter-spacing:-.04em; line-height:1;
  font-variant-numeric:tabular-nums;
}
.flip__status{min-height:1.6em; margin:1.25rem 0 0; color:var(--muted); font-size:.95rem}
.flip__status.is-win{color:var(--figure); font-weight:600}
.flip__controls{display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1.25rem}

/* The board is the logo's own grid carried out to 5×5: tiles and gaps in
   the mark's 26:4 ratio (5 tiles + 4 gaps = 146 units), so a finished
   board has the logo's true proportions. */
.flip__stage{
  position:relative;
  grid-area:board; align-self:center;
  width:min(100%,24rem);
  margin-inline:auto;
  container-type:inline-size;
}
.flip__board{
  display:grid; grid-template-columns:repeat(5,minmax(0,1fr));
  gap:8px;
  gap:calc(100cqi * 4 / 146);
  perspective:800px;
  touch-action:manipulation;
}
.tile{
  position:relative;
  aspect-ratio:1;
  margin:0; padding:0;
  border:0; border-radius:0;
  background:var(--slot);
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  /* the colour swaps halfway through the flip, when the tile is edge-on */
  transition:background-color 0s linear calc(var(--d,0ms) + 90ms), box-shadow .15s;
}
.tile.is-on{background:var(--figure)}
.tile.is-flipping{animation:tile-flip .18s var(--d,0ms) ease-in-out}
@keyframes tile-flip{50%{transform:rotateY(90deg)}}

/* what a press would flip — red, as a rule */
.tile.is-near{box-shadow:inset 0 0 0 1px var(--red)}
.tile.is-aim{box-shadow:inset 0 0 0 2px var(--red)}
.tile.is-hint{animation:tile-hint .6s ease-in-out 3}
@keyframes tile-hint{50%{box-shadow:inset 0 0 0 5px var(--red)}}
.tile:focus-visible{outline:2px solid var(--figure); outline-offset:2px; z-index:1}

/* The goal: a dashed plus drawn through the gaps around the mark's five
   tiles, so it never sits on top of one. The offset starts each corner
   mid-dash, so the dashes wrap the corners evenly. */
.flip__target{
  position:absolute; inset:0;
  width:100%; height:100%;
  overflow:visible;
  pointer-events:none;
  transition:opacity .4s ease;
}
.flip__target path{
  fill:none;
  stroke:var(--figure);
  stroke-width:.6;
  stroke-dasharray:3 2;
  stroke-dashoffset:1.5;
  opacity:.55;
}

/* Solved. Everything outside the mark fades away (main.js staggers --f out
   from the centre), then the right-hand tile slowly prints red — a red
   square spreading from its middle, like ink. */
.is-solved .tile{
  cursor:default;
  transition:
    background-color 0s linear calc(var(--d,0ms) + 90ms),
    opacity .5s ease calc(var(--f,0ms) + 250ms),
    transform .6s var(--ease) calc(var(--f,0ms) + 250ms);
}
.is-solved .tile:not(.is-on){opacity:0; transform:scale(.6)}
.is-solved .flip__target{opacity:0; transition-delay:.2s}

/* The red grows from the tile's exact centre by clipping, not scaling: a clip
   opens all four edges together and lands crisply, where a scaled layer's
   long easing tail left the bottom edge visibly catching up. */
.tile::before{
  content:"";
  position:absolute; inset:0;
  background:var(--red);
  clip-path:inset(50%);
}
.tile.is-accent::before{
  clip-path:inset(0);
  transition:clip-path .75s cubic-bezier(.4,0,.2,1) .65s;
}

/* ── the closing band: contact and the small print ───────────────────────
   The end of the page is one piece, set apart by its raised ground and a
   hairline — the same band as joeyvilleneuve.ca's. */
.footer{
  margin-top:clamp(5rem,11vw,8rem);
  background:var(--raised);
  border-top:1px solid var(--rule);
}
.footer__contact{
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  align-items:end;
  gap:1.75rem 3rem;
  padding-block:clamp(2.25rem,5vw,3.5rem);
}
/* how to reach us, said in a sentence with the address as a link in it —
   the same as joeyvilleneuve.ca's */
.footer__meta{
  max-width:44ch;
  margin:1.25rem 0 0;
  font-style:normal;
  color:var(--muted);
}
.footer__meta p{margin:0}
.footer__meta .text-link{color:var(--figure)}
.footer__buttons{display:flex; flex-wrap:wrap; gap:.75rem}
.footer__bar{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:.4rem 2rem;
  padding-block:1.1rem 1.3rem;
  border-top:1px solid var(--rule);
}
/* the founder's site, set like a nav link (a red rule grows under it) — the
   same as joeyvilleneuve.ca's link back here */
.footer__sibling{
  display:inline-block; padding:.3rem 0;
  font-family:var(--mono);
  font-size:.75rem; font-weight:500;
  letter-spacing:.13em; text-transform:uppercase;
  color:var(--figure);
  text-decoration:none;
  background:linear-gradient(var(--accent),var(--accent)) 0 100% / 0 2px no-repeat;
  transition:background-size .25s var(--ease);
}
@media (hover:hover){.footer__sibling:hover{background-size:100% 2px}}

/* ── 404 ─────────────────────────────────────────────────────────────────── */
.lost{
  display:flex; flex-direction:column; justify-content:center; align-items:flex-start;
  gap:1.25rem;
  min-height:calc(100vh - 3.75rem);
  min-height:calc(100svh - 3.75rem);
  padding-block:3rem;
}
.lost h1{
  margin:0;
  font-size:clamp(2.75rem,1.75rem + 6vw,8rem); font-weight:800;   /* "requirements." must fit a 375px phone */
  letter-spacing:-.055em; word-spacing:.08em; line-height:.88;
}
.lost p:not(.label){margin:0; max-width:40ch; color:var(--muted); font-size:1.1rem}

/* ── responsive ──────────────────────────────────────────────────────────── */
@media (max-width:900px){
  .section__head{grid-template-columns:minmax(0,1fr)}
  .section__intro{justify-self:start}
  .footer__contact{grid-template-columns:minmax(0,1fr)}
}

@media (max-width:860px){
  /* stacked, a little tighter: the rule gets equal space above and below */
  .hero__row{grid-template-columns:minmax(0,1fr); row-gap:1.5rem; margin-top:clamp(1.5rem,3.5vh,3rem)}
  .definition{max-width:34rem}
}

@media (max-width:760px){
  /* the section links and the switch drop down under the masthead */
  .menu-button{display:inline-flex}
  .nav{
    position:absolute; top:100%; left:0; right:0;
    flex-direction:column; align-items:stretch; gap:0;
    padding:.25rem var(--gutter) 1.25rem;
    background:var(--ground);
    border-bottom:1px solid var(--rule);
    visibility:hidden; opacity:0; transform:translateY(-.5rem);
    transition:opacity .2s, transform .2s, visibility 0s .2s;
  }
  .nav.is-open{visibility:visible; opacity:1; transform:none; transition:opacity .2s, transform .2s}
  .nav__link{padding:.9rem 0; font-size:.8rem; border-bottom:1px solid var(--rule); background:none}
  .nav .mode{margin-top:1rem}

  /* The contact buttons split the width evenly. With an odd number, the
     first (the solid one) gets a row to itself, so none is left alone. */
  .footer__buttons{display:grid; grid-template-columns:repeat(2,minmax(0,1fr))}
  .footer__buttons .btn{justify-content:center}
  .footer__buttons > :first-child:nth-last-child(odd){grid-column:1 / -1}
  .footer__bar{gap:.4rem 1rem}

  /* on narrow screens the board comes straight after the title */
  .flip__layout{
    grid-template-columns:minmax(0,1fr);
    grid-template-areas:"intro" "board" "play";
  }
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none !important; transition:none !important}
}
