/* ==========================================================================
   shell.css — the pieces every page shares in the redesign (docs/home-concept.md §0 and §5):
   header on the grid, view switch, System view, hover tag, footer.
   Loaded on every page after about.css (it uses the type roles and motion tokens defined there
   and in custom.css). Sizes come from the prototypes, whose em differs from the site's on
   tablet and large phones: --shell-k converts them.
   ========================================================================== */

:root {
  --shell-k: 1;
  --shell-rule: color-mix(in srgb, var(--dark-brown) 22%, var(--sand));
}

/* Tablet 768–991: the site root is 1.92vw, the prototypes' 1.15vw */
@media screen and (min-width: 768px) and (max-width: 991px) {
  :root {
    --shell-k: 0.6;
  }
}

/* 480–767: the site root is 2.9vw, the prototypes' 4.1vw; at 479 and below they match */
@media screen and (min-width: 480px) and (max-width: 767px) {
  :root {
    --shell-k: 1.414;
  }
}

/* --- Header on the grid ---------------------------------------------------------------------
   Moiséz c1–c3 · Based in Montevideo c4–c7 · Available c8–c9 · Menu c12. Below 992 the bar is
   already brand + Menu on the outer lines.                                                    */
@media screen and (min-width: 992px) {
  [data-header-bar] {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    /* The row is taller than the bar's content box (the toggle has its own padding): centre the row itself,
       or it starts at the top of the box and everything sits low */
    align-content: center;
    padding-inline: var(--container-padding);
  }

  [data-header-bar] > .brand-2 {
    grid-column: 1 / 4;
    justify-self: start;
  }

  [data-header-bar] > .nav_text {
    grid-column: 4 / 8;
  }

  [data-header-bar] > .status-badge {
    grid-column: 8 / 10;
    justify-self: start;
  }

  /* The label, not the padded button, ends on the last line */
  [data-header-bar] > [data-underlay-nav-toggle] {
    grid-column: 12 / 13;
    justify-self: end;
    margin-right: -1em;
  }
}

@media screen and (max-width: 767px) {
  [data-header-bar] > .brand-2 {
    padding-left: 0;
  }
}

/* --- View switch ----------------------------------------------------------------------------
   A small optional tool, bottom-left on every page: Design, System, and × to put it away
   (remembered per browser). js/system-view.js. The page reads fully without it.              */
.view-switch {
  position: fixed;
  left: var(--about-pad);
  bottom: calc(1.2em + env(safe-area-inset-bottom, 0px));
  z-index: 2147483647; /* a tool, over everything: an open case, the navbar's blur. Later in the document than both. */
  display: flex;
  gap: 1px;
  align-items: center;
  padding: 2px;
  border: 1px solid var(--shell-rule);
  background-color: var(--sand);
  color: var(--dark-brown);
  font-size: calc(1em * var(--shell-k));
}

.view-switch[hidden] {
  display: none;
}

/* Until the script has read the stored choice, a dismissed switch must not flash */
.w-mod-js .view-switch:not(.is-ready) {
  visibility: hidden;
}

/* The menu slides the page aside: the switch belongs to the page, so it steps back */
body[data-menu-status="open"] .view-switch {
  opacity: 0;
  pointer-events: none;
}

.view-switch__btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.1em;
  height: 2.1em;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  transition:
    background-color var(--d-smooth) var(--e-smooth),
    color var(--d-smooth) var(--e-smooth);
}

.view-switch__btn:hover {
  background-color: color-mix(in srgb, var(--dark-brown) 8%, var(--sand));
}

.view-switch__btn svg {
  display: block;
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: currentcolor;
  stroke-width: 1.25;
}

.view-switch__btn svg .view-switch__fill {
  fill: currentcolor;
  stroke: none;
}

.view-switch__btn[aria-pressed="true"] {
  background-color: var(--dark-brown);
  color: var(--sand);
}

.view-switch__btn--system[aria-pressed="true"] {
  background-color: var(--main);
  color: var(--dark-brown);
}

.view-switch__btn--close {
  width: 1.7em;
  border-left: 1px solid color-mix(in srgb, var(--dark-brown) 14%, var(--sand));
  color: var(--light-stone);
}

.view-switch__btn--close svg {
  width: 0.9em;
  height: 0.9em;
}

/* Tip: names the icon on hover and on keyboard focus. None on touch. */
.view-switch__btn::after {
  content: attr(data-tip);
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.55em);
  padding: 0.3em 0.5em;
  background-color: var(--dark-brown);
  color: var(--sand);
  font-family: "Office Code Pro", monospace;
  font-size: max(10px, 0.95em);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(0.25em);
  pointer-events: none;
  transition:
    opacity var(--d-smooth) var(--e-smooth),
    transform var(--d-smooth) var(--e-smooth);
}

.view-switch__btn:hover::after,
.view-switch__btn:focus-visible::after {
  opacity: 1;
  transform: none;
}

@media (hover: none) {
  .view-switch__btn::after {
    display: none;
  }
}

/* Put away: the corner keeps a way back. An eye that only shows when the pointer comes near (or on keyboard
   focus); on touch screens, where nothing hovers, it stays as a faint mark. */
.view-restore {
  position: fixed;
  left: var(--about-pad);
  bottom: calc(1.2em + env(safe-area-inset-bottom, 0px));
  z-index: 2147483647;
  display: grid;
  place-items: center;
  width: 2.1em;
  height: 2.1em;
  min-width: 0;
  padding: 0;
  border: 1px solid var(--shell-rule);
  border-radius: 0;
  background-color: var(--sand);
  color: var(--dark-brown);
  font-size: calc(1em * var(--shell-k));
  opacity: 0;
  cursor: pointer;
  transition: opacity var(--d-smooth) var(--e-smooth);
}

/* Phones: no eye in the corner (it sat on the content). "Show me the workings" still opens the tool. */
@media screen and (max-width: 767px) {
  .view-restore {
    display: none;
  }
}

.view-restore[hidden] {
  display: none;
}

/* The zone that wakes it is bigger than the button */
.view-restore::before {
  content: "";
  position: absolute;
  inset: -2.4em -3.2em -1.2em -2em;
}

.view-restore svg {
  display: block;
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: currentcolor;
  stroke-width: 1.25;
}

.view-restore:hover,
.view-restore:focus-visible {
  opacity: 1;
}

@media (hover: none) {
  .view-restore {
    opacity: 0.4;
  }
}

body[data-menu-status="open"] .view-restore {
  display: none;
}

/* On phones the 2.1em icons would be 34px: give them a real tap target */
@media screen and (max-width: 767px) {
  .view-switch__btn::before {
    content: "";
    position: absolute;
    inset: -6px -2px;
  }
}

/* --- Page transition columns (js/transition.js) ----------------------------------------------------
   On the transition layer, which sits over everything. Side padding + 12 columns + side padding
   (6 on phones). Closed until a transition draws them.                                             */
.transition__cols {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns:
    var(--about-pad) repeat(var(--about-cols), minmax(0, 1fr))
    var(--about-pad);
}

/* Hidden while idle, not only clipped: iOS Safari tints its status and tool bars with the colour of fixed
   elements touching the edges, and these orange strips run the full height (js/transition.js shows them) */
.transition__cols {
  visibility: hidden;
}

.transition__cols.is-active {
  visibility: visible;
}

.transition__cols i {
  margin-right: -1px; /* no hairline of the page between two columns */
  background-color: var(--main);
  clip-path: inset(0 0 100% 0);
  border-right: 2px solid rgba(28, 25, 23, 0.1);
}

@media screen and (max-width: 767px) {
  .transition__cols i:nth-child(n + 8):not(:last-child) {
    display: none;
  }
}

/* --- Home intro (js/intro.js) ------------------------------------------------------------------
   Once per session on the Home: the first paint is orange columns on the grid, the transition's own. Under the
   transition layer, over everything else. Without html[data-intro] (or once it ends) the layer is gone. */
.intro {
  display: none;
}

html[data-intro] .intro {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 2147483646;
  pointer-events: none;
  overflow: clip;
}

/* The header bar sits at the top z-index too: below the intro while it plays */
html[data-intro] .navbar {
  z-index: 2147483645;
}

.intro__cols {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns:
    var(--about-pad) repeat(var(--about-cols), minmax(0, 1fr))
    var(--about-pad);
}

.intro__cols i {
  margin-right: -1px; /* no hairline of the page between two columns */
  background-color: var(--main);
  border-right: 2px solid rgba(28, 25, 23, 0.1);
  will-change: transform;
}

@media screen and (max-width: 767px) {
  .intro__cols i:nth-child(n + 8):not(:last-child) {
    display: none;
  }
}

.intro__ball,
.intro__shadow {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
}

.intro__ball {
  transform: translate3d(-999px, -999px, 0);
  transform-origin: 50% 100%;
}

.intro__ball img {
  display: block;
  width: 100%;
  height: 100%;
}

.intro__shadow {
  opacity: 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(28 25 23 / 34%), rgb(28 25 23 / 0%));
}

/* --- Line button ------------------------------------------------------------------------------
   The site's small button ("Show me the workings", "Back to work", and the ones to come): a mono label
   in a 1px outline. On hover and keyboard focus an orange fill wipes up from the bottom and the arrow, if
   there is one, nudges the way it points (the Contact page's "Send it" move). The text turns to ink on the
   orange, whatever the ground. Same everywhere; the surface only sets the resting colors. */
.line-btn {
  --line-btn-ink: var(--dark-brown);

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-self: start;
  padding: 0.75em 1.05em;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--line-btn-ink);
  border-radius: 0;
  background-color: transparent;
  color: var(--line-btn-ink);
  text-decoration: none;
  cursor: pointer;
}

[data-surface="dark"] .line-btn,
[data-page-tone="dark"] .line-btn {
  --line-btn-ink: var(--sand);
}

/* The fill wipes up on hover and keeps going up when the pointer leaves (it never drops back down):
   it grows from the bottom edge (origin bottom) and, on leave, the origin flips to the top edge so it
   shrinks away upwards. Only the scale is transitioned; the origin switches at once.
   Same pattern on .line-btn, .home-all and .case-next. */
.line-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--line-btn-fill, var(--main));
  transform: scaleY(0);
  transform-origin: 50% 0;
}

/* On a case page the fill is paper and the label takes the page's tone */
[data-page-tone="dark"] .line-btn {
  --line-btn-fill: var(--sand);
  --line-btn-hover-ink: var(--case-tone, var(--dark-brown));
  --line-btn-hover-border: var(--sand);
}

.line-btn__arrow {
  display: inline-block;
  margin-right: 0.6em;
}

/* a forward arrow (→) after the label */
.line-btn__arrow--end {
  order: 1;
  margin: -0.2em 0 0 0.6em;
}

.line-btn:focus-visible {
  border-color: var(--line-btn-hover-border, var(--main));
  color: var(--line-btn-hover-ink, var(--dark-brown));
}

.line-btn:focus-visible::before {
  transform: none;
  transform-origin: 50% 100%;
}

@media (hover: hover) and (pointer: fine) {
  .line-btn {
    transition:
      color var(--d-smooth) var(--e-smooth),
      border-color var(--d-smooth) var(--e-smooth);
  }

  .line-btn::before {
    transition: transform var(--d-smooth) var(--e-smooth);
  }

  .line-btn__arrow {
    transition: transform var(--d-smooth) var(--e-smooth);
  }

  .line-btn:hover {
    border-color: var(--line-btn-hover-border, var(--main));
    color: var(--line-btn-hover-ink, var(--dark-brown));
  }

  .line-btn:hover::before {
    transform: none;
    transform-origin: 50% 100%;
  }

  /* a back arrow (←) moves back */
  .line-btn:hover .line-btn__arrow {
    transform: translateX(-0.15em);
  }

  /* and a forward one moves forward */
  .line-btn:hover .line-btn__arrow--end {
    transform: translateX(0.15em);
  }
}

@media (prefers-reduced-motion: reduce) {
  .line-btn,
  .line-btn::before,
  .line-btn__arrow {
    transition: none;
  }

  .home-all::before,
  .case-next::before {
    transition: none !important;
  }
}

/* --- Hand-drawn underlines (images/underlines/underline-NN.svg, inlined) --------------------
   Filled shapes, not strokes: they keep their own proportions (height follows the width) and are drawn
   in the way a pen does, from the first point of the line to the last (js/underline.js). Pick one by length:
   01 / 02 long and light (phrases), 03 a long sweep, 04 short and dense (short words), 07 busy, 10 open. */
.mz-underline {
  position: absolute;
  z-index: -1;
  height: auto;
  overflow: visible;
  pointer-events: none;
}

.mz-underline > path {
  fill: var(--main);
  stroke: var(--main);
  stroke-width: var(--underline-weight, 0);
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* --- System view (js/system-view.js) ---------------------------------------------------------
   html[data-view="system"]: the column lines go orange, column numbers appear along the top,
   every [data-spec] gets a tag with its real type values and every [data-frame] an orange frame
   with its own spec. Overlays only: nothing moves.                                            */
/* System colours are tokens (docs/system-v2-spec.md §5). One orange everywhere (2026-10-20: the lighter one on dark
   surfaces looked like another brand); on dark surfaces its lines are more opaque, so they don't blend into mud. */
:root {
  --sys: var(--main);
  --sys-line: color-mix(in srgb, var(--main) 50%, transparent);
  --sys-hatch: color-mix(in srgb, var(--main) 16%, transparent);
  --sys-surface: var(--sand);
}

body[data-page-tone="dark"],
body[data-case-open],
.home-details,
.case-page,
.case-overlay {
  --sys: var(--main);
  --sys-line: color-mix(in srgb, var(--main) 62%, transparent);
  --sys-hatch: color-mix(in srgb, var(--main) 20%, transparent);
  --sys-surface: var(--case-tone, var(--dark-brown));
}

html[data-view="system"] {
  --about-line: var(--sys-line);
}

.transition__lines {
  transition: opacity var(--d-smooth) var(--e-smooth);
}

.transition__line {
  transition: border-color var(--d-smooth) var(--e-smooth);
}

/* html[data-sys-lines]: the column lines in their System colour. Separate from data-view so the scan
   (js/system.js) can light them up as its rule crosses them: copies (.sys-lines-copy) are revealed in step,
   and the lines themselves switch when it is done. Set at once when there is no scan. */
html[data-sys-lines] .transition__lines,
.transition__lines.sys-lines-copy {
  opacity: 1;
}

html[data-sys-lines] .transition__line,
html[data-sys-lines] .transition__line.is--first,
.sys-lines-copy .transition__line,
.sys-lines-copy .transition__line.is--first {
  border-color: var(--sys-line);
}

.sys-lines-copy {
  pointer-events: none;
}

.system-colnums {
  position: fixed;
  top: env(safe-area-inset-top, 0px);
  left: 0;
  right: 0;
  z-index: 2147483647; /* the navbar sits at the top of the stack with a solid ground on phones: the ruler goes over it */
  display: grid;
  grid-template-columns: repeat(var(--about-cols), minmax(0, 1fr));
  padding-inline: var(--about-pad);
  pointer-events: none;
}

/* The bar takes the colour of whatever is under it (js/system.js samples it on scroll) */
.system-colnums span {
  padding: 0.4em 0.5em;
  border-left: 1px solid var(--cn-fg, var(--sys));
  background-color: color-mix(in srgb, var(--cn-bg, var(--sand)) 90%, transparent);
  color: var(--cn-fg, var(--sys));
  opacity: 0;
}

@media screen and (max-width: 767px) {
  .system-colnums span:nth-child(n + 7) {
    display: none;
  }
}

[data-spec],
[data-frame] {
  position: relative;
}

/* A line of display type set with slots (home hero): its box shows in System view */
[data-line] {
  outline: 1px dashed transparent;
  outline-offset: 0.02em;
  transition: outline-color var(--d-smooth) var(--e-smooth);
}

html[data-view="system"] [data-line] {
  outline-color: color-mix(in srgb, var(--sys) 85%, transparent);
}

.system-spec {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 20;
  padding: 0.3em 0.5em;
  border: 1px solid var(--sys);
  background-color: var(--sys-surface);
  color: var(--sys);
  font-family: "Office Code Pro", monospace;
  font-size: max(10px, 0.85rem);
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: 0.03em;
  text-indent: 0;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  transform: translateY(calc(-100% - 0.4rem));
}

.system-frame {
  position: absolute;
  inset: 0;
  z-index: 6;
  border: 1px solid var(--sys);
  pointer-events: none;
}

.system-frame .system-spec {
  /* inside a frame the tag sits over the picture: it must stay readable and not leave the frame */
  top: 0.5rem;
  left: 0.5rem;
  max-width: calc(100% - 1rem);
  overflow: hidden;
  text-overflow: ellipsis;
  transform: none;
}

/* --- System view v2 (js/system.js): the scan and the inspector --------------------------------
   Every time and spring is in SYSTEM_MOTION (js/system.js); the motion here is driven from there.    */

/* The scan: a 1px rule sweeps the viewport top to bottom, its Y counting on the right */
.sys-scan {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 2147483646;
  height: 1px;
  background-color: var(--sys);
  opacity: 0;
  visibility: hidden; /* hidden, not only transparent: iOS Safari tints its bars from fixed elements at the edges */
  pointer-events: none;
}

.sys-scan span {
  position: absolute;
  right: var(--about-pad);
  bottom: 0.45em;
  color: var(--sys);
  font-variant-numeric: tabular-nums;
}

/* The inspector: one fixed layer that never takes a click. Box, tag and measurements are placed by the script. */
.sys-insp {
  position: fixed;
  inset: 0;
  z-index: 2147483645;
  display: none;
  pointer-events: none;
}

html.sys-live.has-insp .sys-insp {
  display: block;
}

/* One tag at a time: the inspector replaces "[ Open the case ]" (the pointer cursor stays) */
html.sys-live.has-insp [data-hover-tag] {
  visibility: hidden;
}

.sys-insp__box,
.sys-insp__anchor,
.sys-insp__pads {
  position: absolute;
  top: 0;
  left: 0;
}

.sys-insp__box,
.sys-insp__anchor {
  border: 1px solid var(--sys-ink);
}

.sys-insp__anchor {
  border-style: dashed;
}

.sys-insp__pad {
  position: absolute;
  background: repeating-linear-gradient(45deg, var(--sys-hatch-ink) 0 1px, transparent 1px 6px);
}

.sys-insp__tag {
  position: absolute;
  top: 0;
  left: 0;
  display: grid;
  gap: 0.2em;
  padding: 0.55em 0.7em 0.6em;
  border: 1px solid var(--sys-ink);
  background-color: var(--dark-brown);
  color: var(--sand);
  font-family: "Office Code Pro", monospace;
  font-size: max(10px, 0.82rem);
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  letter-spacing: 0.03em;
  white-space: nowrap;
  transform-origin: 0 100%;
}

.sys-insp__role {
  color: var(--sys-ink);
  text-transform: uppercase;
}

.sys-insp__ok {
  color: #7fd08f;
}

.sys-insp__off {
  color: var(--sys-ink);
}

.sys-insp__soft {
  color: color-mix(in srgb, var(--sand) 66%, transparent);
}

.sys-insp__dims {
  position: absolute;
  inset: 0;
}

.sys-insp__dim {
  position: absolute;
  background-color: var(--sys-ink);
  transform-origin: 0 0;
}

.sys-insp__dim--v {
  width: 1px;
}

.sys-insp__dim--h {
  height: 1px;
}

.sys-insp__dim::before,
.sys-insp__dim::after {
  content: "";
  position: absolute;
  background-color: var(--sys-ink);
}

.sys-insp__dim--v::before,
.sys-insp__dim--v::after {
  left: -3px;
  width: 7px;
  height: 1px;
}

.sys-insp__dim--v::before {
  top: 0;
}

.sys-insp__dim--v::after {
  bottom: 0;
}

.sys-insp__dim--h::before,
.sys-insp__dim--h::after {
  top: -3px;
  width: 1px;
  height: 7px;
}

.sys-insp__dim--h::before {
  left: 0;
}

.sys-insp__dim--h::after {
  right: 0;
}

/* Siblings of the lines, so they never stretch with them. Left of a vertical line: the tag owns the left. */
.sys-insp__label {
  position: absolute;
  padding: 0.15em 0.4em;
  background-color: var(--sys-ink);
  color: var(--dark-brown);
  font-family: "Office Code Pro", monospace;
  font-size: max(10px, 0.78rem);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.sys-insp__label--v {
  translate: -100% -50%;
}

.sys-insp__label--h {
  translate: -50% 0;
}

/* The inspector's ink follows the surface under the pointer (set by the script) */
.sys-insp {
  --sys-ink: var(--main);
  --sys-hatch-ink: color-mix(in srgb, var(--main) 22%, transparent);
}

.sys-insp.is-on-dark {
  --sys-ink: var(--main);
  --sys-hatch-ink: color-mix(in srgb, var(--main) 26%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .sys-scan {
    display: none;
  }
}

/* --- Bottom blur (js/bottom-blur.js) --------------------------------------------------------
   The gradient blur along the bottom edge. Off at the top of the page, it comes in as you start
   to scroll and goes again only at the very end of the page.
   The script drives --blur-k; without it the strip stays off.                                 */
[data-bottom-blur] {
  visibility: hidden;
}

/* The amount is the blur itself, scaled by --blur-k (0 to 1). Not opacity: a parent with opacity under 1
   becomes the backdrop of its children, and their backdrop-filter has nothing left to blur. */
[data-bottom-blur] .progressive-blur__layer.is--1 {
  -webkit-backdrop-filter: blur(calc(0.09375em * var(--blur-k, 0)));
  backdrop-filter: blur(calc(0.09375em * var(--blur-k, 0)));
}

[data-bottom-blur] .progressive-blur__layer.is--2 {
  -webkit-backdrop-filter: blur(calc(0.1875em * var(--blur-k, 0)));
  backdrop-filter: blur(calc(0.1875em * var(--blur-k, 0)));
}

[data-bottom-blur] .progressive-blur__layer.is--3 {
  -webkit-backdrop-filter: blur(calc(0.375em * var(--blur-k, 0)));
  backdrop-filter: blur(calc(0.375em * var(--blur-k, 0)));
}

[data-bottom-blur] .progressive-blur__layer.is--4 {
  -webkit-backdrop-filter: blur(calc(0.75em * var(--blur-k, 0)));
  backdrop-filter: blur(calc(0.75em * var(--blur-k, 0)));
}

[data-bottom-blur] .progressive-blur__layer.is--5 {
  -webkit-backdrop-filter: blur(calc(1.5em * var(--blur-k, 0)));
  backdrop-filter: blur(calc(1.5em * var(--blur-k, 0)));
}

body[data-menu-status="open"] [data-bottom-blur],
body[data-case-open] [data-bottom-blur] {
  display: none;
}

/* --- Hover tag (js/hover-tag.js) -------------------------------------------------------------
   A paper label beside the pointer over anything that opens a case. Mouse only.              */
[data-hover-case] {
  cursor: pointer;
}

.hover-tag {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 65;
  display: inline-flex;
  align-items: center;
  padding: 0.5em 0.7em;
  border: 1px solid var(--shell-rule);
  background-color: var(--sand);
  color: var(--dark-brown);
  box-shadow: 0 0.4em 1em color-mix(in srgb, var(--dark-brown) 12%, transparent);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transform-origin: 0 0;
}

@media (hover: none), (pointer: coarse) {
  .hover-tag {
    display: none;
  }
}

/* --- Footer (global): one footer, themed per page --------------------------------------------
   The footer is the same on every page. A page can change its colors with
   data-footer-theme on the [data-footer-parallax] wrapper: "dark", "orange" or "tone" (a deeper shade
   of the case page's --case-tone; default: paper).
   Only colors change: layout, copy and the falling shapes stay.                               */
.footer {
  --footer-bg: var(--sand);
  --footer-ink: var(--dark-brown);
}

.footer[data-footer-theme="dark"] {
  --footer-bg: var(--dark-brown);
  --footer-ink: var(--sand);
}

/* A case page: a deeper shade of the project's own tone (--case-tone, set on the page) */
.footer[data-footer-theme="tone"] {
  --footer-bg: color-mix(
    in srgb,
    var(--case-tone, var(--dark-brown)) 62%,
    #000
  );
  --footer-ink: var(--sand);
}

/* On a dark ground the last line of the headline takes the orange, as in the Webflow dark footer */
.footer[data-footer-theme="dark"] .ready_heading:last-child,
.footer[data-footer-theme="tone"] .ready_heading:last-child {
  color: var(--main);
}

.footer[data-footer-theme="orange"] {
  --footer-bg: var(--main);
  --footer-ink: var(--dark-brown);
}

.footer .animated-footer {
  background-color: var(--footer-bg);
  color: var(--footer-ink);
}

/* The headline is one sentence on three lines, not three headings: paragraphs, with the weight the h3s had */
p.ready_heading {
  font-weight: 700;
}

.footer .ready_heading,
.footer .demo-footer__a,
.footer .nav_text {
  color: var(--footer-ink);
}

/* The icons carry width and height so their row has its height before they load (lazy): without it the footer
   grew when they arrived, under the visitor's scroll. The CSS height wins; the width follows the ratio. */
.footer .icon_img {
  width: auto;
}

/* The social icons are orange files turned to ink by a filter: on a dark ground the same chain
   without the final invert gives the light version. Hover shows the orange original, as before. */
.footer[data-footer-theme="dark"] .link_icon:not(:hover),
.footer[data-footer-theme="tone"] .link_icon:not(:hover) {
  filter: hue-rotate(180deg) grayscale() brightness(200%) grayscale();
}

@media (prefers-reduced-motion: reduce) {
  .view-switch__btn,
  .view-restore,
  .view-switch__btn::after,
  .transition__lines,
  .transition__line,
  [data-line] {
    transition: none;
  }
}

/* --- Menu (js/menu.js) -----------------------------------------------------------------------
   The grid closes over the page: ink columns drop from the Menu column outward (the same gesture as the
   page transition, from the top), and an index sits on them: four links at Display size, numbered, ruled,
   a short line in mono at the right; at the left, status, email and elsewhere. Hover or focus moves a word
   one column right while its own hand-drawn line is drawn under it (js/underline.js); the current page keeps
   its line. Ink on every page; the header text turns to paper column by column as the columns pass over it
   (js/menu.js). docs/menu-wireframe.html is the prototype.              */
.menu {
  --menu-k: var(--shell-k, 1);
  /* The menu's own surface: ink (paper columns barely showed on the paper pages); a case wears its own tone */
  --menu-bg: var(--dark-brown);
  --menu-ink: var(--sand);
  --menu-muted: color-mix(in srgb, var(--sand) 66%, transparent);
  --menu-ghost: color-mix(in srgb, var(--sand) 28%, transparent);
  --menu-rule: color-mix(in srgb, var(--sand) 20%, transparent);
  --menu-line: color-mix(in srgb, var(--sand) 10%, transparent);
  --menu-slot: 2; /* columns the word moves aside, where its line is drawn */
  --home-label: 0.95em; /* the mono labels (status, write, elsewhere, the lines at the right) */

  position: fixed;
  inset: 0;
  z-index: 44; /* under the header bar (45), over the page */
  color: var(--menu-ink);
  font-size: calc(1em * var(--menu-k));
}

/* On a case page the menu wears the case: the deeper shade of its tone, as the case footer does */
body[data-page-tone="dark"] .menu {
  --menu-bg: color-mix(in srgb, var(--page-tone-bg, var(--dark-brown)) 62%, #000);
}

.menu[hidden] {
  display: none;
}

.menu__band {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: var(--menu-top, 72px);
  background-color: var(--sand);
}

body[data-page-tone="dark"] .menu__band {
  background-color: var(--page-tone-bg, var(--dark-brown));
}

.menu__cols {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: var(--about-pad) repeat(var(--about-cols), minmax(0, 1fr)) var(--about-pad);
}

.menu__cols i {
  margin-right: -1px; /* no hairline of the page between two columns (subpixel seams) */
  background-color: var(--menu-bg);
  transform: scaleY(0);
  transform-origin: 50% 0;
}

/* The grid stays visible on the paper: a hairline on each column's left edge, and the last one's right */
.menu__cols i + i {
  box-shadow: inset 1px 0 0 var(--menu-line);
}

.menu__in {
  position: absolute;
  inset: var(--menu-top, 72px) var(--about-pad) 0;
  display: grid;
  grid-template-columns: repeat(var(--about-cols), minmax(0, 1fr));
  grid-template-rows: 1fr;
  padding: 5vh 0 3vh;
}

.menu__list {
  grid-column: 4 / 13;
  grid-row: 1;
  align-self: center;
  margin: 0;
  padding: 0;
  list-style: none;
}

.menu__row {
  position: relative;
}

.menu__row::before,
.menu__row:last-child::after {
  content: "";
  position: absolute;
  right: 0;
  left: 0;
  height: 1px;
  background-color: var(--menu-rule);
  transform: scaleX(var(--rule, 1));
  transform-origin: 0 50%;
}

.menu__row::before {
  top: 0;
}

.menu__row:last-child::after {
  bottom: 0;
}

.menu__link {
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
  align-items: baseline;
  padding: 0.2em 0 0.45em;
  color: inherit;
  text-decoration: none;
}

.menu__link:focus-visible {
  outline: none; /* focus is shown the way hover is: the word moves and draws its line */
}


.menu__word {
  grid-column: 1 / 9;
  min-width: 0;
  font-size: 8.4em;
  font-weight: 500;
  line-height: 0.92;
  letter-spacing: -0.055em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* The word rises from this mask */
.menu__mask {
  position: relative;
  display: block;
  overflow: hidden;
  margin: -0.08em -0.12em 0 -0.05em; /* room for the tracking and the accents, taken back */
  padding: 0.08em 0.12em 0.06em 0.05em;
}

.menu__text {
  position: relative;
  display: inline-block;
  transition: color var(--d-smooth) var(--e-smooth);
}

.menu.is-pointing .menu__row:not(.is-on) .menu__text {
  color: var(--menu-ghost);
}

/* The slot the word leaves when it moves aside: its own hand-drawn line is drawn there, across the columns */
.menu__stroke {
  position: absolute;
  top: 0;
  bottom: 0.06em;
  left: 0;
  width: calc(var(--menu-slot) * var(--about-col) / var(--menu-k) - 0.25em);
  display: flex;
  align-items: center;
  pointer-events: none;
}

.menu__stroke {
  --underline-weight: 2px; /* the strokes are drawn for words; at this length they need a little more body */
}

.menu__stroke .mz-underline > path {
  fill: var(--main);
  stroke: var(--main);
}

.menu__stroke .mz-underline {
  position: relative;
  z-index: auto; /* the shared rule puts underlines behind their text; here there is no text to sit under */
  width: 100%;
  height: auto;
  max-height: 0.5em;
}

.menu__say {
  grid-column: 9 / 10;
  justify-self: end;
  align-self: end;
  padding-bottom: 1.2em;
  color: var(--menu-muted);
  text-align: right;
}

.menu__meta {
  grid-column: 1 / 4;
  grid-row: 1;
  display: grid;
  align-content: space-between;
  padding-right: 1.5em;
}

.menu__facts {
  display: grid;
  gap: 1.6em;
  margin: 0;
}

.menu__facts dt {
  margin-bottom: 0.3em;
  color: var(--menu-muted);
}

/* The values are set like the Contact page's: Saans, 1.5em, tight; the titles above them stay mono */
.menu__facts dd {
  margin: 0;
  font-size: 1.5em;
  line-height: 1.2;
  letter-spacing: -0.03em;
}

.menu__facts a {
  color: inherit;
  text-decoration: none;
}

.menu__socials {
  display: grid;
  justify-items: start;
  gap: 0.2em;
}

.menu__copy {
  margin: 0;
}

.menu :where(a):focus-visible .menu__text,
.menu__facts a:focus-visible {
  outline: 2px solid var(--main);
  outline-offset: 0.08em;
}

@media screen and (min-width: 768px) and (max-width: 991px) {
  .menu__list {
    grid-column: 1 / 13;
  }

  .menu {
    --home-label: 0.78em;
  }

  /* "Contact" (4.3 of its em) fills about half the width, with room to move two columns aside */
  .menu__word {
    font-size: calc(6 * var(--about-col) / 4.3);
  }

  .menu__meta {
    grid-column: 1 / 13;
    grid-row: 2;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    align-items: end;
    padding: 0;
  }

  .menu__facts {
    grid-column: 1 / 10;
    grid-template-columns: repeat(2, 1fr);
    gap: 1em;
  }

  .menu__copy {
    grid-column: 10 / 13;
    justify-self: end;
  }

  .menu__in {
    grid-template-rows: 1fr auto;
  }
}

@media screen and (max-width: 767px) {
  .menu__in {
    grid-template-rows: 1fr auto;
    padding: 3vh 0 2.5vh;
  }

  .menu__list {
    grid-column: 1 / 7;
    align-self: start;
    margin-top: 3vh;
  }

  .menu__link {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }


  /* "Contact" (4.3 of its em) fills five of the six columns: the sixth is the slot it moves into */
  .menu__word {
    grid-column: 1 / 7;
    font-size: calc(5 * var(--about-col) / 4.3);
  }

  .menu__say {
    display: none;
  }

  .menu {
    --menu-slot: 1;
    --home-label: 0.72em;
  }

  .menu__meta {
    grid-column: 1 / 7;
    grid-row: 2;
    grid-template-columns: 1fr 1fr;
    gap: 1.4em 1em;
    padding: 0;
  }

  .menu__facts {
    grid-column: 1 / 7;
    grid-template-columns: 1fr 1fr;
    gap: 1.4em 1em;
    align-items: start;
  }

  /* 20px, as on the Contact page */
  .menu__facts dd {
    font-size: 1.25em;
  }

  .menu__copy {
    display: none;
  }
}

/* While the menu shows, the header bar is clear and its own colour is painted by the menu instead, on a band
   under the columns (.menu__band): the columns drop over it one by one, so the header changes colour with them,
   column by column, never all at once. */
/* Each header item turns to paper when the column under it has covered the bar (js/menu.js), and back */
[data-header-bar] .is-menu-ink,
[data-header-bar] .is-menu-ink * {
  color: var(--sand);
}

[data-header-bar] .is-menu-ink .logo {
  filter: invert(1);
}

body[data-menu-shown] [data-header-bar] {
  background-color: transparent !important;
  background-image: none !important;
}

/* The Menu / Close label rolling over itself on hover (js/menu.js): each label clips its own copy, one line below */
.underlay-nav__toggle-label {
  display: block;
  flex: none; /* clipped, a flex item could shrink: each keeps its full line */
  overflow: hidden;
}

.underlay-nav__toggle-roll {
  position: relative;
  display: block;
}

.underlay-nav__toggle-roll::after {
  content: attr(data-text);
  position: absolute;
  top: 100%;
  left: 0;
}

/* The strip iOS 26 reads the colour of its top bar from (js/chrome.js). 3px, full width, above the page and
   under the intro and the transition, in the colour of the surface at the top edge, so it is never seen. */
.chrome-edge {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 2147483644;
  height: 3px;
  pointer-events: none;
}

/* --- Tap targets -------------------------------------------------------------------------------------------
   Small text links and buttons get a 44px-tall hit area from padding, taken back with an equal negative margin
   so nothing moves. (Phones and tablets; a mouse is precise enough, and the hover shapes stay as drawn.) */
@media (pointer: coarse), (max-width: 991px) {
  .w-nav-brand,
  .demo-footer__a,
  .contact__value,
  .home-details__back,
  .menu__facts a {
    padding-block: 0.8em;
    margin-block: -0.8em;
  }

  .w-nav-brand {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-block: 0;
    margin-block: 0;
  }

  /* these two set their own padding with more weight */
  .home-label.home-details__back,
  button.contact__value.contact__email {
    padding-block: 0.8em;
    margin-block: -0.8em;
  }
}
